View.java revision 9bafa1786948ea7b98b6b075c4b9a0de6a443d25
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 android.animation.AnimatorInflater;
20import android.animation.StateListAnimator;
21import android.annotation.CallSuper;
22import android.annotation.ColorInt;
23import android.annotation.DrawableRes;
24import android.annotation.FloatRange;
25import android.annotation.IdRes;
26import android.annotation.IntDef;
27import android.annotation.IntRange;
28import android.annotation.LayoutRes;
29import android.annotation.NonNull;
30import android.annotation.Nullable;
31import android.annotation.Size;
32import android.annotation.UiThread;
33import android.content.ClipData;
34import android.content.Context;
35import android.content.ContextWrapper;
36import android.content.Intent;
37import android.content.res.ColorStateList;
38import android.content.res.Configuration;
39import android.content.res.Resources;
40import android.content.res.TypedArray;
41import android.graphics.Bitmap;
42import android.graphics.Canvas;
43import android.graphics.Color;
44import android.graphics.Insets;
45import android.graphics.Interpolator;
46import android.graphics.LinearGradient;
47import android.graphics.Matrix;
48import android.graphics.Outline;
49import android.graphics.Paint;
50import android.graphics.PixelFormat;
51import android.graphics.Point;
52import android.graphics.PorterDuff;
53import android.graphics.PorterDuffXfermode;
54import android.graphics.Rect;
55import android.graphics.RectF;
56import android.graphics.Region;
57import android.graphics.Shader;
58import android.graphics.drawable.ColorDrawable;
59import android.graphics.drawable.Drawable;
60import android.hardware.display.DisplayManagerGlobal;
61import android.os.Build.VERSION_CODES;
62import android.os.Bundle;
63import android.os.Handler;
64import android.os.IBinder;
65import android.os.Parcel;
66import android.os.Parcelable;
67import android.os.RemoteException;
68import android.os.SystemClock;
69import android.os.SystemProperties;
70import android.os.Trace;
71import android.text.TextUtils;
72import android.util.AttributeSet;
73import android.util.FloatProperty;
74import android.util.LayoutDirection;
75import android.util.Log;
76import android.util.LongSparseLongArray;
77import android.util.Pools.SynchronizedPool;
78import android.util.Property;
79import android.util.SparseArray;
80import android.util.StateSet;
81import android.util.SuperNotCalledException;
82import android.util.TypedValue;
83import android.view.ContextMenu.ContextMenuInfo;
84import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
85import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
86import android.view.AccessibilityIterators.TextSegmentIterator;
87import android.view.AccessibilityIterators.WordTextSegmentIterator;
88import android.view.accessibility.AccessibilityEvent;
89import android.view.accessibility.AccessibilityEventSource;
90import android.view.accessibility.AccessibilityManager;
91import android.view.accessibility.AccessibilityNodeInfo;
92import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
93import android.view.accessibility.AccessibilityNodeProvider;
94import android.view.animation.Animation;
95import android.view.animation.AnimationUtils;
96import android.view.animation.Transformation;
97import android.view.inputmethod.EditorInfo;
98import android.view.inputmethod.InputConnection;
99import android.view.inputmethod.InputMethodManager;
100import android.widget.Checkable;
101import android.widget.FrameLayout;
102import android.widget.ScrollBarDrawable;
103import static android.os.Build.VERSION_CODES.*;
104import static java.lang.Math.max;
105
106import com.android.internal.R;
107import com.android.internal.util.Predicate;
108import com.android.internal.view.menu.MenuBuilder;
109import com.android.internal.widget.ScrollBarUtils;
110import com.google.android.collect.Lists;
111import com.google.android.collect.Maps;
112
113import java.lang.NullPointerException;
114import java.lang.annotation.Retention;
115import java.lang.annotation.RetentionPolicy;
116import java.lang.ref.WeakReference;
117import java.lang.reflect.Field;
118import java.lang.reflect.InvocationTargetException;
119import java.lang.reflect.Method;
120import java.lang.reflect.Modifier;
121import java.util.ArrayList;
122import java.util.Arrays;
123import java.util.Collections;
124import java.util.HashMap;
125import java.util.List;
126import java.util.Locale;
127import java.util.Map;
128import java.util.concurrent.CopyOnWriteArrayList;
129import java.util.concurrent.atomic.AtomicInteger;
130
131/**
132 * <p>
133 * This class represents the basic building block for user interface components. A View
134 * occupies a rectangular area on the screen and is responsible for drawing and
135 * event handling. View is the base class for <em>widgets</em>, which are
136 * used to create interactive UI components (buttons, text fields, etc.). The
137 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
138 * are invisible containers that hold other Views (or other ViewGroups) and define
139 * their layout properties.
140 * </p>
141 *
142 * <div class="special reference">
143 * <h3>Developer Guides</h3>
144 * <p>For information about using this class to develop your application's user interface,
145 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
146 * </div>
147 *
148 * <a name="Using"></a>
149 * <h3>Using Views</h3>
150 * <p>
151 * All of the views in a window are arranged in a single tree. You can add views
152 * either from code or by specifying a tree of views in one or more XML layout
153 * files. There are many specialized subclasses of views that act as controls or
154 * are capable of displaying text, images, or other content.
155 * </p>
156 * <p>
157 * Once you have created a tree of views, there are typically a few types of
158 * common operations you may wish to perform:
159 * <ul>
160 * <li><strong>Set properties:</strong> for example setting the text of a
161 * {@link android.widget.TextView}. The available properties and the methods
162 * that set them will vary among the different subclasses of views. Note that
163 * properties that are known at build time can be set in the XML layout
164 * files.</li>
165 * <li><strong>Set focus:</strong> The framework will handle moving focus in
166 * response to user input. To force focus to a specific view, call
167 * {@link #requestFocus}.</li>
168 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
169 * that will be notified when something interesting happens to the view. For
170 * example, all views will let you set a listener to be notified when the view
171 * gains or loses focus. You can register such a listener using
172 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
173 * Other view subclasses offer more specialized listeners. For example, a Button
174 * exposes a listener to notify clients when the button is clicked.</li>
175 * <li><strong>Set visibility:</strong> You can hide or show views using
176 * {@link #setVisibility(int)}.</li>
177 * </ul>
178 * </p>
179 * <p><em>
180 * Note: The Android framework is responsible for measuring, laying out and
181 * drawing views. You should not call methods that perform these actions on
182 * views yourself unless you are actually implementing a
183 * {@link android.view.ViewGroup}.
184 * </em></p>
185 *
186 * <a name="Lifecycle"></a>
187 * <h3>Implementing a Custom View</h3>
188 *
189 * <p>
190 * To implement a custom view, you will usually begin by providing overrides for
191 * some of the standard methods that the framework calls on all views. You do
192 * not need to override all of these methods. In fact, you can start by just
193 * overriding {@link #onDraw(android.graphics.Canvas)}.
194 * <table border="2" width="85%" align="center" cellpadding="5">
195 *     <thead>
196 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
197 *     </thead>
198 *
199 *     <tbody>
200 *     <tr>
201 *         <td rowspan="2">Creation</td>
202 *         <td>Constructors</td>
203 *         <td>There is a form of the constructor that are called when the view
204 *         is created from code and a form that is called when the view is
205 *         inflated from a layout file. The second form should parse and apply
206 *         any attributes defined in the layout file.
207 *         </td>
208 *     </tr>
209 *     <tr>
210 *         <td><code>{@link #onFinishInflate()}</code></td>
211 *         <td>Called after a view and all of its children has been inflated
212 *         from XML.</td>
213 *     </tr>
214 *
215 *     <tr>
216 *         <td rowspan="3">Layout</td>
217 *         <td><code>{@link #onMeasure(int, int)}</code></td>
218 *         <td>Called to determine the size requirements for this view and all
219 *         of its children.
220 *         </td>
221 *     </tr>
222 *     <tr>
223 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
224 *         <td>Called when this view should assign a size and position to all
225 *         of its children.
226 *         </td>
227 *     </tr>
228 *     <tr>
229 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
230 *         <td>Called when the size of this view has changed.
231 *         </td>
232 *     </tr>
233 *
234 *     <tr>
235 *         <td>Drawing</td>
236 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
237 *         <td>Called when the view should render its content.
238 *         </td>
239 *     </tr>
240 *
241 *     <tr>
242 *         <td rowspan="4">Event processing</td>
243 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
244 *         <td>Called when a new hardware key event occurs.
245 *         </td>
246 *     </tr>
247 *     <tr>
248 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
249 *         <td>Called when a hardware key up event occurs.
250 *         </td>
251 *     </tr>
252 *     <tr>
253 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
254 *         <td>Called when a trackball motion event occurs.
255 *         </td>
256 *     </tr>
257 *     <tr>
258 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
259 *         <td>Called when a touch screen motion event occurs.
260 *         </td>
261 *     </tr>
262 *
263 *     <tr>
264 *         <td rowspan="2">Focus</td>
265 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
266 *         <td>Called when the view gains or loses focus.
267 *         </td>
268 *     </tr>
269 *
270 *     <tr>
271 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
272 *         <td>Called when the window containing the view gains or loses focus.
273 *         </td>
274 *     </tr>
275 *
276 *     <tr>
277 *         <td rowspan="3">Attaching</td>
278 *         <td><code>{@link #onAttachedToWindow()}</code></td>
279 *         <td>Called when the view is attached to a window.
280 *         </td>
281 *     </tr>
282 *
283 *     <tr>
284 *         <td><code>{@link #onDetachedFromWindow}</code></td>
285 *         <td>Called when the view is detached from its window.
286 *         </td>
287 *     </tr>
288 *
289 *     <tr>
290 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
291 *         <td>Called when the visibility of the window containing the view
292 *         has changed.
293 *         </td>
294 *     </tr>
295 *     </tbody>
296 *
297 * </table>
298 * </p>
299 *
300 * <a name="IDs"></a>
301 * <h3>IDs</h3>
302 * Views may have an integer id associated with them. These ids are typically
303 * assigned in the layout XML files, and are used to find specific views within
304 * the view tree. A common pattern is to:
305 * <ul>
306 * <li>Define a Button in the layout file and assign it a unique ID.
307 * <pre>
308 * &lt;Button
309 *     android:id="@+id/my_button"
310 *     android:layout_width="wrap_content"
311 *     android:layout_height="wrap_content"
312 *     android:text="@string/my_button_text"/&gt;
313 * </pre></li>
314 * <li>From the onCreate method of an Activity, find the Button
315 * <pre class="prettyprint">
316 *      Button myButton = (Button) findViewById(R.id.my_button);
317 * </pre></li>
318 * </ul>
319 * <p>
320 * View IDs need not be unique throughout the tree, but it is good practice to
321 * ensure that they are at least unique within the part of the tree you are
322 * searching.
323 * </p>
324 *
325 * <a name="Position"></a>
326 * <h3>Position</h3>
327 * <p>
328 * The geometry of a view is that of a rectangle. A view has a location,
329 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
330 * two dimensions, expressed as a width and a height. The unit for location
331 * and dimensions is the pixel.
332 * </p>
333 *
334 * <p>
335 * It is possible to retrieve the location of a view by invoking the methods
336 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
337 * coordinate of the rectangle representing the view. The latter returns the
338 * top, or Y, coordinate of the rectangle representing the view. These methods
339 * both return the location of the view relative to its parent. For instance,
340 * when getLeft() returns 20, that means the view is located 20 pixels to the
341 * right of the left edge of its direct parent.
342 * </p>
343 *
344 * <p>
345 * In addition, several convenience methods are offered to avoid unnecessary
346 * computations, namely {@link #getRight()} and {@link #getBottom()}.
347 * These methods return the coordinates of the right and bottom edges of the
348 * rectangle representing the view. For instance, calling {@link #getRight()}
349 * is similar to the following computation: <code>getLeft() + getWidth()</code>
350 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
351 * </p>
352 *
353 * <a name="SizePaddingMargins"></a>
354 * <h3>Size, padding and margins</h3>
355 * <p>
356 * The size of a view is expressed with a width and a height. A view actually
357 * possess two pairs of width and height values.
358 * </p>
359 *
360 * <p>
361 * The first pair is known as <em>measured width</em> and
362 * <em>measured height</em>. These dimensions define how big a view wants to be
363 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
364 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
365 * and {@link #getMeasuredHeight()}.
366 * </p>
367 *
368 * <p>
369 * The second pair is simply known as <em>width</em> and <em>height</em>, or
370 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
371 * dimensions define the actual size of the view on screen, at drawing time and
372 * after layout. These values may, but do not have to, be different from the
373 * measured width and height. The width and height can be obtained by calling
374 * {@link #getWidth()} and {@link #getHeight()}.
375 * </p>
376 *
377 * <p>
378 * To measure its dimensions, a view takes into account its padding. The padding
379 * is expressed in pixels for the left, top, right and bottom parts of the view.
380 * Padding can be used to offset the content of the view by a specific amount of
381 * pixels. For instance, a left padding of 2 will push the view's content by
382 * 2 pixels to the right of the left edge. Padding can be set using the
383 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
384 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
385 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
386 * {@link #getPaddingEnd()}.
387 * </p>
388 *
389 * <p>
390 * Even though a view can define a padding, it does not provide any support for
391 * margins. However, view groups provide such a support. Refer to
392 * {@link android.view.ViewGroup} and
393 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
394 * </p>
395 *
396 * <a name="Layout"></a>
397 * <h3>Layout</h3>
398 * <p>
399 * Layout is a two pass process: a measure pass and a layout pass. The measuring
400 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
401 * of the view tree. Each view pushes dimension specifications down the tree
402 * during the recursion. At the end of the measure pass, every view has stored
403 * its measurements. The second pass happens in
404 * {@link #layout(int,int,int,int)} and is also top-down. During
405 * this pass each parent is responsible for positioning all of its children
406 * using the sizes computed in the measure pass.
407 * </p>
408 *
409 * <p>
410 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
411 * {@link #getMeasuredHeight()} values must be set, along with those for all of
412 * that view's descendants. A view's measured width and measured height values
413 * must respect the constraints imposed by the view's parents. This guarantees
414 * that at the end of the measure pass, all parents accept all of their
415 * children's measurements. A parent view may call measure() more than once on
416 * its children. For example, the parent may measure each child once with
417 * unspecified dimensions to find out how big they want to be, then call
418 * measure() on them again with actual numbers if the sum of all the children's
419 * unconstrained sizes is too big or too small.
420 * </p>
421 *
422 * <p>
423 * The measure pass uses two classes to communicate dimensions. The
424 * {@link MeasureSpec} class is used by views to tell their parents how they
425 * want to be measured and positioned. The base LayoutParams class just
426 * describes how big the view wants to be for both width and height. For each
427 * dimension, it can specify one of:
428 * <ul>
429 * <li> an exact number
430 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
431 * (minus padding)
432 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
433 * enclose its content (plus padding).
434 * </ul>
435 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
436 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
437 * an X and Y value.
438 * </p>
439 *
440 * <p>
441 * MeasureSpecs are used to push requirements down the tree from parent to
442 * child. A MeasureSpec can be in one of three modes:
443 * <ul>
444 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
445 * of a child view. For example, a LinearLayout may call measure() on its child
446 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
447 * tall the child view wants to be given a width of 240 pixels.
448 * <li>EXACTLY: This is used by the parent to impose an exact size on the
449 * child. The child must use this size, and guarantee that all of its
450 * descendants will fit within this size.
451 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
452 * child. The child must guarantee that it and all of its descendants will fit
453 * within this size.
454 * </ul>
455 * </p>
456 *
457 * <p>
458 * To initiate a layout, call {@link #requestLayout}. This method is typically
459 * called by a view on itself when it believes that is can no longer fit within
460 * its current bounds.
461 * </p>
462 *
463 * <a name="Drawing"></a>
464 * <h3>Drawing</h3>
465 * <p>
466 * Drawing is handled by walking the tree and recording the drawing commands of
467 * any View that needs to update. After this, the drawing commands of the
468 * entire tree are issued to screen, clipped to the newly damaged area.
469 * </p>
470 *
471 * <p>
472 * The tree is largely recorded and drawn in order, with parents drawn before
473 * (i.e., behind) their children, with siblings drawn in the order they appear
474 * in the tree. If you set a background drawable for a View, then the View will
475 * draw it before calling back to its <code>onDraw()</code> method. The child
476 * drawing order can be overridden with
477 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
478 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
479 * </p>
480 *
481 * <p>
482 * To force a view to draw, call {@link #invalidate()}.
483 * </p>
484 *
485 * <a name="EventHandlingThreading"></a>
486 * <h3>Event Handling and Threading</h3>
487 * <p>
488 * The basic cycle of a view is as follows:
489 * <ol>
490 * <li>An event comes in and is dispatched to the appropriate view. The view
491 * handles the event and notifies any listeners.</li>
492 * <li>If in the course of processing the event, the view's bounds may need
493 * to be changed, the view will call {@link #requestLayout()}.</li>
494 * <li>Similarly, if in the course of processing the event the view's appearance
495 * may need to be changed, the view will call {@link #invalidate()}.</li>
496 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
497 * the framework will take care of measuring, laying out, and drawing the tree
498 * as appropriate.</li>
499 * </ol>
500 * </p>
501 *
502 * <p><em>Note: The entire view tree is single threaded. You must always be on
503 * the UI thread when calling any method on any view.</em>
504 * If you are doing work on other threads and want to update the state of a view
505 * from that thread, you should use a {@link Handler}.
506 * </p>
507 *
508 * <a name="FocusHandling"></a>
509 * <h3>Focus Handling</h3>
510 * <p>
511 * The framework will handle routine focus movement in response to user input.
512 * This includes changing the focus as views are removed or hidden, or as new
513 * views become available. Views indicate their willingness to take focus
514 * through the {@link #isFocusable} method. To change whether a view can take
515 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
516 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
517 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
518 * </p>
519 * <p>
520 * Focus movement is based on an algorithm which finds the nearest neighbor in a
521 * given direction. In rare cases, the default algorithm may not match the
522 * intended behavior of the developer. In these situations, you can provide
523 * explicit overrides by using these XML attributes in the layout file:
524 * <pre>
525 * nextFocusDown
526 * nextFocusLeft
527 * nextFocusRight
528 * nextFocusUp
529 * </pre>
530 * </p>
531 *
532 *
533 * <p>
534 * To get a particular view to take focus, call {@link #requestFocus()}.
535 * </p>
536 *
537 * <a name="TouchMode"></a>
538 * <h3>Touch Mode</h3>
539 * <p>
540 * When a user is navigating a user interface via directional keys such as a D-pad, it is
541 * necessary to give focus to actionable items such as buttons so the user can see
542 * what will take input.  If the device has touch capabilities, however, and the user
543 * begins interacting with the interface by touching it, it is no longer necessary to
544 * always highlight, or give focus to, a particular view.  This motivates a mode
545 * for interaction named 'touch mode'.
546 * </p>
547 * <p>
548 * For a touch capable device, once the user touches the screen, the device
549 * will enter touch mode.  From this point onward, only views for which
550 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
551 * Other views that are touchable, like buttons, will not take focus when touched; they will
552 * only fire the on click listeners.
553 * </p>
554 * <p>
555 * Any time a user hits a directional key, such as a D-pad direction, the view device will
556 * exit touch mode, and find a view to take focus, so that the user may resume interacting
557 * with the user interface without touching the screen again.
558 * </p>
559 * <p>
560 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
561 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
562 * </p>
563 *
564 * <a name="Scrolling"></a>
565 * <h3>Scrolling</h3>
566 * <p>
567 * The framework provides basic support for views that wish to internally
568 * scroll their content. This includes keeping track of the X and Y scroll
569 * offset as well as mechanisms for drawing scrollbars. See
570 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
571 * {@link #awakenScrollBars()} for more details.
572 * </p>
573 *
574 * <a name="Tags"></a>
575 * <h3>Tags</h3>
576 * <p>
577 * Unlike IDs, tags are not used to identify views. Tags are essentially an
578 * extra piece of information that can be associated with a view. They are most
579 * often used as a convenience to store data related to views in the views
580 * themselves rather than by putting them in a separate structure.
581 * </p>
582 * <p>
583 * Tags may be specified with character sequence values in layout XML as either
584 * a single tag using the {@link android.R.styleable#View_tag android:tag}
585 * attribute or multiple tags using the {@code <tag>} child element:
586 * <pre>
587 *     &ltView ...
588 *           android:tag="@string/mytag_value" /&gt;
589 *     &ltView ...&gt;
590 *         &lttag android:id="@+id/mytag"
591 *              android:value="@string/mytag_value" /&gt;
592 *     &lt/View>
593 * </pre>
594 * </p>
595 * <p>
596 * Tags may also be specified with arbitrary objects from code using
597 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
598 * </p>
599 *
600 * <a name="Themes"></a>
601 * <h3>Themes</h3>
602 * <p>
603 * By default, Views are created using the theme of the Context object supplied
604 * to their constructor; however, a different theme may be specified by using
605 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
606 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
607 * code.
608 * </p>
609 * <p>
610 * When the {@link android.R.styleable#View_theme android:theme} attribute is
611 * used in XML, the specified theme is applied on top of the inflation
612 * context's theme (see {@link LayoutInflater}) and used for the view itself as
613 * well as any child elements.
614 * </p>
615 * <p>
616 * In the following example, both views will be created using the Material dark
617 * color scheme; however, because an overlay theme is used which only defines a
618 * subset of attributes, the value of
619 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
620 * the inflation context's theme (e.g. the Activity theme) will be preserved.
621 * <pre>
622 *     &ltLinearLayout
623 *             ...
624 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
625 *         &ltView ...&gt;
626 *     &lt/LinearLayout&gt;
627 * </pre>
628 * </p>
629 *
630 * <a name="Properties"></a>
631 * <h3>Properties</h3>
632 * <p>
633 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
634 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
635 * available both in the {@link Property} form as well as in similarly-named setter/getter
636 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
637 * be used to set persistent state associated with these rendering-related properties on the view.
638 * The properties and methods can also be used in conjunction with
639 * {@link android.animation.Animator Animator}-based animations, described more in the
640 * <a href="#Animation">Animation</a> section.
641 * </p>
642 *
643 * <a name="Animation"></a>
644 * <h3>Animation</h3>
645 * <p>
646 * Starting with Android 3.0, the preferred way of animating views is to use the
647 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
648 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
649 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
650 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
651 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
652 * makes animating these View properties particularly easy and efficient.
653 * </p>
654 * <p>
655 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
656 * You can attach an {@link Animation} object to a view using
657 * {@link #setAnimation(Animation)} or
658 * {@link #startAnimation(Animation)}. The animation can alter the scale,
659 * rotation, translation and alpha of a view over time. If the animation is
660 * attached to a view that has children, the animation will affect the entire
661 * subtree rooted by that node. When an animation is started, the framework will
662 * take care of redrawing the appropriate views until the animation completes.
663 * </p>
664 *
665 * <a name="Security"></a>
666 * <h3>Security</h3>
667 * <p>
668 * Sometimes it is essential that an application be able to verify that an action
669 * is being performed with the full knowledge and consent of the user, such as
670 * granting a permission request, making a purchase or clicking on an advertisement.
671 * Unfortunately, a malicious application could try to spoof the user into
672 * performing these actions, unaware, by concealing the intended purpose of the view.
673 * As a remedy, the framework offers a touch filtering mechanism that can be used to
674 * improve the security of views that provide access to sensitive functionality.
675 * </p><p>
676 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
677 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
678 * will discard touches that are received whenever the view's window is obscured by
679 * another visible window.  As a result, the view will not receive touches whenever a
680 * toast, dialog or other window appears above the view's window.
681 * </p><p>
682 * For more fine-grained control over security, consider overriding the
683 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
684 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
685 * </p>
686 *
687 * @attr ref android.R.styleable#View_alpha
688 * @attr ref android.R.styleable#View_background
689 * @attr ref android.R.styleable#View_clickable
690 * @attr ref android.R.styleable#View_contentDescription
691 * @attr ref android.R.styleable#View_drawingCacheQuality
692 * @attr ref android.R.styleable#View_duplicateParentState
693 * @attr ref android.R.styleable#View_id
694 * @attr ref android.R.styleable#View_requiresFadingEdge
695 * @attr ref android.R.styleable#View_fadeScrollbars
696 * @attr ref android.R.styleable#View_fadingEdgeLength
697 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
698 * @attr ref android.R.styleable#View_fitsSystemWindows
699 * @attr ref android.R.styleable#View_isScrollContainer
700 * @attr ref android.R.styleable#View_focusable
701 * @attr ref android.R.styleable#View_focusableInTouchMode
702 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
703 * @attr ref android.R.styleable#View_keepScreenOn
704 * @attr ref android.R.styleable#View_layerType
705 * @attr ref android.R.styleable#View_layoutDirection
706 * @attr ref android.R.styleable#View_longClickable
707 * @attr ref android.R.styleable#View_minHeight
708 * @attr ref android.R.styleable#View_minWidth
709 * @attr ref android.R.styleable#View_nextFocusDown
710 * @attr ref android.R.styleable#View_nextFocusLeft
711 * @attr ref android.R.styleable#View_nextFocusRight
712 * @attr ref android.R.styleable#View_nextFocusUp
713 * @attr ref android.R.styleable#View_onClick
714 * @attr ref android.R.styleable#View_padding
715 * @attr ref android.R.styleable#View_paddingBottom
716 * @attr ref android.R.styleable#View_paddingLeft
717 * @attr ref android.R.styleable#View_paddingRight
718 * @attr ref android.R.styleable#View_paddingTop
719 * @attr ref android.R.styleable#View_paddingStart
720 * @attr ref android.R.styleable#View_paddingEnd
721 * @attr ref android.R.styleable#View_saveEnabled
722 * @attr ref android.R.styleable#View_rotation
723 * @attr ref android.R.styleable#View_rotationX
724 * @attr ref android.R.styleable#View_rotationY
725 * @attr ref android.R.styleable#View_scaleX
726 * @attr ref android.R.styleable#View_scaleY
727 * @attr ref android.R.styleable#View_scrollX
728 * @attr ref android.R.styleable#View_scrollY
729 * @attr ref android.R.styleable#View_scrollbarSize
730 * @attr ref android.R.styleable#View_scrollbarStyle
731 * @attr ref android.R.styleable#View_scrollbars
732 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
733 * @attr ref android.R.styleable#View_scrollbarFadeDuration
734 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
735 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
736 * @attr ref android.R.styleable#View_scrollbarThumbVertical
737 * @attr ref android.R.styleable#View_scrollbarTrackVertical
738 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
739 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
740 * @attr ref android.R.styleable#View_stateListAnimator
741 * @attr ref android.R.styleable#View_transitionName
742 * @attr ref android.R.styleable#View_soundEffectsEnabled
743 * @attr ref android.R.styleable#View_tag
744 * @attr ref android.R.styleable#View_textAlignment
745 * @attr ref android.R.styleable#View_textDirection
746 * @attr ref android.R.styleable#View_transformPivotX
747 * @attr ref android.R.styleable#View_transformPivotY
748 * @attr ref android.R.styleable#View_translationX
749 * @attr ref android.R.styleable#View_translationY
750 * @attr ref android.R.styleable#View_translationZ
751 * @attr ref android.R.styleable#View_visibility
752 * @attr ref android.R.styleable#View_theme
753 *
754 * @see android.view.ViewGroup
755 */
756@UiThread
757public class View implements Drawable.Callback, KeyEvent.Callback,
758        AccessibilityEventSource {
759    private static final boolean DBG = false;
760
761    /**
762     * The logging tag used by this class with android.util.Log.
763     */
764    protected static final String VIEW_LOG_TAG = "View";
765
766    /**
767     * When set to true, apps will draw debugging information about their layouts.
768     *
769     * @hide
770     */
771    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
772
773    /**
774     * When set to true, this view will save its attribute data.
775     *
776     * @hide
777     */
778    public static boolean mDebugViewAttributes = false;
779
780    /**
781     * Used to mark a View that has no ID.
782     */
783    public static final int NO_ID = -1;
784
785    /**
786     * Signals that compatibility booleans have been initialized according to
787     * target SDK versions.
788     */
789    private static boolean sCompatibilityDone = false;
790
791    /**
792     * Use the old (broken) way of building MeasureSpecs.
793     */
794    private static boolean sUseBrokenMakeMeasureSpec = false;
795
796    /**
797     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
798     */
799    static boolean sUseZeroUnspecifiedMeasureSpec = false;
800
801    /**
802     * Ignore any optimizations using the measure cache.
803     */
804    private static boolean sIgnoreMeasureCache = false;
805
806    /**
807     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
808     */
809    private static boolean sAlwaysRemeasureExactly = false;
810
811    /**
812     * Relax constraints around whether setLayoutParams() must be called after
813     * modifying the layout params.
814     */
815    private static boolean sLayoutParamsAlwaysChanged = false;
816
817    /**
818     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
819     * without throwing
820     */
821    static boolean sTextureViewIgnoresDrawableSetters = false;
822
823    /**
824     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
825     * calling setFlags.
826     */
827    private static final int NOT_FOCUSABLE = 0x00000000;
828
829    /**
830     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
831     * setFlags.
832     */
833    private static final int FOCUSABLE = 0x00000001;
834
835    /**
836     * Mask for use with setFlags indicating bits used for focus.
837     */
838    private static final int FOCUSABLE_MASK = 0x00000001;
839
840    /**
841     * This view will adjust its padding to fit sytem windows (e.g. status bar)
842     */
843    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
844
845    /** @hide */
846    @IntDef({VISIBLE, INVISIBLE, GONE})
847    @Retention(RetentionPolicy.SOURCE)
848    public @interface Visibility {}
849
850    /**
851     * This view is visible.
852     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
853     * android:visibility}.
854     */
855    public static final int VISIBLE = 0x00000000;
856
857    /**
858     * This view is invisible, but it still takes up space for layout purposes.
859     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
860     * android:visibility}.
861     */
862    public static final int INVISIBLE = 0x00000004;
863
864    /**
865     * This view is invisible, and it doesn't take any space for layout
866     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
867     * android:visibility}.
868     */
869    public static final int GONE = 0x00000008;
870
871    /**
872     * Mask for use with setFlags indicating bits used for visibility.
873     * {@hide}
874     */
875    static final int VISIBILITY_MASK = 0x0000000C;
876
877    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
878
879    /**
880     * This view is enabled. Interpretation varies by subclass.
881     * Use with ENABLED_MASK when calling setFlags.
882     * {@hide}
883     */
884    static final int ENABLED = 0x00000000;
885
886    /**
887     * This view is disabled. Interpretation varies by subclass.
888     * Use with ENABLED_MASK when calling setFlags.
889     * {@hide}
890     */
891    static final int DISABLED = 0x00000020;
892
893   /**
894    * Mask for use with setFlags indicating bits used for indicating whether
895    * this view is enabled
896    * {@hide}
897    */
898    static final int ENABLED_MASK = 0x00000020;
899
900    /**
901     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
902     * called and further optimizations will be performed. It is okay to have
903     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
904     * {@hide}
905     */
906    static final int WILL_NOT_DRAW = 0x00000080;
907
908    /**
909     * Mask for use with setFlags indicating bits used for indicating whether
910     * this view is will draw
911     * {@hide}
912     */
913    static final int DRAW_MASK = 0x00000080;
914
915    /**
916     * <p>This view doesn't show scrollbars.</p>
917     * {@hide}
918     */
919    static final int SCROLLBARS_NONE = 0x00000000;
920
921    /**
922     * <p>This view shows horizontal scrollbars.</p>
923     * {@hide}
924     */
925    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
926
927    /**
928     * <p>This view shows vertical scrollbars.</p>
929     * {@hide}
930     */
931    static final int SCROLLBARS_VERTICAL = 0x00000200;
932
933    /**
934     * <p>Mask for use with setFlags indicating bits used for indicating which
935     * scrollbars are enabled.</p>
936     * {@hide}
937     */
938    static final int SCROLLBARS_MASK = 0x00000300;
939
940    /**
941     * Indicates that the view should filter touches when its window is obscured.
942     * Refer to the class comments for more information about this security feature.
943     * {@hide}
944     */
945    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
946
947    /**
948     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
949     * that they are optional and should be skipped if the window has
950     * requested system UI flags that ignore those insets for layout.
951     */
952    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
953
954    /**
955     * <p>This view doesn't show fading edges.</p>
956     * {@hide}
957     */
958    static final int FADING_EDGE_NONE = 0x00000000;
959
960    /**
961     * <p>This view shows horizontal fading edges.</p>
962     * {@hide}
963     */
964    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
965
966    /**
967     * <p>This view shows vertical fading edges.</p>
968     * {@hide}
969     */
970    static final int FADING_EDGE_VERTICAL = 0x00002000;
971
972    /**
973     * <p>Mask for use with setFlags indicating bits used for indicating which
974     * fading edges are enabled.</p>
975     * {@hide}
976     */
977    static final int FADING_EDGE_MASK = 0x00003000;
978
979    /**
980     * <p>Indicates this view can be clicked. When clickable, a View reacts
981     * to clicks by notifying the OnClickListener.<p>
982     * {@hide}
983     */
984    static final int CLICKABLE = 0x00004000;
985
986    /**
987     * <p>Indicates this view is caching its drawing into a bitmap.</p>
988     * {@hide}
989     */
990    static final int DRAWING_CACHE_ENABLED = 0x00008000;
991
992    /**
993     * <p>Indicates that no icicle should be saved for this view.<p>
994     * {@hide}
995     */
996    static final int SAVE_DISABLED = 0x000010000;
997
998    /**
999     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1000     * property.</p>
1001     * {@hide}
1002     */
1003    static final int SAVE_DISABLED_MASK = 0x000010000;
1004
1005    /**
1006     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1007     * {@hide}
1008     */
1009    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1010
1011    /**
1012     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1013     * {@hide}
1014     */
1015    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1016
1017    /** @hide */
1018    @Retention(RetentionPolicy.SOURCE)
1019    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1020    public @interface DrawingCacheQuality {}
1021
1022    /**
1023     * <p>Enables low quality mode for the drawing cache.</p>
1024     */
1025    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1026
1027    /**
1028     * <p>Enables high quality mode for the drawing cache.</p>
1029     */
1030    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1031
1032    /**
1033     * <p>Enables automatic quality mode for the drawing cache.</p>
1034     */
1035    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1036
1037    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1038            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1039    };
1040
1041    /**
1042     * <p>Mask for use with setFlags indicating bits used for the cache
1043     * quality property.</p>
1044     * {@hide}
1045     */
1046    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1047
1048    /**
1049     * <p>
1050     * Indicates this view can be long clicked. When long clickable, a View
1051     * reacts to long clicks by notifying the OnLongClickListener or showing a
1052     * context menu.
1053     * </p>
1054     * {@hide}
1055     */
1056    static final int LONG_CLICKABLE = 0x00200000;
1057
1058    /**
1059     * <p>Indicates that this view gets its drawable states from its direct parent
1060     * and ignores its original internal states.</p>
1061     *
1062     * @hide
1063     */
1064    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1065
1066    /**
1067     * <p>
1068     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1069     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1070     * OnContextClickListener.
1071     * </p>
1072     * {@hide}
1073     */
1074    static final int CONTEXT_CLICKABLE = 0x00800000;
1075
1076
1077    /** @hide */
1078    @IntDef({
1079        SCROLLBARS_INSIDE_OVERLAY,
1080        SCROLLBARS_INSIDE_INSET,
1081        SCROLLBARS_OUTSIDE_OVERLAY,
1082        SCROLLBARS_OUTSIDE_INSET
1083    })
1084    @Retention(RetentionPolicy.SOURCE)
1085    public @interface ScrollBarStyle {}
1086
1087    /**
1088     * The scrollbar style to display the scrollbars inside the content area,
1089     * without increasing the padding. The scrollbars will be overlaid with
1090     * translucency on the view's content.
1091     */
1092    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1093
1094    /**
1095     * The scrollbar style to display the scrollbars inside the padded area,
1096     * increasing the padding of the view. The scrollbars will not overlap the
1097     * content area of the view.
1098     */
1099    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1100
1101    /**
1102     * The scrollbar style to display the scrollbars at the edge of the view,
1103     * without increasing the padding. The scrollbars will be overlaid with
1104     * translucency.
1105     */
1106    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1107
1108    /**
1109     * The scrollbar style to display the scrollbars at the edge of the view,
1110     * increasing the padding of the view. The scrollbars will only overlap the
1111     * background, if any.
1112     */
1113    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1114
1115    /**
1116     * Mask to check if the scrollbar style is overlay or inset.
1117     * {@hide}
1118     */
1119    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1120
1121    /**
1122     * Mask to check if the scrollbar style is inside or outside.
1123     * {@hide}
1124     */
1125    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1126
1127    /**
1128     * Mask for scrollbar style.
1129     * {@hide}
1130     */
1131    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1132
1133    /**
1134     * View flag indicating that the screen should remain on while the
1135     * window containing this view is visible to the user.  This effectively
1136     * takes care of automatically setting the WindowManager's
1137     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1138     */
1139    public static final int KEEP_SCREEN_ON = 0x04000000;
1140
1141    /**
1142     * View flag indicating whether this view should have sound effects enabled
1143     * for events such as clicking and touching.
1144     */
1145    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1146
1147    /**
1148     * View flag indicating whether this view should have haptic feedback
1149     * enabled for events such as long presses.
1150     */
1151    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1152
1153    /**
1154     * <p>Indicates that the view hierarchy should stop saving state when
1155     * it reaches this view.  If state saving is initiated immediately at
1156     * the view, it will be allowed.
1157     * {@hide}
1158     */
1159    static final int PARENT_SAVE_DISABLED = 0x20000000;
1160
1161    /**
1162     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1163     * {@hide}
1164     */
1165    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1166
1167    /** @hide */
1168    @IntDef(flag = true,
1169            value = {
1170                FOCUSABLES_ALL,
1171                FOCUSABLES_TOUCH_MODE
1172            })
1173    @Retention(RetentionPolicy.SOURCE)
1174    public @interface FocusableMode {}
1175
1176    /**
1177     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1178     * should add all focusable Views regardless if they are focusable in touch mode.
1179     */
1180    public static final int FOCUSABLES_ALL = 0x00000000;
1181
1182    /**
1183     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1184     * should add only Views focusable in touch mode.
1185     */
1186    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1187
1188    /** @hide */
1189    @IntDef({
1190            FOCUS_BACKWARD,
1191            FOCUS_FORWARD,
1192            FOCUS_LEFT,
1193            FOCUS_UP,
1194            FOCUS_RIGHT,
1195            FOCUS_DOWN
1196    })
1197    @Retention(RetentionPolicy.SOURCE)
1198    public @interface FocusDirection {}
1199
1200    /** @hide */
1201    @IntDef({
1202            FOCUS_LEFT,
1203            FOCUS_UP,
1204            FOCUS_RIGHT,
1205            FOCUS_DOWN
1206    })
1207    @Retention(RetentionPolicy.SOURCE)
1208    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1209
1210    /**
1211     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1212     * item.
1213     */
1214    public static final int FOCUS_BACKWARD = 0x00000001;
1215
1216    /**
1217     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1218     * item.
1219     */
1220    public static final int FOCUS_FORWARD = 0x00000002;
1221
1222    /**
1223     * Use with {@link #focusSearch(int)}. Move focus to the left.
1224     */
1225    public static final int FOCUS_LEFT = 0x00000011;
1226
1227    /**
1228     * Use with {@link #focusSearch(int)}. Move focus up.
1229     */
1230    public static final int FOCUS_UP = 0x00000021;
1231
1232    /**
1233     * Use with {@link #focusSearch(int)}. Move focus to the right.
1234     */
1235    public static final int FOCUS_RIGHT = 0x00000042;
1236
1237    /**
1238     * Use with {@link #focusSearch(int)}. Move focus down.
1239     */
1240    public static final int FOCUS_DOWN = 0x00000082;
1241
1242    /**
1243     * Bits of {@link #getMeasuredWidthAndState()} and
1244     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1245     */
1246    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1247
1248    /**
1249     * Bits of {@link #getMeasuredWidthAndState()} and
1250     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1251     */
1252    public static final int MEASURED_STATE_MASK = 0xff000000;
1253
1254    /**
1255     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1256     * for functions that combine both width and height into a single int,
1257     * such as {@link #getMeasuredState()} and the childState argument of
1258     * {@link #resolveSizeAndState(int, int, int)}.
1259     */
1260    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1261
1262    /**
1263     * Bit of {@link #getMeasuredWidthAndState()} and
1264     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1265     * is smaller that the space the view would like to have.
1266     */
1267    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1268
1269    /**
1270     * Base View state sets
1271     */
1272    // Singles
1273    /**
1274     * Indicates the view has no states set. States are used with
1275     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1276     * view depending on its state.
1277     *
1278     * @see android.graphics.drawable.Drawable
1279     * @see #getDrawableState()
1280     */
1281    protected static final int[] EMPTY_STATE_SET;
1282    /**
1283     * Indicates the view is enabled. States are used with
1284     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1285     * view depending on its state.
1286     *
1287     * @see android.graphics.drawable.Drawable
1288     * @see #getDrawableState()
1289     */
1290    protected static final int[] ENABLED_STATE_SET;
1291    /**
1292     * Indicates the view is focused. States are used with
1293     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1294     * view depending on its state.
1295     *
1296     * @see android.graphics.drawable.Drawable
1297     * @see #getDrawableState()
1298     */
1299    protected static final int[] FOCUSED_STATE_SET;
1300    /**
1301     * Indicates the view is selected. States are used with
1302     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1303     * view depending on its state.
1304     *
1305     * @see android.graphics.drawable.Drawable
1306     * @see #getDrawableState()
1307     */
1308    protected static final int[] SELECTED_STATE_SET;
1309    /**
1310     * Indicates the view is pressed. States are used with
1311     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1312     * view depending on its state.
1313     *
1314     * @see android.graphics.drawable.Drawable
1315     * @see #getDrawableState()
1316     */
1317    protected static final int[] PRESSED_STATE_SET;
1318    /**
1319     * Indicates the view's window has focus. States are used with
1320     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1321     * view depending on its state.
1322     *
1323     * @see android.graphics.drawable.Drawable
1324     * @see #getDrawableState()
1325     */
1326    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1327    // Doubles
1328    /**
1329     * Indicates the view is enabled and has the focus.
1330     *
1331     * @see #ENABLED_STATE_SET
1332     * @see #FOCUSED_STATE_SET
1333     */
1334    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1335    /**
1336     * Indicates the view is enabled and selected.
1337     *
1338     * @see #ENABLED_STATE_SET
1339     * @see #SELECTED_STATE_SET
1340     */
1341    protected static final int[] ENABLED_SELECTED_STATE_SET;
1342    /**
1343     * Indicates the view is enabled and that its window has focus.
1344     *
1345     * @see #ENABLED_STATE_SET
1346     * @see #WINDOW_FOCUSED_STATE_SET
1347     */
1348    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1349    /**
1350     * Indicates the view is focused and selected.
1351     *
1352     * @see #FOCUSED_STATE_SET
1353     * @see #SELECTED_STATE_SET
1354     */
1355    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1356    /**
1357     * Indicates the view has the focus and that its window has the focus.
1358     *
1359     * @see #FOCUSED_STATE_SET
1360     * @see #WINDOW_FOCUSED_STATE_SET
1361     */
1362    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1363    /**
1364     * Indicates the view is selected and that its window has the focus.
1365     *
1366     * @see #SELECTED_STATE_SET
1367     * @see #WINDOW_FOCUSED_STATE_SET
1368     */
1369    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1370    // Triples
1371    /**
1372     * Indicates the view is enabled, focused and selected.
1373     *
1374     * @see #ENABLED_STATE_SET
1375     * @see #FOCUSED_STATE_SET
1376     * @see #SELECTED_STATE_SET
1377     */
1378    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1379    /**
1380     * Indicates the view is enabled, focused and its window has the focus.
1381     *
1382     * @see #ENABLED_STATE_SET
1383     * @see #FOCUSED_STATE_SET
1384     * @see #WINDOW_FOCUSED_STATE_SET
1385     */
1386    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1387    /**
1388     * Indicates the view is enabled, selected and its window has the focus.
1389     *
1390     * @see #ENABLED_STATE_SET
1391     * @see #SELECTED_STATE_SET
1392     * @see #WINDOW_FOCUSED_STATE_SET
1393     */
1394    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1395    /**
1396     * Indicates the view is focused, selected and its window has the focus.
1397     *
1398     * @see #FOCUSED_STATE_SET
1399     * @see #SELECTED_STATE_SET
1400     * @see #WINDOW_FOCUSED_STATE_SET
1401     */
1402    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1403    /**
1404     * Indicates the view is enabled, focused, selected and its window
1405     * has the focus.
1406     *
1407     * @see #ENABLED_STATE_SET
1408     * @see #FOCUSED_STATE_SET
1409     * @see #SELECTED_STATE_SET
1410     * @see #WINDOW_FOCUSED_STATE_SET
1411     */
1412    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1413    /**
1414     * Indicates the view is pressed and its window has the focus.
1415     *
1416     * @see #PRESSED_STATE_SET
1417     * @see #WINDOW_FOCUSED_STATE_SET
1418     */
1419    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1420    /**
1421     * Indicates the view is pressed and selected.
1422     *
1423     * @see #PRESSED_STATE_SET
1424     * @see #SELECTED_STATE_SET
1425     */
1426    protected static final int[] PRESSED_SELECTED_STATE_SET;
1427    /**
1428     * Indicates the view is pressed, selected and its window has the focus.
1429     *
1430     * @see #PRESSED_STATE_SET
1431     * @see #SELECTED_STATE_SET
1432     * @see #WINDOW_FOCUSED_STATE_SET
1433     */
1434    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1435    /**
1436     * Indicates the view is pressed and focused.
1437     *
1438     * @see #PRESSED_STATE_SET
1439     * @see #FOCUSED_STATE_SET
1440     */
1441    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1442    /**
1443     * Indicates the view is pressed, focused and its window has the focus.
1444     *
1445     * @see #PRESSED_STATE_SET
1446     * @see #FOCUSED_STATE_SET
1447     * @see #WINDOW_FOCUSED_STATE_SET
1448     */
1449    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1450    /**
1451     * Indicates the view is pressed, focused and selected.
1452     *
1453     * @see #PRESSED_STATE_SET
1454     * @see #SELECTED_STATE_SET
1455     * @see #FOCUSED_STATE_SET
1456     */
1457    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1458    /**
1459     * Indicates the view is pressed, focused, selected and its window has the focus.
1460     *
1461     * @see #PRESSED_STATE_SET
1462     * @see #FOCUSED_STATE_SET
1463     * @see #SELECTED_STATE_SET
1464     * @see #WINDOW_FOCUSED_STATE_SET
1465     */
1466    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1467    /**
1468     * Indicates the view is pressed and enabled.
1469     *
1470     * @see #PRESSED_STATE_SET
1471     * @see #ENABLED_STATE_SET
1472     */
1473    protected static final int[] PRESSED_ENABLED_STATE_SET;
1474    /**
1475     * Indicates the view is pressed, enabled and its window has the focus.
1476     *
1477     * @see #PRESSED_STATE_SET
1478     * @see #ENABLED_STATE_SET
1479     * @see #WINDOW_FOCUSED_STATE_SET
1480     */
1481    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1482    /**
1483     * Indicates the view is pressed, enabled and selected.
1484     *
1485     * @see #PRESSED_STATE_SET
1486     * @see #ENABLED_STATE_SET
1487     * @see #SELECTED_STATE_SET
1488     */
1489    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1490    /**
1491     * Indicates the view is pressed, enabled, selected and its window has the
1492     * focus.
1493     *
1494     * @see #PRESSED_STATE_SET
1495     * @see #ENABLED_STATE_SET
1496     * @see #SELECTED_STATE_SET
1497     * @see #WINDOW_FOCUSED_STATE_SET
1498     */
1499    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1500    /**
1501     * Indicates the view is pressed, enabled and focused.
1502     *
1503     * @see #PRESSED_STATE_SET
1504     * @see #ENABLED_STATE_SET
1505     * @see #FOCUSED_STATE_SET
1506     */
1507    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1508    /**
1509     * Indicates the view is pressed, enabled, focused and its window has the
1510     * focus.
1511     *
1512     * @see #PRESSED_STATE_SET
1513     * @see #ENABLED_STATE_SET
1514     * @see #FOCUSED_STATE_SET
1515     * @see #WINDOW_FOCUSED_STATE_SET
1516     */
1517    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1518    /**
1519     * Indicates the view is pressed, enabled, focused and selected.
1520     *
1521     * @see #PRESSED_STATE_SET
1522     * @see #ENABLED_STATE_SET
1523     * @see #SELECTED_STATE_SET
1524     * @see #FOCUSED_STATE_SET
1525     */
1526    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1527    /**
1528     * Indicates the view is pressed, enabled, focused, selected and its window
1529     * has the focus.
1530     *
1531     * @see #PRESSED_STATE_SET
1532     * @see #ENABLED_STATE_SET
1533     * @see #SELECTED_STATE_SET
1534     * @see #FOCUSED_STATE_SET
1535     * @see #WINDOW_FOCUSED_STATE_SET
1536     */
1537    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1538
1539    static {
1540        EMPTY_STATE_SET = StateSet.get(0);
1541
1542        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1543
1544        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1545        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1546                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1547
1548        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1549        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1550                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1551        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1552                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1553        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1554                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1555                        | StateSet.VIEW_STATE_FOCUSED);
1556
1557        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1558        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1559                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1560        ENABLED_SELECTED_STATE_SET = StateSet.get(
1561                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1562        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1563                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1564                        | StateSet.VIEW_STATE_ENABLED);
1565        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1566                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1567        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1568                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1569                        | StateSet.VIEW_STATE_ENABLED);
1570        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1571                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1572                        | StateSet.VIEW_STATE_ENABLED);
1573        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1574                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1575                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1576
1577        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1578        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1579                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1580        PRESSED_SELECTED_STATE_SET = StateSet.get(
1581                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1582        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1583                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1584                        | StateSet.VIEW_STATE_PRESSED);
1585        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1586                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1587        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1588                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1589                        | StateSet.VIEW_STATE_PRESSED);
1590        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1591                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1592                        | StateSet.VIEW_STATE_PRESSED);
1593        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1594                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1595                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1596        PRESSED_ENABLED_STATE_SET = StateSet.get(
1597                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1598        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1599                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1600                        | StateSet.VIEW_STATE_PRESSED);
1601        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1602                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1603                        | StateSet.VIEW_STATE_PRESSED);
1604        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1605                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1606                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1607        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1608                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1609                        | StateSet.VIEW_STATE_PRESSED);
1610        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1611                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1612                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1613        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1614                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1615                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1616        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1617                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1618                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1619                        | StateSet.VIEW_STATE_PRESSED);
1620    }
1621
1622    /**
1623     * Accessibility event types that are dispatched for text population.
1624     */
1625    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1626            AccessibilityEvent.TYPE_VIEW_CLICKED
1627            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1628            | AccessibilityEvent.TYPE_VIEW_SELECTED
1629            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1630            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1631            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1632            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1633            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1634            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1635            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1636            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1637
1638    /**
1639     * Temporary Rect currently for use in setBackground().  This will probably
1640     * be extended in the future to hold our own class with more than just
1641     * a Rect. :)
1642     */
1643    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1644
1645    /**
1646     * Map used to store views' tags.
1647     */
1648    private SparseArray<Object> mKeyedTags;
1649
1650    /**
1651     * The next available accessibility id.
1652     */
1653    private static int sNextAccessibilityViewId;
1654
1655    /**
1656     * The animation currently associated with this view.
1657     * @hide
1658     */
1659    protected Animation mCurrentAnimation = null;
1660
1661    /**
1662     * Width as measured during measure pass.
1663     * {@hide}
1664     */
1665    @ViewDebug.ExportedProperty(category = "measurement")
1666    int mMeasuredWidth;
1667
1668    /**
1669     * Height as measured during measure pass.
1670     * {@hide}
1671     */
1672    @ViewDebug.ExportedProperty(category = "measurement")
1673    int mMeasuredHeight;
1674
1675    /**
1676     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1677     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1678     * its display list. This flag, used only when hw accelerated, allows us to clear the
1679     * flag while retaining this information until it's needed (at getDisplayList() time and
1680     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1681     *
1682     * {@hide}
1683     */
1684    boolean mRecreateDisplayList = false;
1685
1686    /**
1687     * The view's identifier.
1688     * {@hide}
1689     *
1690     * @see #setId(int)
1691     * @see #getId()
1692     */
1693    @IdRes
1694    @ViewDebug.ExportedProperty(resolveId = true)
1695    int mID = NO_ID;
1696
1697    /**
1698     * The stable ID of this view for accessibility purposes.
1699     */
1700    int mAccessibilityViewId = NO_ID;
1701
1702    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1703
1704    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1705
1706    /**
1707     * The view's tag.
1708     * {@hide}
1709     *
1710     * @see #setTag(Object)
1711     * @see #getTag()
1712     */
1713    protected Object mTag = null;
1714
1715    // for mPrivateFlags:
1716    /** {@hide} */
1717    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1718    /** {@hide} */
1719    static final int PFLAG_FOCUSED                     = 0x00000002;
1720    /** {@hide} */
1721    static final int PFLAG_SELECTED                    = 0x00000004;
1722    /** {@hide} */
1723    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1724    /** {@hide} */
1725    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1726    /** {@hide} */
1727    static final int PFLAG_DRAWN                       = 0x00000020;
1728    /**
1729     * When this flag is set, this view is running an animation on behalf of its
1730     * children and should therefore not cancel invalidate requests, even if they
1731     * lie outside of this view's bounds.
1732     *
1733     * {@hide}
1734     */
1735    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1736    /** {@hide} */
1737    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1738    /** {@hide} */
1739    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1740    /** {@hide} */
1741    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1742    /** {@hide} */
1743    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1744    /** {@hide} */
1745    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1746    /** {@hide} */
1747    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1748
1749    private static final int PFLAG_PRESSED             = 0x00004000;
1750
1751    /** {@hide} */
1752    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1753    /**
1754     * Flag used to indicate that this view should be drawn once more (and only once
1755     * more) after its animation has completed.
1756     * {@hide}
1757     */
1758    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1759
1760    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1761
1762    /**
1763     * Indicates that the View returned true when onSetAlpha() was called and that
1764     * the alpha must be restored.
1765     * {@hide}
1766     */
1767    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1768
1769    /**
1770     * Set by {@link #setScrollContainer(boolean)}.
1771     */
1772    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1773
1774    /**
1775     * Set by {@link #setScrollContainer(boolean)}.
1776     */
1777    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1778
1779    /**
1780     * View flag indicating whether this view was invalidated (fully or partially.)
1781     *
1782     * @hide
1783     */
1784    static final int PFLAG_DIRTY                       = 0x00200000;
1785
1786    /**
1787     * View flag indicating whether this view was invalidated by an opaque
1788     * invalidate request.
1789     *
1790     * @hide
1791     */
1792    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1793
1794    /**
1795     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1796     *
1797     * @hide
1798     */
1799    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1800
1801    /**
1802     * Indicates whether the background is opaque.
1803     *
1804     * @hide
1805     */
1806    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1807
1808    /**
1809     * Indicates whether the scrollbars are opaque.
1810     *
1811     * @hide
1812     */
1813    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1814
1815    /**
1816     * Indicates whether the view is opaque.
1817     *
1818     * @hide
1819     */
1820    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1821
1822    /**
1823     * Indicates a prepressed state;
1824     * the short time between ACTION_DOWN and recognizing
1825     * a 'real' press. Prepressed is used to recognize quick taps
1826     * even when they are shorter than ViewConfiguration.getTapTimeout().
1827     *
1828     * @hide
1829     */
1830    private static final int PFLAG_PREPRESSED          = 0x02000000;
1831
1832    /**
1833     * Indicates whether the view is temporarily detached.
1834     *
1835     * @hide
1836     */
1837    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1838
1839    /**
1840     * Indicates that we should awaken scroll bars once attached
1841     *
1842     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1843     * during window attachment and it is no longer needed. Feel free to repurpose it.
1844     *
1845     * @hide
1846     */
1847    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1848
1849    /**
1850     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1851     * @hide
1852     */
1853    private static final int PFLAG_HOVERED             = 0x10000000;
1854
1855    /**
1856     * no longer needed, should be reused
1857     */
1858    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1859
1860    /** {@hide} */
1861    static final int PFLAG_ACTIVATED                   = 0x40000000;
1862
1863    /**
1864     * Indicates that this view was specifically invalidated, not just dirtied because some
1865     * child view was invalidated. The flag is used to determine when we need to recreate
1866     * a view's display list (as opposed to just returning a reference to its existing
1867     * display list).
1868     *
1869     * @hide
1870     */
1871    static final int PFLAG_INVALIDATED                 = 0x80000000;
1872
1873    /**
1874     * Masks for mPrivateFlags2, as generated by dumpFlags():
1875     *
1876     * |-------|-------|-------|-------|
1877     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1878     *                                1  PFLAG2_DRAG_HOVERED
1879     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1880     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1881     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1882     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1883     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1884     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1885     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1886     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1887     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1888     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1889     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1890     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1891     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1892     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1893     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1894     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1895     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1896     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1897     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1898     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1899     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1900     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1901     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1902     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1903     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1904     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1905     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1906     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1907     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1908     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1909     *    1                              PFLAG2_PADDING_RESOLVED
1910     *   1                               PFLAG2_DRAWABLE_RESOLVED
1911     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1912     * |-------|-------|-------|-------|
1913     */
1914
1915    /**
1916     * Indicates that this view has reported that it can accept the current drag's content.
1917     * Cleared when the drag operation concludes.
1918     * @hide
1919     */
1920    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1921
1922    /**
1923     * Indicates that this view is currently directly under the drag location in a
1924     * drag-and-drop operation involving content that it can accept.  Cleared when
1925     * the drag exits the view, or when the drag operation concludes.
1926     * @hide
1927     */
1928    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1929
1930    /** @hide */
1931    @IntDef({
1932        LAYOUT_DIRECTION_LTR,
1933        LAYOUT_DIRECTION_RTL,
1934        LAYOUT_DIRECTION_INHERIT,
1935        LAYOUT_DIRECTION_LOCALE
1936    })
1937    @Retention(RetentionPolicy.SOURCE)
1938    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1939    public @interface LayoutDir {}
1940
1941    /** @hide */
1942    @IntDef({
1943        LAYOUT_DIRECTION_LTR,
1944        LAYOUT_DIRECTION_RTL
1945    })
1946    @Retention(RetentionPolicy.SOURCE)
1947    public @interface ResolvedLayoutDir {}
1948
1949    /**
1950     * A flag to indicate that the layout direction of this view has not been defined yet.
1951     * @hide
1952     */
1953    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1954
1955    /**
1956     * Horizontal layout direction of this view is from Left to Right.
1957     * Use with {@link #setLayoutDirection}.
1958     */
1959    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1960
1961    /**
1962     * Horizontal layout direction of this view is from Right to Left.
1963     * Use with {@link #setLayoutDirection}.
1964     */
1965    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1966
1967    /**
1968     * Horizontal layout direction of this view is inherited from its parent.
1969     * Use with {@link #setLayoutDirection}.
1970     */
1971    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1972
1973    /**
1974     * Horizontal layout direction of this view is from deduced from the default language
1975     * script for the locale. Use with {@link #setLayoutDirection}.
1976     */
1977    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1978
1979    /**
1980     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1981     * @hide
1982     */
1983    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1984
1985    /**
1986     * Mask for use with private flags indicating bits used for horizontal layout direction.
1987     * @hide
1988     */
1989    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1990
1991    /**
1992     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1993     * right-to-left direction.
1994     * @hide
1995     */
1996    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1997
1998    /**
1999     * Indicates whether the view horizontal layout direction has been resolved.
2000     * @hide
2001     */
2002    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2003
2004    /**
2005     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2006     * @hide
2007     */
2008    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2009            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2010
2011    /*
2012     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2013     * flag value.
2014     * @hide
2015     */
2016    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2017            LAYOUT_DIRECTION_LTR,
2018            LAYOUT_DIRECTION_RTL,
2019            LAYOUT_DIRECTION_INHERIT,
2020            LAYOUT_DIRECTION_LOCALE
2021    };
2022
2023    /**
2024     * Default horizontal layout direction.
2025     */
2026    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2027
2028    /**
2029     * Default horizontal layout direction.
2030     * @hide
2031     */
2032    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2033
2034    /**
2035     * Text direction is inherited through {@link ViewGroup}
2036     */
2037    public static final int TEXT_DIRECTION_INHERIT = 0;
2038
2039    /**
2040     * Text direction is using "first strong algorithm". The first strong directional character
2041     * determines the paragraph direction. If there is no strong directional character, the
2042     * paragraph direction is the view's resolved layout direction.
2043     */
2044    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2045
2046    /**
2047     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2048     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2049     * If there are neither, the paragraph direction is the view's resolved layout direction.
2050     */
2051    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2052
2053    /**
2054     * Text direction is forced to LTR.
2055     */
2056    public static final int TEXT_DIRECTION_LTR = 3;
2057
2058    /**
2059     * Text direction is forced to RTL.
2060     */
2061    public static final int TEXT_DIRECTION_RTL = 4;
2062
2063    /**
2064     * Text direction is coming from the system Locale.
2065     */
2066    public static final int TEXT_DIRECTION_LOCALE = 5;
2067
2068    /**
2069     * Text direction is using "first strong algorithm". The first strong directional character
2070     * determines the paragraph direction. If there is no strong directional character, the
2071     * paragraph direction is LTR.
2072     */
2073    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2074
2075    /**
2076     * Text direction is using "first strong algorithm". The first strong directional character
2077     * determines the paragraph direction. If there is no strong directional character, the
2078     * paragraph direction is RTL.
2079     */
2080    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2081
2082    /**
2083     * Default text direction is inherited
2084     */
2085    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2086
2087    /**
2088     * Default resolved text direction
2089     * @hide
2090     */
2091    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2092
2093    /**
2094     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2095     * @hide
2096     */
2097    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2098
2099    /**
2100     * Mask for use with private flags indicating bits used for text direction.
2101     * @hide
2102     */
2103    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2104            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2105
2106    /**
2107     * Array of text direction flags for mapping attribute "textDirection" to correct
2108     * flag value.
2109     * @hide
2110     */
2111    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2112            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2113            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2114            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2115            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2116            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2117            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2118            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2119            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2120    };
2121
2122    /**
2123     * Indicates whether the view text direction has been resolved.
2124     * @hide
2125     */
2126    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2127            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2128
2129    /**
2130     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2131     * @hide
2132     */
2133    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2134
2135    /**
2136     * Mask for use with private flags indicating bits used for resolved text direction.
2137     * @hide
2138     */
2139    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2140            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2141
2142    /**
2143     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2144     * @hide
2145     */
2146    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2147            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2148
2149    /** @hide */
2150    @IntDef({
2151        TEXT_ALIGNMENT_INHERIT,
2152        TEXT_ALIGNMENT_GRAVITY,
2153        TEXT_ALIGNMENT_CENTER,
2154        TEXT_ALIGNMENT_TEXT_START,
2155        TEXT_ALIGNMENT_TEXT_END,
2156        TEXT_ALIGNMENT_VIEW_START,
2157        TEXT_ALIGNMENT_VIEW_END
2158    })
2159    @Retention(RetentionPolicy.SOURCE)
2160    public @interface TextAlignment {}
2161
2162    /**
2163     * Default text alignment. The text alignment of this View is inherited from its parent.
2164     * Use with {@link #setTextAlignment(int)}
2165     */
2166    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2167
2168    /**
2169     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2170     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2171     *
2172     * Use with {@link #setTextAlignment(int)}
2173     */
2174    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2175
2176    /**
2177     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2178     *
2179     * Use with {@link #setTextAlignment(int)}
2180     */
2181    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2182
2183    /**
2184     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2185     *
2186     * Use with {@link #setTextAlignment(int)}
2187     */
2188    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2189
2190    /**
2191     * Center the paragraph, e.g. ALIGN_CENTER.
2192     *
2193     * Use with {@link #setTextAlignment(int)}
2194     */
2195    public static final int TEXT_ALIGNMENT_CENTER = 4;
2196
2197    /**
2198     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2199     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2200     *
2201     * Use with {@link #setTextAlignment(int)}
2202     */
2203    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2204
2205    /**
2206     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2207     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2208     *
2209     * Use with {@link #setTextAlignment(int)}
2210     */
2211    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2212
2213    /**
2214     * Default text alignment is inherited
2215     */
2216    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2217
2218    /**
2219     * Default resolved text alignment
2220     * @hide
2221     */
2222    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2223
2224    /**
2225      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2226      * @hide
2227      */
2228    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2229
2230    /**
2231      * Mask for use with private flags indicating bits used for text alignment.
2232      * @hide
2233      */
2234    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2235
2236    /**
2237     * Array of text direction flags for mapping attribute "textAlignment" to correct
2238     * flag value.
2239     * @hide
2240     */
2241    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2242            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2243            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2244            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2245            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2246            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2247            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2248            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2249    };
2250
2251    /**
2252     * Indicates whether the view text alignment has been resolved.
2253     * @hide
2254     */
2255    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2256
2257    /**
2258     * Bit shift to get the resolved text alignment.
2259     * @hide
2260     */
2261    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2262
2263    /**
2264     * Mask for use with private flags indicating bits used for text alignment.
2265     * @hide
2266     */
2267    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2268            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2269
2270    /**
2271     * Indicates whether if the view text alignment has been resolved to gravity
2272     */
2273    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2274            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2275
2276    // Accessiblity constants for mPrivateFlags2
2277
2278    /**
2279     * Shift for the bits in {@link #mPrivateFlags2} related to the
2280     * "importantForAccessibility" attribute.
2281     */
2282    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2283
2284    /**
2285     * Automatically determine whether a view is important for accessibility.
2286     */
2287    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2288
2289    /**
2290     * The view is important for accessibility.
2291     */
2292    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2293
2294    /**
2295     * The view is not important for accessibility.
2296     */
2297    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2298
2299    /**
2300     * The view is not important for accessibility, nor are any of its
2301     * descendant views.
2302     */
2303    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2304
2305    /**
2306     * The default whether the view is important for accessibility.
2307     */
2308    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2309
2310    /**
2311     * Mask for obtainig the bits which specify how to determine
2312     * whether a view is important for accessibility.
2313     */
2314    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2315        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2316        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2317        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2318
2319    /**
2320     * Shift for the bits in {@link #mPrivateFlags2} related to the
2321     * "accessibilityLiveRegion" attribute.
2322     */
2323    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2324
2325    /**
2326     * Live region mode specifying that accessibility services should not
2327     * automatically announce changes to this view. This is the default live
2328     * region mode for most views.
2329     * <p>
2330     * Use with {@link #setAccessibilityLiveRegion(int)}.
2331     */
2332    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2333
2334    /**
2335     * Live region mode specifying that accessibility services should announce
2336     * changes to this view.
2337     * <p>
2338     * Use with {@link #setAccessibilityLiveRegion(int)}.
2339     */
2340    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2341
2342    /**
2343     * Live region mode specifying that accessibility services should interrupt
2344     * ongoing speech to immediately announce changes to this view.
2345     * <p>
2346     * Use with {@link #setAccessibilityLiveRegion(int)}.
2347     */
2348    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2349
2350    /**
2351     * The default whether the view is important for accessibility.
2352     */
2353    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2354
2355    /**
2356     * Mask for obtaining the bits which specify a view's accessibility live
2357     * region mode.
2358     */
2359    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2360            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2361            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2362
2363    /**
2364     * Flag indicating whether a view has accessibility focus.
2365     */
2366    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2367
2368    /**
2369     * Flag whether the accessibility state of the subtree rooted at this view changed.
2370     */
2371    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2372
2373    /**
2374     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2375     * is used to check whether later changes to the view's transform should invalidate the
2376     * view to force the quickReject test to run again.
2377     */
2378    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2379
2380    /**
2381     * Flag indicating that start/end padding has been resolved into left/right padding
2382     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2383     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2384     * during measurement. In some special cases this is required such as when an adapter-based
2385     * view measures prospective children without attaching them to a window.
2386     */
2387    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2388
2389    /**
2390     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2391     */
2392    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2393
2394    /**
2395     * Indicates that the view is tracking some sort of transient state
2396     * that the app should not need to be aware of, but that the framework
2397     * should take special care to preserve.
2398     */
2399    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2400
2401    /**
2402     * Group of bits indicating that RTL properties resolution is done.
2403     */
2404    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2405            PFLAG2_TEXT_DIRECTION_RESOLVED |
2406            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2407            PFLAG2_PADDING_RESOLVED |
2408            PFLAG2_DRAWABLE_RESOLVED;
2409
2410    // There are a couple of flags left in mPrivateFlags2
2411
2412    /* End of masks for mPrivateFlags2 */
2413
2414    /**
2415     * Masks for mPrivateFlags3, as generated by dumpFlags():
2416     *
2417     * |-------|-------|-------|-------|
2418     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2419     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2420     *                               1   PFLAG3_IS_LAID_OUT
2421     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2422     *                             1     PFLAG3_CALLED_SUPER
2423     *                            1      PFLAG3_APPLYING_INSETS
2424     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2425     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2426     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2427     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2428     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2429     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2430     *                     1             PFLAG3_SCROLL_INDICATOR_START
2431     *                    1              PFLAG3_SCROLL_INDICATOR_END
2432     *                   1               PFLAG3_ASSIST_BLOCKED
2433     *                  1                PFLAG3_POINTER_ICON_NULL
2434     *                 1                 PFLAG3_POINTER_ICON_VALUE_START
2435     *           11111111                PFLAG3_POINTER_ICON_MASK
2436     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2437     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2438     *        1                          PFLAG3_TEMPORARY_DETACH
2439     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2440     * |-------|-------|-------|-------|
2441     */
2442
2443    /**
2444     * Flag indicating that view has a transform animation set on it. This is used to track whether
2445     * an animation is cleared between successive frames, in order to tell the associated
2446     * DisplayList to clear its animation matrix.
2447     */
2448    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2449
2450    /**
2451     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2452     * animation is cleared between successive frames, in order to tell the associated
2453     * DisplayList to restore its alpha value.
2454     */
2455    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2456
2457    /**
2458     * Flag indicating that the view has been through at least one layout since it
2459     * was last attached to a window.
2460     */
2461    static final int PFLAG3_IS_LAID_OUT = 0x4;
2462
2463    /**
2464     * Flag indicating that a call to measure() was skipped and should be done
2465     * instead when layout() is invoked.
2466     */
2467    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2468
2469    /**
2470     * Flag indicating that an overridden method correctly called down to
2471     * the superclass implementation as required by the API spec.
2472     */
2473    static final int PFLAG3_CALLED_SUPER = 0x10;
2474
2475    /**
2476     * Flag indicating that we're in the process of applying window insets.
2477     */
2478    static final int PFLAG3_APPLYING_INSETS = 0x20;
2479
2480    /**
2481     * Flag indicating that we're in the process of fitting system windows using the old method.
2482     */
2483    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2484
2485    /**
2486     * Flag indicating that nested scrolling is enabled for this view.
2487     * The view will optionally cooperate with views up its parent chain to allow for
2488     * integrated nested scrolling along the same axis.
2489     */
2490    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2491
2492    /**
2493     * Flag indicating that the bottom scroll indicator should be displayed
2494     * when this view can scroll up.
2495     */
2496    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2497
2498    /**
2499     * Flag indicating that the bottom scroll indicator should be displayed
2500     * when this view can scroll down.
2501     */
2502    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2503
2504    /**
2505     * Flag indicating that the left scroll indicator should be displayed
2506     * when this view can scroll left.
2507     */
2508    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2509
2510    /**
2511     * Flag indicating that the right scroll indicator should be displayed
2512     * when this view can scroll right.
2513     */
2514    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2515
2516    /**
2517     * Flag indicating that the start scroll indicator should be displayed
2518     * when this view can scroll in the start direction.
2519     */
2520    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2521
2522    /**
2523     * Flag indicating that the end scroll indicator should be displayed
2524     * when this view can scroll in the end direction.
2525     */
2526    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2527
2528    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2529
2530    static final int SCROLL_INDICATORS_NONE = 0x0000;
2531
2532    /**
2533     * Mask for use with setFlags indicating bits used for indicating which
2534     * scroll indicators are enabled.
2535     */
2536    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2537            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2538            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2539            | PFLAG3_SCROLL_INDICATOR_END;
2540
2541    /**
2542     * Left-shift required to translate between public scroll indicator flags
2543     * and internal PFLAGS3 flags. When used as a right-shift, translates
2544     * PFLAGS3 flags to public flags.
2545     */
2546    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2547
2548    /** @hide */
2549    @Retention(RetentionPolicy.SOURCE)
2550    @IntDef(flag = true,
2551            value = {
2552                    SCROLL_INDICATOR_TOP,
2553                    SCROLL_INDICATOR_BOTTOM,
2554                    SCROLL_INDICATOR_LEFT,
2555                    SCROLL_INDICATOR_RIGHT,
2556                    SCROLL_INDICATOR_START,
2557                    SCROLL_INDICATOR_END,
2558            })
2559    public @interface ScrollIndicators {}
2560
2561    /**
2562     * Scroll indicator direction for the top edge of the view.
2563     *
2564     * @see #setScrollIndicators(int)
2565     * @see #setScrollIndicators(int, int)
2566     * @see #getScrollIndicators()
2567     */
2568    public static final int SCROLL_INDICATOR_TOP =
2569            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2570
2571    /**
2572     * Scroll indicator direction for the bottom edge of the view.
2573     *
2574     * @see #setScrollIndicators(int)
2575     * @see #setScrollIndicators(int, int)
2576     * @see #getScrollIndicators()
2577     */
2578    public static final int SCROLL_INDICATOR_BOTTOM =
2579            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2580
2581    /**
2582     * Scroll indicator direction for the left edge of the view.
2583     *
2584     * @see #setScrollIndicators(int)
2585     * @see #setScrollIndicators(int, int)
2586     * @see #getScrollIndicators()
2587     */
2588    public static final int SCROLL_INDICATOR_LEFT =
2589            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2590
2591    /**
2592     * Scroll indicator direction for the right edge of the view.
2593     *
2594     * @see #setScrollIndicators(int)
2595     * @see #setScrollIndicators(int, int)
2596     * @see #getScrollIndicators()
2597     */
2598    public static final int SCROLL_INDICATOR_RIGHT =
2599            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2600
2601    /**
2602     * Scroll indicator direction for the starting edge of the view.
2603     * <p>
2604     * Resolved according to the view's layout direction, see
2605     * {@link #getLayoutDirection()} for more information.
2606     *
2607     * @see #setScrollIndicators(int)
2608     * @see #setScrollIndicators(int, int)
2609     * @see #getScrollIndicators()
2610     */
2611    public static final int SCROLL_INDICATOR_START =
2612            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2613
2614    /**
2615     * Scroll indicator direction for the ending edge of the view.
2616     * <p>
2617     * Resolved according to the view's layout direction, see
2618     * {@link #getLayoutDirection()} for more information.
2619     *
2620     * @see #setScrollIndicators(int)
2621     * @see #setScrollIndicators(int, int)
2622     * @see #getScrollIndicators()
2623     */
2624    public static final int SCROLL_INDICATOR_END =
2625            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2626
2627    /**
2628     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2629     * into this view.<p>
2630     */
2631    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2632
2633    /**
2634     * The mask for use with private flags indicating bits used for pointer icon shapes.
2635     */
2636    static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
2637
2638    /**
2639     * Left-shift used for pointer icon shape values in private flags.
2640     */
2641    static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
2642
2643    /**
2644     * Value indicating no specific pointer icons.
2645     */
2646    private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
2647
2648    /**
2649     * Value indicating {@link PointerIcon.TYPE_NULL}.
2650     */
2651    private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
2652
2653    /**
2654     * The base value for other pointer icon shapes.
2655     */
2656    private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
2657
2658    /**
2659     * Whether this view has rendered elements that overlap (see {@link
2660     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2661     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2662     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2663     * determined by whatever {@link #hasOverlappingRendering()} returns.
2664     */
2665    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2666
2667    /**
2668     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2669     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2670     */
2671    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2672
2673    /**
2674     * Flag indicating that the view is temporarily detached from the parent view.
2675     *
2676     * @see #onStartTemporaryDetach()
2677     * @see #onFinishTemporaryDetach()
2678     */
2679    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
2680
2681    /**
2682     * Flag indicating that the view does not wish to be revealed within its parent
2683     * hierarchy when it gains focus. Expressed in the negative since the historical
2684     * default behavior is to reveal on focus; this flag suppresses that behavior.
2685     *
2686     * @see #setRevealOnFocusHint(boolean)
2687     * @see #getRevealOnFocusHint()
2688     */
2689    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
2690
2691    /* End of masks for mPrivateFlags3 */
2692
2693    /**
2694     * Always allow a user to over-scroll this view, provided it is a
2695     * view that can scroll.
2696     *
2697     * @see #getOverScrollMode()
2698     * @see #setOverScrollMode(int)
2699     */
2700    public static final int OVER_SCROLL_ALWAYS = 0;
2701
2702    /**
2703     * Allow a user to over-scroll this view only if the content is large
2704     * enough to meaningfully scroll, provided it is a view that can scroll.
2705     *
2706     * @see #getOverScrollMode()
2707     * @see #setOverScrollMode(int)
2708     */
2709    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2710
2711    /**
2712     * Never allow a user to over-scroll this view.
2713     *
2714     * @see #getOverScrollMode()
2715     * @see #setOverScrollMode(int)
2716     */
2717    public static final int OVER_SCROLL_NEVER = 2;
2718
2719    /**
2720     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2721     * requested the system UI (status bar) to be visible (the default).
2722     *
2723     * @see #setSystemUiVisibility(int)
2724     */
2725    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2726
2727    /**
2728     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2729     * system UI to enter an unobtrusive "low profile" mode.
2730     *
2731     * <p>This is for use in games, book readers, video players, or any other
2732     * "immersive" application where the usual system chrome is deemed too distracting.
2733     *
2734     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2735     *
2736     * @see #setSystemUiVisibility(int)
2737     */
2738    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2739
2740    /**
2741     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2742     * system navigation be temporarily hidden.
2743     *
2744     * <p>This is an even less obtrusive state than that called for by
2745     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2746     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2747     * those to disappear. This is useful (in conjunction with the
2748     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2749     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2750     * window flags) for displaying content using every last pixel on the display.
2751     *
2752     * <p>There is a limitation: because navigation controls are so important, the least user
2753     * interaction will cause them to reappear immediately.  When this happens, both
2754     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2755     * so that both elements reappear at the same time.
2756     *
2757     * @see #setSystemUiVisibility(int)
2758     */
2759    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2760
2761    /**
2762     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2763     * into the normal fullscreen mode so that its content can take over the screen
2764     * while still allowing the user to interact with the application.
2765     *
2766     * <p>This has the same visual effect as
2767     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2768     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2769     * meaning that non-critical screen decorations (such as the status bar) will be
2770     * hidden while the user is in the View's window, focusing the experience on
2771     * that content.  Unlike the window flag, if you are using ActionBar in
2772     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2773     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2774     * hide the action bar.
2775     *
2776     * <p>This approach to going fullscreen is best used over the window flag when
2777     * it is a transient state -- that is, the application does this at certain
2778     * points in its user interaction where it wants to allow the user to focus
2779     * on content, but not as a continuous state.  For situations where the application
2780     * would like to simply stay full screen the entire time (such as a game that
2781     * wants to take over the screen), the
2782     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2783     * is usually a better approach.  The state set here will be removed by the system
2784     * in various situations (such as the user moving to another application) like
2785     * the other system UI states.
2786     *
2787     * <p>When using this flag, the application should provide some easy facility
2788     * for the user to go out of it.  A common example would be in an e-book
2789     * reader, where tapping on the screen brings back whatever screen and UI
2790     * decorations that had been hidden while the user was immersed in reading
2791     * the book.
2792     *
2793     * @see #setSystemUiVisibility(int)
2794     */
2795    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2796
2797    /**
2798     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2799     * flags, we would like a stable view of the content insets given to
2800     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2801     * will always represent the worst case that the application can expect
2802     * as a continuous state.  In the stock Android UI this is the space for
2803     * the system bar, nav bar, and status bar, but not more transient elements
2804     * such as an input method.
2805     *
2806     * The stable layout your UI sees is based on the system UI modes you can
2807     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2808     * then you will get a stable layout for changes of the
2809     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2810     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2811     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2812     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2813     * with a stable layout.  (Note that you should avoid using
2814     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2815     *
2816     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2817     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2818     * then a hidden status bar will be considered a "stable" state for purposes
2819     * here.  This allows your UI to continually hide the status bar, while still
2820     * using the system UI flags to hide the action bar while still retaining
2821     * a stable layout.  Note that changing the window fullscreen flag will never
2822     * provide a stable layout for a clean transition.
2823     *
2824     * <p>If you are using ActionBar in
2825     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2826     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2827     * insets it adds to those given to the application.
2828     */
2829    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2830
2831    /**
2832     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2833     * to be laid out as if it has requested
2834     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2835     * allows it to avoid artifacts when switching in and out of that mode, at
2836     * the expense that some of its user interface may be covered by screen
2837     * decorations when they are shown.  You can perform layout of your inner
2838     * UI elements to account for the navigation system UI through the
2839     * {@link #fitSystemWindows(Rect)} method.
2840     */
2841    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2842
2843    /**
2844     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2845     * to be laid out as if it has requested
2846     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2847     * allows it to avoid artifacts when switching in and out of that mode, at
2848     * the expense that some of its user interface may be covered by screen
2849     * decorations when they are shown.  You can perform layout of your inner
2850     * UI elements to account for non-fullscreen system UI through the
2851     * {@link #fitSystemWindows(Rect)} method.
2852     */
2853    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2854
2855    /**
2856     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2857     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2858     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2859     * user interaction.
2860     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2861     * has an effect when used in combination with that flag.</p>
2862     */
2863    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2864
2865    /**
2866     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2867     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2868     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2869     * experience while also hiding the system bars.  If this flag is not set,
2870     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2871     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2872     * if the user swipes from the top of the screen.
2873     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2874     * system gestures, such as swiping from the top of the screen.  These transient system bars
2875     * will overlay app’s content, may have some degree of transparency, and will automatically
2876     * hide after a short timeout.
2877     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2878     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2879     * with one or both of those flags.</p>
2880     */
2881    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2882
2883    /**
2884     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2885     * is compatible with light status bar backgrounds.
2886     *
2887     * <p>For this to take effect, the window must request
2888     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2889     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2890     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2891     *         FLAG_TRANSLUCENT_STATUS}.
2892     *
2893     * @see android.R.attr#windowLightStatusBar
2894     */
2895    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2896
2897    /**
2898     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2899     */
2900    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2901
2902    /**
2903     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2904     */
2905    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2906
2907    /**
2908     * @hide
2909     *
2910     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2911     * out of the public fields to keep the undefined bits out of the developer's way.
2912     *
2913     * Flag to make the status bar not expandable.  Unless you also
2914     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2915     */
2916    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2917
2918    /**
2919     * @hide
2920     *
2921     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2922     * out of the public fields to keep the undefined bits out of the developer's way.
2923     *
2924     * Flag to hide notification icons and scrolling ticker text.
2925     */
2926    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2927
2928    /**
2929     * @hide
2930     *
2931     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2932     * out of the public fields to keep the undefined bits out of the developer's way.
2933     *
2934     * Flag to disable incoming notification alerts.  This will not block
2935     * icons, but it will block sound, vibrating and other visual or aural notifications.
2936     */
2937    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2938
2939    /**
2940     * @hide
2941     *
2942     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2943     * out of the public fields to keep the undefined bits out of the developer's way.
2944     *
2945     * Flag to hide only the scrolling ticker.  Note that
2946     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2947     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2948     */
2949    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2950
2951    /**
2952     * @hide
2953     *
2954     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2955     * out of the public fields to keep the undefined bits out of the developer's way.
2956     *
2957     * Flag to hide the center system info area.
2958     */
2959    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2960
2961    /**
2962     * @hide
2963     *
2964     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2965     * out of the public fields to keep the undefined bits out of the developer's way.
2966     *
2967     * Flag to hide only the home button.  Don't use this
2968     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2969     */
2970    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2971
2972    /**
2973     * @hide
2974     *
2975     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2976     * out of the public fields to keep the undefined bits out of the developer's way.
2977     *
2978     * Flag to hide only the back button. Don't use this
2979     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2980     */
2981    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2982
2983    /**
2984     * @hide
2985     *
2986     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2987     * out of the public fields to keep the undefined bits out of the developer's way.
2988     *
2989     * Flag to hide only the clock.  You might use this if your activity has
2990     * its own clock making the status bar's clock redundant.
2991     */
2992    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2993
2994    /**
2995     * @hide
2996     *
2997     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2998     * out of the public fields to keep the undefined bits out of the developer's way.
2999     *
3000     * Flag to hide only the recent apps button. Don't use this
3001     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3002     */
3003    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3004
3005    /**
3006     * @hide
3007     *
3008     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3009     * out of the public fields to keep the undefined bits out of the developer's way.
3010     *
3011     * Flag to disable the global search gesture. Don't use this
3012     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3013     */
3014    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3015
3016    /**
3017     * @hide
3018     *
3019     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3020     * out of the public fields to keep the undefined bits out of the developer's way.
3021     *
3022     * Flag to specify that the status bar is displayed in transient mode.
3023     */
3024    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3025
3026    /**
3027     * @hide
3028     *
3029     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3030     * out of the public fields to keep the undefined bits out of the developer's way.
3031     *
3032     * Flag to specify that the navigation bar is displayed in transient mode.
3033     */
3034    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3035
3036    /**
3037     * @hide
3038     *
3039     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3040     * out of the public fields to keep the undefined bits out of the developer's way.
3041     *
3042     * Flag to specify that the hidden status bar would like to be shown.
3043     */
3044    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3045
3046    /**
3047     * @hide
3048     *
3049     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3050     * out of the public fields to keep the undefined bits out of the developer's way.
3051     *
3052     * Flag to specify that the hidden navigation bar would like to be shown.
3053     */
3054    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3055
3056    /**
3057     * @hide
3058     *
3059     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3060     * out of the public fields to keep the undefined bits out of the developer's way.
3061     *
3062     * Flag to specify that the status bar is displayed in translucent mode.
3063     */
3064    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3065
3066    /**
3067     * @hide
3068     *
3069     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3070     * out of the public fields to keep the undefined bits out of the developer's way.
3071     *
3072     * Flag to specify that the navigation bar is displayed in translucent mode.
3073     */
3074    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3075
3076    /**
3077     * @hide
3078     *
3079     * Whether Recents is visible or not.
3080     */
3081    public static final int RECENT_APPS_VISIBLE = 0x00004000;
3082
3083    /**
3084     * @hide
3085     *
3086     * Whether the TV's picture-in-picture is visible or not.
3087     */
3088    public static final int TV_PICTURE_IN_PICTURE_VISIBLE = 0x00010000;
3089
3090    /**
3091     * @hide
3092     *
3093     * Makes navigation bar transparent (but not the status bar).
3094     */
3095    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3096
3097    /**
3098     * @hide
3099     *
3100     * Makes status bar transparent (but not the navigation bar).
3101     */
3102    public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
3103
3104    /**
3105     * @hide
3106     *
3107     * Makes both status bar and navigation bar transparent.
3108     */
3109    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3110            | STATUS_BAR_TRANSPARENT;
3111
3112    /**
3113     * @hide
3114     */
3115    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3116
3117    /**
3118     * These are the system UI flags that can be cleared by events outside
3119     * of an application.  Currently this is just the ability to tap on the
3120     * screen while hiding the navigation bar to have it return.
3121     * @hide
3122     */
3123    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3124            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3125            | SYSTEM_UI_FLAG_FULLSCREEN;
3126
3127    /**
3128     * Flags that can impact the layout in relation to system UI.
3129     */
3130    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3131            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3132            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3133
3134    /** @hide */
3135    @IntDef(flag = true,
3136            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3137    @Retention(RetentionPolicy.SOURCE)
3138    public @interface FindViewFlags {}
3139
3140    /**
3141     * Find views that render the specified text.
3142     *
3143     * @see #findViewsWithText(ArrayList, CharSequence, int)
3144     */
3145    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3146
3147    /**
3148     * Find find views that contain the specified content description.
3149     *
3150     * @see #findViewsWithText(ArrayList, CharSequence, int)
3151     */
3152    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3153
3154    /**
3155     * Find views that contain {@link AccessibilityNodeProvider}. Such
3156     * a View is a root of virtual view hierarchy and may contain the searched
3157     * text. If this flag is set Views with providers are automatically
3158     * added and it is a responsibility of the client to call the APIs of
3159     * the provider to determine whether the virtual tree rooted at this View
3160     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3161     * representing the virtual views with this text.
3162     *
3163     * @see #findViewsWithText(ArrayList, CharSequence, int)
3164     *
3165     * @hide
3166     */
3167    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3168
3169    /**
3170     * The undefined cursor position.
3171     *
3172     * @hide
3173     */
3174    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3175
3176    /**
3177     * Indicates that the screen has changed state and is now off.
3178     *
3179     * @see #onScreenStateChanged(int)
3180     */
3181    public static final int SCREEN_STATE_OFF = 0x0;
3182
3183    /**
3184     * Indicates that the screen has changed state and is now on.
3185     *
3186     * @see #onScreenStateChanged(int)
3187     */
3188    public static final int SCREEN_STATE_ON = 0x1;
3189
3190    /**
3191     * Indicates no axis of view scrolling.
3192     */
3193    public static final int SCROLL_AXIS_NONE = 0;
3194
3195    /**
3196     * Indicates scrolling along the horizontal axis.
3197     */
3198    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3199
3200    /**
3201     * Indicates scrolling along the vertical axis.
3202     */
3203    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3204
3205    /**
3206     * Controls the over-scroll mode for this view.
3207     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3208     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3209     * and {@link #OVER_SCROLL_NEVER}.
3210     */
3211    private int mOverScrollMode;
3212
3213    /**
3214     * The parent this view is attached to.
3215     * {@hide}
3216     *
3217     * @see #getParent()
3218     */
3219    protected ViewParent mParent;
3220
3221    /**
3222     * {@hide}
3223     */
3224    AttachInfo mAttachInfo;
3225
3226    /**
3227     * {@hide}
3228     */
3229    @ViewDebug.ExportedProperty(flagMapping = {
3230        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3231                name = "FORCE_LAYOUT"),
3232        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3233                name = "LAYOUT_REQUIRED"),
3234        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3235            name = "DRAWING_CACHE_INVALID", outputIf = false),
3236        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3237        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3238        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3239        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3240    }, formatToHexString = true)
3241    int mPrivateFlags;
3242    int mPrivateFlags2;
3243    int mPrivateFlags3;
3244
3245    /**
3246     * This view's request for the visibility of the status bar.
3247     * @hide
3248     */
3249    @ViewDebug.ExportedProperty(flagMapping = {
3250        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3251                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3252                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3253        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3254                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3255                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3256        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3257                                equals = SYSTEM_UI_FLAG_VISIBLE,
3258                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3259    }, formatToHexString = true)
3260    int mSystemUiVisibility;
3261
3262    /**
3263     * Reference count for transient state.
3264     * @see #setHasTransientState(boolean)
3265     */
3266    int mTransientStateCount = 0;
3267
3268    /**
3269     * Count of how many windows this view has been attached to.
3270     */
3271    int mWindowAttachCount;
3272
3273    /**
3274     * The layout parameters associated with this view and used by the parent
3275     * {@link android.view.ViewGroup} to determine how this view should be
3276     * laid out.
3277     * {@hide}
3278     */
3279    protected ViewGroup.LayoutParams mLayoutParams;
3280
3281    /**
3282     * The view flags hold various views states.
3283     * {@hide}
3284     */
3285    @ViewDebug.ExportedProperty(formatToHexString = true)
3286    int mViewFlags;
3287
3288    static class TransformationInfo {
3289        /**
3290         * The transform matrix for the View. This transform is calculated internally
3291         * based on the translation, rotation, and scale properties.
3292         *
3293         * Do *not* use this variable directly; instead call getMatrix(), which will
3294         * load the value from the View's RenderNode.
3295         */
3296        private final Matrix mMatrix = new Matrix();
3297
3298        /**
3299         * The inverse transform matrix for the View. This transform is calculated
3300         * internally based on the translation, rotation, and scale properties.
3301         *
3302         * Do *not* use this variable directly; instead call getInverseMatrix(),
3303         * which will load the value from the View's RenderNode.
3304         */
3305        private Matrix mInverseMatrix;
3306
3307        /**
3308         * The opacity of the View. This is a value from 0 to 1, where 0 means
3309         * completely transparent and 1 means completely opaque.
3310         */
3311        @ViewDebug.ExportedProperty
3312        float mAlpha = 1f;
3313
3314        /**
3315         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3316         * property only used by transitions, which is composited with the other alpha
3317         * values to calculate the final visual alpha value.
3318         */
3319        float mTransitionAlpha = 1f;
3320    }
3321
3322    TransformationInfo mTransformationInfo;
3323
3324    /**
3325     * Current clip bounds. to which all drawing of this view are constrained.
3326     */
3327    Rect mClipBounds = null;
3328
3329    private boolean mLastIsOpaque;
3330
3331    /**
3332     * The distance in pixels from the left edge of this view's parent
3333     * to the left edge of this view.
3334     * {@hide}
3335     */
3336    @ViewDebug.ExportedProperty(category = "layout")
3337    protected int mLeft;
3338    /**
3339     * The distance in pixels from the left edge of this view's parent
3340     * to the right edge of this view.
3341     * {@hide}
3342     */
3343    @ViewDebug.ExportedProperty(category = "layout")
3344    protected int mRight;
3345    /**
3346     * The distance in pixels from the top edge of this view's parent
3347     * to the top edge of this view.
3348     * {@hide}
3349     */
3350    @ViewDebug.ExportedProperty(category = "layout")
3351    protected int mTop;
3352    /**
3353     * The distance in pixels from the top edge of this view's parent
3354     * to the bottom edge of this view.
3355     * {@hide}
3356     */
3357    @ViewDebug.ExportedProperty(category = "layout")
3358    protected int mBottom;
3359
3360    /**
3361     * The offset, in pixels, by which the content of this view is scrolled
3362     * horizontally.
3363     * {@hide}
3364     */
3365    @ViewDebug.ExportedProperty(category = "scrolling")
3366    protected int mScrollX;
3367    /**
3368     * The offset, in pixels, by which the content of this view is scrolled
3369     * vertically.
3370     * {@hide}
3371     */
3372    @ViewDebug.ExportedProperty(category = "scrolling")
3373    protected int mScrollY;
3374
3375    /**
3376     * The left padding in pixels, that is the distance in pixels between the
3377     * left edge of this view and the left edge of its content.
3378     * {@hide}
3379     */
3380    @ViewDebug.ExportedProperty(category = "padding")
3381    protected int mPaddingLeft = 0;
3382    /**
3383     * The right padding in pixels, that is the distance in pixels between the
3384     * right edge of this view and the right edge of its content.
3385     * {@hide}
3386     */
3387    @ViewDebug.ExportedProperty(category = "padding")
3388    protected int mPaddingRight = 0;
3389    /**
3390     * The top padding in pixels, that is the distance in pixels between the
3391     * top edge of this view and the top edge of its content.
3392     * {@hide}
3393     */
3394    @ViewDebug.ExportedProperty(category = "padding")
3395    protected int mPaddingTop;
3396    /**
3397     * The bottom padding in pixels, that is the distance in pixels between the
3398     * bottom edge of this view and the bottom edge of its content.
3399     * {@hide}
3400     */
3401    @ViewDebug.ExportedProperty(category = "padding")
3402    protected int mPaddingBottom;
3403
3404    /**
3405     * The layout insets in pixels, that is the distance in pixels between the
3406     * visible edges of this view its bounds.
3407     */
3408    private Insets mLayoutInsets;
3409
3410    /**
3411     * Briefly describes the view and is primarily used for accessibility support.
3412     */
3413    private CharSequence mContentDescription;
3414
3415    /**
3416     * Specifies the id of a view for which this view serves as a label for
3417     * accessibility purposes.
3418     */
3419    private int mLabelForId = View.NO_ID;
3420
3421    /**
3422     * Predicate for matching labeled view id with its label for
3423     * accessibility purposes.
3424     */
3425    private MatchLabelForPredicate mMatchLabelForPredicate;
3426
3427    /**
3428     * Specifies a view before which this one is visited in accessibility traversal.
3429     */
3430    private int mAccessibilityTraversalBeforeId = NO_ID;
3431
3432    /**
3433     * Specifies a view after which this one is visited in accessibility traversal.
3434     */
3435    private int mAccessibilityTraversalAfterId = NO_ID;
3436
3437    /**
3438     * Predicate for matching a view by its id.
3439     */
3440    private MatchIdPredicate mMatchIdPredicate;
3441
3442    /**
3443     * Cache the paddingRight set by the user to append to the scrollbar's size.
3444     *
3445     * @hide
3446     */
3447    @ViewDebug.ExportedProperty(category = "padding")
3448    protected int mUserPaddingRight;
3449
3450    /**
3451     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3452     *
3453     * @hide
3454     */
3455    @ViewDebug.ExportedProperty(category = "padding")
3456    protected int mUserPaddingBottom;
3457
3458    /**
3459     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3460     *
3461     * @hide
3462     */
3463    @ViewDebug.ExportedProperty(category = "padding")
3464    protected int mUserPaddingLeft;
3465
3466    /**
3467     * Cache the paddingStart set by the user to append to the scrollbar's size.
3468     *
3469     */
3470    @ViewDebug.ExportedProperty(category = "padding")
3471    int mUserPaddingStart;
3472
3473    /**
3474     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3475     *
3476     */
3477    @ViewDebug.ExportedProperty(category = "padding")
3478    int mUserPaddingEnd;
3479
3480    /**
3481     * Cache initial left padding.
3482     *
3483     * @hide
3484     */
3485    int mUserPaddingLeftInitial;
3486
3487    /**
3488     * Cache initial right padding.
3489     *
3490     * @hide
3491     */
3492    int mUserPaddingRightInitial;
3493
3494    /**
3495     * Default undefined padding
3496     */
3497    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3498
3499    /**
3500     * Cache if a left padding has been defined
3501     */
3502    private boolean mLeftPaddingDefined = false;
3503
3504    /**
3505     * Cache if a right padding has been defined
3506     */
3507    private boolean mRightPaddingDefined = false;
3508
3509    /**
3510     * @hide
3511     */
3512    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3513    /**
3514     * @hide
3515     */
3516    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3517
3518    private LongSparseLongArray mMeasureCache;
3519
3520    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3521    private Drawable mBackground;
3522    private TintInfo mBackgroundTint;
3523
3524    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3525    private ForegroundInfo mForegroundInfo;
3526
3527    private Drawable mScrollIndicatorDrawable;
3528
3529    /**
3530     * RenderNode used for backgrounds.
3531     * <p>
3532     * When non-null and valid, this is expected to contain an up-to-date copy
3533     * of the background drawable. It is cleared on temporary detach, and reset
3534     * on cleanup.
3535     */
3536    private RenderNode mBackgroundRenderNode;
3537
3538    private int mBackgroundResource;
3539    private boolean mBackgroundSizeChanged;
3540
3541    private String mTransitionName;
3542
3543    static class TintInfo {
3544        ColorStateList mTintList;
3545        PorterDuff.Mode mTintMode;
3546        boolean mHasTintMode;
3547        boolean mHasTintList;
3548    }
3549
3550    private static class ForegroundInfo {
3551        private Drawable mDrawable;
3552        private TintInfo mTintInfo;
3553        private int mGravity = Gravity.FILL;
3554        private boolean mInsidePadding = true;
3555        private boolean mBoundsChanged = true;
3556        private final Rect mSelfBounds = new Rect();
3557        private final Rect mOverlayBounds = new Rect();
3558    }
3559
3560    static class ListenerInfo {
3561        /**
3562         * Listener used to dispatch focus change events.
3563         * This field should be made private, so it is hidden from the SDK.
3564         * {@hide}
3565         */
3566        protected OnFocusChangeListener mOnFocusChangeListener;
3567
3568        /**
3569         * Listeners for layout change events.
3570         */
3571        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3572
3573        protected OnScrollChangeListener mOnScrollChangeListener;
3574
3575        /**
3576         * Listeners for attach events.
3577         */
3578        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3579
3580        /**
3581         * Listener used to dispatch click events.
3582         * This field should be made private, so it is hidden from the SDK.
3583         * {@hide}
3584         */
3585        public OnClickListener mOnClickListener;
3586
3587        /**
3588         * Listener used to dispatch long click events.
3589         * This field should be made private, so it is hidden from the SDK.
3590         * {@hide}
3591         */
3592        protected OnLongClickListener mOnLongClickListener;
3593
3594        /**
3595         * Listener used to dispatch context click events. This field should be made private, so it
3596         * is hidden from the SDK.
3597         * {@hide}
3598         */
3599        protected OnContextClickListener mOnContextClickListener;
3600
3601        /**
3602         * Listener used to build the context menu.
3603         * This field should be made private, so it is hidden from the SDK.
3604         * {@hide}
3605         */
3606        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3607
3608        private OnKeyListener mOnKeyListener;
3609
3610        private OnTouchListener mOnTouchListener;
3611
3612        private OnHoverListener mOnHoverListener;
3613
3614        private OnGenericMotionListener mOnGenericMotionListener;
3615
3616        private OnDragListener mOnDragListener;
3617
3618        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3619
3620        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3621    }
3622
3623    ListenerInfo mListenerInfo;
3624
3625    // Temporary values used to hold (x,y) coordinates when delegating from the
3626    // two-arg performLongClick() method to the legacy no-arg version.
3627    private float mLongClickX = Float.NaN;
3628    private float mLongClickY = Float.NaN;
3629
3630    /**
3631     * The application environment this view lives in.
3632     * This field should be made private, so it is hidden from the SDK.
3633     * {@hide}
3634     */
3635    @ViewDebug.ExportedProperty(deepExport = true)
3636    protected Context mContext;
3637
3638    private final Resources mResources;
3639
3640    private ScrollabilityCache mScrollCache;
3641
3642    private int[] mDrawableState = null;
3643
3644    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3645
3646    /**
3647     * Animator that automatically runs based on state changes.
3648     */
3649    private StateListAnimator mStateListAnimator;
3650
3651    /**
3652     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3653     * the user may specify which view to go to next.
3654     */
3655    private int mNextFocusLeftId = View.NO_ID;
3656
3657    /**
3658     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3659     * the user may specify which view to go to next.
3660     */
3661    private int mNextFocusRightId = View.NO_ID;
3662
3663    /**
3664     * When this view has focus and the next focus is {@link #FOCUS_UP},
3665     * the user may specify which view to go to next.
3666     */
3667    private int mNextFocusUpId = View.NO_ID;
3668
3669    /**
3670     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3671     * the user may specify which view to go to next.
3672     */
3673    private int mNextFocusDownId = View.NO_ID;
3674
3675    /**
3676     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3677     * the user may specify which view to go to next.
3678     */
3679    int mNextFocusForwardId = View.NO_ID;
3680
3681    private CheckForLongPress mPendingCheckForLongPress;
3682    private CheckForTap mPendingCheckForTap = null;
3683    private PerformClick mPerformClick;
3684    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3685
3686    private UnsetPressedState mUnsetPressedState;
3687
3688    /**
3689     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3690     * up event while a long press is invoked as soon as the long press duration is reached, so
3691     * a long press could be performed before the tap is checked, in which case the tap's action
3692     * should not be invoked.
3693     */
3694    private boolean mHasPerformedLongPress;
3695
3696    /**
3697     * Whether a context click button is currently pressed down. This is true when the stylus is
3698     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3699     * pressed. This is false once the button is released or if the stylus has been lifted.
3700     */
3701    private boolean mInContextButtonPress;
3702
3703    /**
3704     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3705     * true after a stylus button press has occured, when the next up event should not be recognized
3706     * as a tap.
3707     */
3708    private boolean mIgnoreNextUpEvent;
3709
3710    /**
3711     * The minimum height of the view. We'll try our best to have the height
3712     * of this view to at least this amount.
3713     */
3714    @ViewDebug.ExportedProperty(category = "measurement")
3715    private int mMinHeight;
3716
3717    /**
3718     * The minimum width of the view. We'll try our best to have the width
3719     * of this view to at least this amount.
3720     */
3721    @ViewDebug.ExportedProperty(category = "measurement")
3722    private int mMinWidth;
3723
3724    /**
3725     * The delegate to handle touch events that are physically in this view
3726     * but should be handled by another view.
3727     */
3728    private TouchDelegate mTouchDelegate = null;
3729
3730    /**
3731     * Solid color to use as a background when creating the drawing cache. Enables
3732     * the cache to use 16 bit bitmaps instead of 32 bit.
3733     */
3734    private int mDrawingCacheBackgroundColor = 0;
3735
3736    /**
3737     * Special tree observer used when mAttachInfo is null.
3738     */
3739    private ViewTreeObserver mFloatingTreeObserver;
3740
3741    /**
3742     * Cache the touch slop from the context that created the view.
3743     */
3744    private int mTouchSlop;
3745
3746    /**
3747     * Object that handles automatic animation of view properties.
3748     */
3749    private ViewPropertyAnimator mAnimator = null;
3750
3751    /**
3752     * List of registered FrameMetricsObservers.
3753     */
3754    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
3755
3756    /**
3757     * Flag indicating that a drag can cross window boundaries.  When
3758     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3759     * with this flag set, all visible applications with targetSdkVersion >=
3760     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
3761     * in the drag operation and receive the dragged content.
3762     *
3763     * If this is the only flag set, then the drag recipient will only have access to text data
3764     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3765     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags.
3766     */
3767    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3768
3769    /**
3770     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3771     * request read access to the content URI(s) contained in the {@link ClipData} object.
3772     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3773     */
3774    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3775
3776    /**
3777     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3778     * request write access to the content URI(s) contained in the {@link ClipData} object.
3779     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3780     */
3781    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3782
3783    /**
3784     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3785     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3786     * reboots until explicitly revoked with
3787     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3788     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3789     */
3790    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3791            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3792
3793    /**
3794     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3795     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3796     * match against the original granted URI.
3797     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3798     */
3799    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3800            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3801
3802    /**
3803     * Flag indicating that the drag shadow will be opaque.  When
3804     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3805     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3806     */
3807    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3808
3809    /**
3810     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3811     */
3812    private float mVerticalScrollFactor;
3813
3814    /**
3815     * Position of the vertical scroll bar.
3816     */
3817    private int mVerticalScrollbarPosition;
3818
3819    /**
3820     * Position the scroll bar at the default position as determined by the system.
3821     */
3822    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3823
3824    /**
3825     * Position the scroll bar along the left edge.
3826     */
3827    public static final int SCROLLBAR_POSITION_LEFT = 1;
3828
3829    /**
3830     * Position the scroll bar along the right edge.
3831     */
3832    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3833
3834    /**
3835     * Indicates that the view does not have a layer.
3836     *
3837     * @see #getLayerType()
3838     * @see #setLayerType(int, android.graphics.Paint)
3839     * @see #LAYER_TYPE_SOFTWARE
3840     * @see #LAYER_TYPE_HARDWARE
3841     */
3842    public static final int LAYER_TYPE_NONE = 0;
3843
3844    /**
3845     * <p>Indicates that the view has a software layer. A software layer is backed
3846     * by a bitmap and causes the view to be rendered using Android's software
3847     * rendering pipeline, even if hardware acceleration is enabled.</p>
3848     *
3849     * <p>Software layers have various usages:</p>
3850     * <p>When the application is not using hardware acceleration, a software layer
3851     * is useful to apply a specific color filter and/or blending mode and/or
3852     * translucency to a view and all its children.</p>
3853     * <p>When the application is using hardware acceleration, a software layer
3854     * is useful to render drawing primitives not supported by the hardware
3855     * accelerated pipeline. It can also be used to cache a complex view tree
3856     * into a texture and reduce the complexity of drawing operations. For instance,
3857     * when animating a complex view tree with a translation, a software layer can
3858     * be used to render the view tree only once.</p>
3859     * <p>Software layers should be avoided when the affected view tree updates
3860     * often. Every update will require to re-render the software layer, which can
3861     * potentially be slow (particularly when hardware acceleration is turned on
3862     * since the layer will have to be uploaded into a hardware texture after every
3863     * update.)</p>
3864     *
3865     * @see #getLayerType()
3866     * @see #setLayerType(int, android.graphics.Paint)
3867     * @see #LAYER_TYPE_NONE
3868     * @see #LAYER_TYPE_HARDWARE
3869     */
3870    public static final int LAYER_TYPE_SOFTWARE = 1;
3871
3872    /**
3873     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3874     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3875     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3876     * rendering pipeline, but only if hardware acceleration is turned on for the
3877     * view hierarchy. When hardware acceleration is turned off, hardware layers
3878     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3879     *
3880     * <p>A hardware layer is useful to apply a specific color filter and/or
3881     * blending mode and/or translucency to a view and all its children.</p>
3882     * <p>A hardware layer can be used to cache a complex view tree into a
3883     * texture and reduce the complexity of drawing operations. For instance,
3884     * when animating a complex view tree with a translation, a hardware layer can
3885     * be used to render the view tree only once.</p>
3886     * <p>A hardware layer can also be used to increase the rendering quality when
3887     * rotation transformations are applied on a view. It can also be used to
3888     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3889     *
3890     * @see #getLayerType()
3891     * @see #setLayerType(int, android.graphics.Paint)
3892     * @see #LAYER_TYPE_NONE
3893     * @see #LAYER_TYPE_SOFTWARE
3894     */
3895    public static final int LAYER_TYPE_HARDWARE = 2;
3896
3897    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3898            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3899            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3900            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3901    })
3902    int mLayerType = LAYER_TYPE_NONE;
3903    Paint mLayerPaint;
3904
3905    /**
3906     * Set to true when drawing cache is enabled and cannot be created.
3907     *
3908     * @hide
3909     */
3910    public boolean mCachingFailed;
3911    private Bitmap mDrawingCache;
3912    private Bitmap mUnscaledDrawingCache;
3913
3914    /**
3915     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3916     * <p>
3917     * When non-null and valid, this is expected to contain an up-to-date copy
3918     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3919     * cleanup.
3920     */
3921    final RenderNode mRenderNode;
3922
3923    /**
3924     * Set to true when the view is sending hover accessibility events because it
3925     * is the innermost hovered view.
3926     */
3927    private boolean mSendingHoverAccessibilityEvents;
3928
3929    /**
3930     * Delegate for injecting accessibility functionality.
3931     */
3932    AccessibilityDelegate mAccessibilityDelegate;
3933
3934    /**
3935     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3936     * and add/remove objects to/from the overlay directly through the Overlay methods.
3937     */
3938    ViewOverlay mOverlay;
3939
3940    /**
3941     * The currently active parent view for receiving delegated nested scrolling events.
3942     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3943     * by {@link #stopNestedScroll()} at the same point where we clear
3944     * requestDisallowInterceptTouchEvent.
3945     */
3946    private ViewParent mNestedScrollingParent;
3947
3948    /**
3949     * Consistency verifier for debugging purposes.
3950     * @hide
3951     */
3952    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3953            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3954                    new InputEventConsistencyVerifier(this, 0) : null;
3955
3956    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3957
3958    private int[] mTempNestedScrollConsumed;
3959
3960    /**
3961     * An overlay is going to draw this View instead of being drawn as part of this
3962     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3963     * when this view is invalidated.
3964     */
3965    GhostView mGhostView;
3966
3967    /**
3968     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3969     * @hide
3970     */
3971    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3972    public String[] mAttributes;
3973
3974    /**
3975     * Maps a Resource id to its name.
3976     */
3977    private static SparseArray<String> mAttributeMap;
3978
3979    /**
3980     * Queue of pending runnables. Used to postpone calls to post() until this
3981     * view is attached and has a handler.
3982     */
3983    private HandlerActionQueue mRunQueue;
3984
3985    /**
3986     * The pointer icon when the mouse hovers on this view. The default is null.
3987     */
3988    private PointerIcon mPointerIcon;
3989
3990    /**
3991     * @hide
3992     */
3993    String mStartActivityRequestWho;
3994
3995    @Nullable
3996    private RoundScrollbarRenderer mRoundScrollbarRenderer;
3997
3998    /**
3999     * Simple constructor to use when creating a view from code.
4000     *
4001     * @param context The Context the view is running in, through which it can
4002     *        access the current theme, resources, etc.
4003     */
4004    public View(Context context) {
4005        mContext = context;
4006        mResources = context != null ? context.getResources() : null;
4007        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
4008        // Set some flags defaults
4009        mPrivateFlags2 =
4010                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4011                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4012                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4013                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4014                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4015                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4016        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4017        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4018        mUserPaddingStart = UNDEFINED_PADDING;
4019        mUserPaddingEnd = UNDEFINED_PADDING;
4020        mRenderNode = RenderNode.create(getClass().getName(), this);
4021
4022        if (!sCompatibilityDone && context != null) {
4023            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4024
4025            // Older apps may need this compatibility hack for measurement.
4026            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
4027
4028            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4029            // of whether a layout was requested on that View.
4030            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
4031
4032            Canvas.sCompatibilityRestore = targetSdkVersion < M;
4033
4034            // In M and newer, our widgets can pass a "hint" value in the size
4035            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4036            // know what the expected parent size is going to be, so e.g. list items can size
4037            // themselves at 1/3 the size of their container. It breaks older apps though,
4038            // specifically apps that use some popular open source libraries.
4039            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
4040
4041            // Old versions of the platform would give different results from
4042            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4043            // modes, so we always need to run an additional EXACTLY pass.
4044            sAlwaysRemeasureExactly = targetSdkVersion <= M;
4045
4046            // Prior to N, layout params could change without requiring a
4047            // subsequent call to setLayoutParams() and they would usually
4048            // work. Partial layout breaks this assumption.
4049            sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
4050
4051            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4052            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4053            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
4054
4055            sCompatibilityDone = true;
4056        }
4057    }
4058
4059    /**
4060     * Constructor that is called when inflating a view from XML. This is called
4061     * when a view is being constructed from an XML file, supplying attributes
4062     * that were specified in the XML file. This version uses a default style of
4063     * 0, so the only attribute values applied are those in the Context's Theme
4064     * and the given AttributeSet.
4065     *
4066     * <p>
4067     * The method onFinishInflate() will be called after all children have been
4068     * added.
4069     *
4070     * @param context The Context the view is running in, through which it can
4071     *        access the current theme, resources, etc.
4072     * @param attrs The attributes of the XML tag that is inflating the view.
4073     * @see #View(Context, AttributeSet, int)
4074     */
4075    public View(Context context, @Nullable AttributeSet attrs) {
4076        this(context, attrs, 0);
4077    }
4078
4079    /**
4080     * Perform inflation from XML and apply a class-specific base style from a
4081     * theme attribute. This constructor of View allows subclasses to use their
4082     * own base style when they are inflating. For example, a Button class's
4083     * constructor would call this version of the super class constructor and
4084     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4085     * allows the theme's button style to modify all of the base view attributes
4086     * (in particular its background) as well as the Button class's attributes.
4087     *
4088     * @param context The Context the view is running in, through which it can
4089     *        access the current theme, resources, etc.
4090     * @param attrs The attributes of the XML tag that is inflating the view.
4091     * @param defStyleAttr An attribute in the current theme that contains a
4092     *        reference to a style resource that supplies default values for
4093     *        the view. Can be 0 to not look for defaults.
4094     * @see #View(Context, AttributeSet)
4095     */
4096    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4097        this(context, attrs, defStyleAttr, 0);
4098    }
4099
4100    /**
4101     * Perform inflation from XML and apply a class-specific base style from a
4102     * theme attribute or style resource. This constructor of View allows
4103     * subclasses to use their own base style when they are inflating.
4104     * <p>
4105     * When determining the final value of a particular attribute, there are
4106     * four inputs that come into play:
4107     * <ol>
4108     * <li>Any attribute values in the given AttributeSet.
4109     * <li>The style resource specified in the AttributeSet (named "style").
4110     * <li>The default style specified by <var>defStyleAttr</var>.
4111     * <li>The default style specified by <var>defStyleRes</var>.
4112     * <li>The base values in this theme.
4113     * </ol>
4114     * <p>
4115     * Each of these inputs is considered in-order, with the first listed taking
4116     * precedence over the following ones. In other words, if in the
4117     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4118     * , then the button's text will <em>always</em> be black, regardless of
4119     * what is specified in any of the styles.
4120     *
4121     * @param context The Context the view is running in, through which it can
4122     *        access the current theme, resources, etc.
4123     * @param attrs The attributes of the XML tag that is inflating the view.
4124     * @param defStyleAttr An attribute in the current theme that contains a
4125     *        reference to a style resource that supplies default values for
4126     *        the view. Can be 0 to not look for defaults.
4127     * @param defStyleRes A resource identifier of a style resource that
4128     *        supplies default values for the view, used only if
4129     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4130     *        to not look for defaults.
4131     * @see #View(Context, AttributeSet, int)
4132     */
4133    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4134        this(context);
4135
4136        final TypedArray a = context.obtainStyledAttributes(
4137                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4138
4139        if (mDebugViewAttributes) {
4140            saveAttributeData(attrs, a);
4141        }
4142
4143        Drawable background = null;
4144
4145        int leftPadding = -1;
4146        int topPadding = -1;
4147        int rightPadding = -1;
4148        int bottomPadding = -1;
4149        int startPadding = UNDEFINED_PADDING;
4150        int endPadding = UNDEFINED_PADDING;
4151
4152        int padding = -1;
4153
4154        int viewFlagValues = 0;
4155        int viewFlagMasks = 0;
4156
4157        boolean setScrollContainer = false;
4158
4159        int x = 0;
4160        int y = 0;
4161
4162        float tx = 0;
4163        float ty = 0;
4164        float tz = 0;
4165        float elevation = 0;
4166        float rotation = 0;
4167        float rotationX = 0;
4168        float rotationY = 0;
4169        float sx = 1f;
4170        float sy = 1f;
4171        boolean transformSet = false;
4172
4173        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4174        int overScrollMode = mOverScrollMode;
4175        boolean initializeScrollbars = false;
4176        boolean initializeScrollIndicators = false;
4177
4178        boolean startPaddingDefined = false;
4179        boolean endPaddingDefined = false;
4180        boolean leftPaddingDefined = false;
4181        boolean rightPaddingDefined = false;
4182
4183        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4184
4185        final int N = a.getIndexCount();
4186        for (int i = 0; i < N; i++) {
4187            int attr = a.getIndex(i);
4188            switch (attr) {
4189                case com.android.internal.R.styleable.View_background:
4190                    background = a.getDrawable(attr);
4191                    break;
4192                case com.android.internal.R.styleable.View_padding:
4193                    padding = a.getDimensionPixelSize(attr, -1);
4194                    mUserPaddingLeftInitial = padding;
4195                    mUserPaddingRightInitial = padding;
4196                    leftPaddingDefined = true;
4197                    rightPaddingDefined = true;
4198                    break;
4199                 case com.android.internal.R.styleable.View_paddingLeft:
4200                    leftPadding = a.getDimensionPixelSize(attr, -1);
4201                    mUserPaddingLeftInitial = leftPadding;
4202                    leftPaddingDefined = true;
4203                    break;
4204                case com.android.internal.R.styleable.View_paddingTop:
4205                    topPadding = a.getDimensionPixelSize(attr, -1);
4206                    break;
4207                case com.android.internal.R.styleable.View_paddingRight:
4208                    rightPadding = a.getDimensionPixelSize(attr, -1);
4209                    mUserPaddingRightInitial = rightPadding;
4210                    rightPaddingDefined = true;
4211                    break;
4212                case com.android.internal.R.styleable.View_paddingBottom:
4213                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4214                    break;
4215                case com.android.internal.R.styleable.View_paddingStart:
4216                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4217                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4218                    break;
4219                case com.android.internal.R.styleable.View_paddingEnd:
4220                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4221                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4222                    break;
4223                case com.android.internal.R.styleable.View_scrollX:
4224                    x = a.getDimensionPixelOffset(attr, 0);
4225                    break;
4226                case com.android.internal.R.styleable.View_scrollY:
4227                    y = a.getDimensionPixelOffset(attr, 0);
4228                    break;
4229                case com.android.internal.R.styleable.View_alpha:
4230                    setAlpha(a.getFloat(attr, 1f));
4231                    break;
4232                case com.android.internal.R.styleable.View_transformPivotX:
4233                    setPivotX(a.getDimension(attr, 0));
4234                    break;
4235                case com.android.internal.R.styleable.View_transformPivotY:
4236                    setPivotY(a.getDimension(attr, 0));
4237                    break;
4238                case com.android.internal.R.styleable.View_translationX:
4239                    tx = a.getDimension(attr, 0);
4240                    transformSet = true;
4241                    break;
4242                case com.android.internal.R.styleable.View_translationY:
4243                    ty = a.getDimension(attr, 0);
4244                    transformSet = true;
4245                    break;
4246                case com.android.internal.R.styleable.View_translationZ:
4247                    tz = a.getDimension(attr, 0);
4248                    transformSet = true;
4249                    break;
4250                case com.android.internal.R.styleable.View_elevation:
4251                    elevation = a.getDimension(attr, 0);
4252                    transformSet = true;
4253                    break;
4254                case com.android.internal.R.styleable.View_rotation:
4255                    rotation = a.getFloat(attr, 0);
4256                    transformSet = true;
4257                    break;
4258                case com.android.internal.R.styleable.View_rotationX:
4259                    rotationX = a.getFloat(attr, 0);
4260                    transformSet = true;
4261                    break;
4262                case com.android.internal.R.styleable.View_rotationY:
4263                    rotationY = a.getFloat(attr, 0);
4264                    transformSet = true;
4265                    break;
4266                case com.android.internal.R.styleable.View_scaleX:
4267                    sx = a.getFloat(attr, 1f);
4268                    transformSet = true;
4269                    break;
4270                case com.android.internal.R.styleable.View_scaleY:
4271                    sy = a.getFloat(attr, 1f);
4272                    transformSet = true;
4273                    break;
4274                case com.android.internal.R.styleable.View_id:
4275                    mID = a.getResourceId(attr, NO_ID);
4276                    break;
4277                case com.android.internal.R.styleable.View_tag:
4278                    mTag = a.getText(attr);
4279                    break;
4280                case com.android.internal.R.styleable.View_fitsSystemWindows:
4281                    if (a.getBoolean(attr, false)) {
4282                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4283                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4284                    }
4285                    break;
4286                case com.android.internal.R.styleable.View_focusable:
4287                    if (a.getBoolean(attr, false)) {
4288                        viewFlagValues |= FOCUSABLE;
4289                        viewFlagMasks |= FOCUSABLE_MASK;
4290                    }
4291                    break;
4292                case com.android.internal.R.styleable.View_focusableInTouchMode:
4293                    if (a.getBoolean(attr, false)) {
4294                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4295                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4296                    }
4297                    break;
4298                case com.android.internal.R.styleable.View_clickable:
4299                    if (a.getBoolean(attr, false)) {
4300                        viewFlagValues |= CLICKABLE;
4301                        viewFlagMasks |= CLICKABLE;
4302                    }
4303                    break;
4304                case com.android.internal.R.styleable.View_longClickable:
4305                    if (a.getBoolean(attr, false)) {
4306                        viewFlagValues |= LONG_CLICKABLE;
4307                        viewFlagMasks |= LONG_CLICKABLE;
4308                    }
4309                    break;
4310                case com.android.internal.R.styleable.View_contextClickable:
4311                    if (a.getBoolean(attr, false)) {
4312                        viewFlagValues |= CONTEXT_CLICKABLE;
4313                        viewFlagMasks |= CONTEXT_CLICKABLE;
4314                    }
4315                    break;
4316                case com.android.internal.R.styleable.View_saveEnabled:
4317                    if (!a.getBoolean(attr, true)) {
4318                        viewFlagValues |= SAVE_DISABLED;
4319                        viewFlagMasks |= SAVE_DISABLED_MASK;
4320                    }
4321                    break;
4322                case com.android.internal.R.styleable.View_duplicateParentState:
4323                    if (a.getBoolean(attr, false)) {
4324                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4325                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4326                    }
4327                    break;
4328                case com.android.internal.R.styleable.View_visibility:
4329                    final int visibility = a.getInt(attr, 0);
4330                    if (visibility != 0) {
4331                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4332                        viewFlagMasks |= VISIBILITY_MASK;
4333                    }
4334                    break;
4335                case com.android.internal.R.styleable.View_layoutDirection:
4336                    // Clear any layout direction flags (included resolved bits) already set
4337                    mPrivateFlags2 &=
4338                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4339                    // Set the layout direction flags depending on the value of the attribute
4340                    final int layoutDirection = a.getInt(attr, -1);
4341                    final int value = (layoutDirection != -1) ?
4342                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4343                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4344                    break;
4345                case com.android.internal.R.styleable.View_drawingCacheQuality:
4346                    final int cacheQuality = a.getInt(attr, 0);
4347                    if (cacheQuality != 0) {
4348                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4349                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4350                    }
4351                    break;
4352                case com.android.internal.R.styleable.View_contentDescription:
4353                    setContentDescription(a.getString(attr));
4354                    break;
4355                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4356                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4357                    break;
4358                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4359                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4360                    break;
4361                case com.android.internal.R.styleable.View_labelFor:
4362                    setLabelFor(a.getResourceId(attr, NO_ID));
4363                    break;
4364                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4365                    if (!a.getBoolean(attr, true)) {
4366                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4367                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4368                    }
4369                    break;
4370                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4371                    if (!a.getBoolean(attr, true)) {
4372                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4373                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4374                    }
4375                    break;
4376                case R.styleable.View_scrollbars:
4377                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4378                    if (scrollbars != SCROLLBARS_NONE) {
4379                        viewFlagValues |= scrollbars;
4380                        viewFlagMasks |= SCROLLBARS_MASK;
4381                        initializeScrollbars = true;
4382                    }
4383                    break;
4384                //noinspection deprecation
4385                case R.styleable.View_fadingEdge:
4386                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4387                        // Ignore the attribute starting with ICS
4388                        break;
4389                    }
4390                    // With builds < ICS, fall through and apply fading edges
4391                case R.styleable.View_requiresFadingEdge:
4392                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4393                    if (fadingEdge != FADING_EDGE_NONE) {
4394                        viewFlagValues |= fadingEdge;
4395                        viewFlagMasks |= FADING_EDGE_MASK;
4396                        initializeFadingEdgeInternal(a);
4397                    }
4398                    break;
4399                case R.styleable.View_scrollbarStyle:
4400                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4401                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4402                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4403                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4404                    }
4405                    break;
4406                case R.styleable.View_isScrollContainer:
4407                    setScrollContainer = true;
4408                    if (a.getBoolean(attr, false)) {
4409                        setScrollContainer(true);
4410                    }
4411                    break;
4412                case com.android.internal.R.styleable.View_keepScreenOn:
4413                    if (a.getBoolean(attr, false)) {
4414                        viewFlagValues |= KEEP_SCREEN_ON;
4415                        viewFlagMasks |= KEEP_SCREEN_ON;
4416                    }
4417                    break;
4418                case R.styleable.View_filterTouchesWhenObscured:
4419                    if (a.getBoolean(attr, false)) {
4420                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4421                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4422                    }
4423                    break;
4424                case R.styleable.View_nextFocusLeft:
4425                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4426                    break;
4427                case R.styleable.View_nextFocusRight:
4428                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4429                    break;
4430                case R.styleable.View_nextFocusUp:
4431                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4432                    break;
4433                case R.styleable.View_nextFocusDown:
4434                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4435                    break;
4436                case R.styleable.View_nextFocusForward:
4437                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4438                    break;
4439                case R.styleable.View_minWidth:
4440                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4441                    break;
4442                case R.styleable.View_minHeight:
4443                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4444                    break;
4445                case R.styleable.View_onClick:
4446                    if (context.isRestricted()) {
4447                        throw new IllegalStateException("The android:onClick attribute cannot "
4448                                + "be used within a restricted context");
4449                    }
4450
4451                    final String handlerName = a.getString(attr);
4452                    if (handlerName != null) {
4453                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4454                    }
4455                    break;
4456                case R.styleable.View_overScrollMode:
4457                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4458                    break;
4459                case R.styleable.View_verticalScrollbarPosition:
4460                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4461                    break;
4462                case R.styleable.View_layerType:
4463                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4464                    break;
4465                case R.styleable.View_textDirection:
4466                    // Clear any text direction flag already set
4467                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4468                    // Set the text direction flags depending on the value of the attribute
4469                    final int textDirection = a.getInt(attr, -1);
4470                    if (textDirection != -1) {
4471                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4472                    }
4473                    break;
4474                case R.styleable.View_textAlignment:
4475                    // Clear any text alignment flag already set
4476                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4477                    // Set the text alignment flag depending on the value of the attribute
4478                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4479                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4480                    break;
4481                case R.styleable.View_importantForAccessibility:
4482                    setImportantForAccessibility(a.getInt(attr,
4483                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4484                    break;
4485                case R.styleable.View_accessibilityLiveRegion:
4486                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4487                    break;
4488                case R.styleable.View_transitionName:
4489                    setTransitionName(a.getString(attr));
4490                    break;
4491                case R.styleable.View_nestedScrollingEnabled:
4492                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4493                    break;
4494                case R.styleable.View_stateListAnimator:
4495                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4496                            a.getResourceId(attr, 0)));
4497                    break;
4498                case R.styleable.View_backgroundTint:
4499                    // This will get applied later during setBackground().
4500                    if (mBackgroundTint == null) {
4501                        mBackgroundTint = new TintInfo();
4502                    }
4503                    mBackgroundTint.mTintList = a.getColorStateList(
4504                            R.styleable.View_backgroundTint);
4505                    mBackgroundTint.mHasTintList = true;
4506                    break;
4507                case R.styleable.View_backgroundTintMode:
4508                    // This will get applied later during setBackground().
4509                    if (mBackgroundTint == null) {
4510                        mBackgroundTint = new TintInfo();
4511                    }
4512                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4513                            R.styleable.View_backgroundTintMode, -1), null);
4514                    mBackgroundTint.mHasTintMode = true;
4515                    break;
4516                case R.styleable.View_outlineProvider:
4517                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4518                            PROVIDER_BACKGROUND));
4519                    break;
4520                case R.styleable.View_foreground:
4521                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4522                        setForeground(a.getDrawable(attr));
4523                    }
4524                    break;
4525                case R.styleable.View_foregroundGravity:
4526                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4527                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4528                    }
4529                    break;
4530                case R.styleable.View_foregroundTintMode:
4531                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4532                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4533                    }
4534                    break;
4535                case R.styleable.View_foregroundTint:
4536                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4537                        setForegroundTintList(a.getColorStateList(attr));
4538                    }
4539                    break;
4540                case R.styleable.View_foregroundInsidePadding:
4541                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4542                        if (mForegroundInfo == null) {
4543                            mForegroundInfo = new ForegroundInfo();
4544                        }
4545                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4546                                mForegroundInfo.mInsidePadding);
4547                    }
4548                    break;
4549                case R.styleable.View_scrollIndicators:
4550                    final int scrollIndicators =
4551                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4552                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4553                    if (scrollIndicators != 0) {
4554                        mPrivateFlags3 |= scrollIndicators;
4555                        initializeScrollIndicators = true;
4556                    }
4557                    break;
4558                case R.styleable.View_pointerIcon:
4559                    final int resourceId = a.getResourceId(attr, 0);
4560                    if (resourceId != 0) {
4561                        setPointerIcon(PointerIcon.load(
4562                                context.getResources(), resourceId));
4563                    } else {
4564                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4565                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4566                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
4567                        }
4568                    }
4569                    break;
4570                case R.styleable.View_forceHasOverlappingRendering:
4571                    if (a.peekValue(attr) != null) {
4572                        forceHasOverlappingRendering(a.getBoolean(attr, true));
4573                    }
4574                    break;
4575
4576            }
4577        }
4578
4579        setOverScrollMode(overScrollMode);
4580
4581        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4582        // the resolved layout direction). Those cached values will be used later during padding
4583        // resolution.
4584        mUserPaddingStart = startPadding;
4585        mUserPaddingEnd = endPadding;
4586
4587        if (background != null) {
4588            setBackground(background);
4589        }
4590
4591        // setBackground above will record that padding is currently provided by the background.
4592        // If we have padding specified via xml, record that here instead and use it.
4593        mLeftPaddingDefined = leftPaddingDefined;
4594        mRightPaddingDefined = rightPaddingDefined;
4595
4596        if (padding >= 0) {
4597            leftPadding = padding;
4598            topPadding = padding;
4599            rightPadding = padding;
4600            bottomPadding = padding;
4601            mUserPaddingLeftInitial = padding;
4602            mUserPaddingRightInitial = padding;
4603        }
4604
4605        if (isRtlCompatibilityMode()) {
4606            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4607            // left / right padding are used if defined (meaning here nothing to do). If they are not
4608            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4609            // start / end and resolve them as left / right (layout direction is not taken into account).
4610            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4611            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4612            // defined.
4613            if (!mLeftPaddingDefined && startPaddingDefined) {
4614                leftPadding = startPadding;
4615            }
4616            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4617            if (!mRightPaddingDefined && endPaddingDefined) {
4618                rightPadding = endPadding;
4619            }
4620            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4621        } else {
4622            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4623            // values defined. Otherwise, left /right values are used.
4624            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4625            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4626            // defined.
4627            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4628
4629            if (mLeftPaddingDefined && !hasRelativePadding) {
4630                mUserPaddingLeftInitial = leftPadding;
4631            }
4632            if (mRightPaddingDefined && !hasRelativePadding) {
4633                mUserPaddingRightInitial = rightPadding;
4634            }
4635        }
4636
4637        internalSetPadding(
4638                mUserPaddingLeftInitial,
4639                topPadding >= 0 ? topPadding : mPaddingTop,
4640                mUserPaddingRightInitial,
4641                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4642
4643        if (viewFlagMasks != 0) {
4644            setFlags(viewFlagValues, viewFlagMasks);
4645        }
4646
4647        if (initializeScrollbars) {
4648            initializeScrollbarsInternal(a);
4649        }
4650
4651        if (initializeScrollIndicators) {
4652            initializeScrollIndicatorsInternal();
4653        }
4654
4655        a.recycle();
4656
4657        // Needs to be called after mViewFlags is set
4658        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4659            recomputePadding();
4660        }
4661
4662        if (x != 0 || y != 0) {
4663            scrollTo(x, y);
4664        }
4665
4666        if (transformSet) {
4667            setTranslationX(tx);
4668            setTranslationY(ty);
4669            setTranslationZ(tz);
4670            setElevation(elevation);
4671            setRotation(rotation);
4672            setRotationX(rotationX);
4673            setRotationY(rotationY);
4674            setScaleX(sx);
4675            setScaleY(sy);
4676        }
4677
4678        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4679            setScrollContainer(true);
4680        }
4681
4682        computeOpaqueFlags();
4683    }
4684
4685    /**
4686     * An implementation of OnClickListener that attempts to lazily load a
4687     * named click handling method from a parent or ancestor context.
4688     */
4689    private static class DeclaredOnClickListener implements OnClickListener {
4690        private final View mHostView;
4691        private final String mMethodName;
4692
4693        private Method mResolvedMethod;
4694        private Context mResolvedContext;
4695
4696        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4697            mHostView = hostView;
4698            mMethodName = methodName;
4699        }
4700
4701        @Override
4702        public void onClick(@NonNull View v) {
4703            if (mResolvedMethod == null) {
4704                resolveMethod(mHostView.getContext(), mMethodName);
4705            }
4706
4707            try {
4708                mResolvedMethod.invoke(mResolvedContext, v);
4709            } catch (IllegalAccessException e) {
4710                throw new IllegalStateException(
4711                        "Could not execute non-public method for android:onClick", e);
4712            } catch (InvocationTargetException e) {
4713                throw new IllegalStateException(
4714                        "Could not execute method for android:onClick", e);
4715            }
4716        }
4717
4718        @NonNull
4719        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4720            while (context != null) {
4721                try {
4722                    if (!context.isRestricted()) {
4723                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4724                        if (method != null) {
4725                            mResolvedMethod = method;
4726                            mResolvedContext = context;
4727                            return;
4728                        }
4729                    }
4730                } catch (NoSuchMethodException e) {
4731                    // Failed to find method, keep searching up the hierarchy.
4732                }
4733
4734                if (context instanceof ContextWrapper) {
4735                    context = ((ContextWrapper) context).getBaseContext();
4736                } else {
4737                    // Can't search up the hierarchy, null out and fail.
4738                    context = null;
4739                }
4740            }
4741
4742            final int id = mHostView.getId();
4743            final String idText = id == NO_ID ? "" : " with id '"
4744                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4745            throw new IllegalStateException("Could not find method " + mMethodName
4746                    + "(View) in a parent or ancestor Context for android:onClick "
4747                    + "attribute defined on view " + mHostView.getClass() + idText);
4748        }
4749    }
4750
4751    /**
4752     * Non-public constructor for use in testing
4753     */
4754    View() {
4755        mResources = null;
4756        mRenderNode = RenderNode.create(getClass().getName(), this);
4757    }
4758
4759    private static SparseArray<String> getAttributeMap() {
4760        if (mAttributeMap == null) {
4761            mAttributeMap = new SparseArray<>();
4762        }
4763        return mAttributeMap;
4764    }
4765
4766    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4767        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4768        final int indexCount = t.getIndexCount();
4769        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4770
4771        int i = 0;
4772
4773        // Store raw XML attributes.
4774        for (int j = 0; j < attrsCount; ++j) {
4775            attributes[i] = attrs.getAttributeName(j);
4776            attributes[i + 1] = attrs.getAttributeValue(j);
4777            i += 2;
4778        }
4779
4780        // Store resolved styleable attributes.
4781        final Resources res = t.getResources();
4782        final SparseArray<String> attributeMap = getAttributeMap();
4783        for (int j = 0; j < indexCount; ++j) {
4784            final int index = t.getIndex(j);
4785            if (!t.hasValueOrEmpty(index)) {
4786                // Value is undefined. Skip it.
4787                continue;
4788            }
4789
4790            final int resourceId = t.getResourceId(index, 0);
4791            if (resourceId == 0) {
4792                // Value is not a reference. Skip it.
4793                continue;
4794            }
4795
4796            String resourceName = attributeMap.get(resourceId);
4797            if (resourceName == null) {
4798                try {
4799                    resourceName = res.getResourceName(resourceId);
4800                } catch (Resources.NotFoundException e) {
4801                    resourceName = "0x" + Integer.toHexString(resourceId);
4802                }
4803                attributeMap.put(resourceId, resourceName);
4804            }
4805
4806            attributes[i] = resourceName;
4807            attributes[i + 1] = t.getString(index);
4808            i += 2;
4809        }
4810
4811        // Trim to fit contents.
4812        final String[] trimmed = new String[i];
4813        System.arraycopy(attributes, 0, trimmed, 0, i);
4814        mAttributes = trimmed;
4815    }
4816
4817    public String toString() {
4818        StringBuilder out = new StringBuilder(128);
4819        out.append(getClass().getName());
4820        out.append('{');
4821        out.append(Integer.toHexString(System.identityHashCode(this)));
4822        out.append(' ');
4823        switch (mViewFlags&VISIBILITY_MASK) {
4824            case VISIBLE: out.append('V'); break;
4825            case INVISIBLE: out.append('I'); break;
4826            case GONE: out.append('G'); break;
4827            default: out.append('.'); break;
4828        }
4829        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4830        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4831        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4832        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4833        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4834        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4835        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4836        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4837        out.append(' ');
4838        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4839        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4840        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4841        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4842            out.append('p');
4843        } else {
4844            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4845        }
4846        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4847        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4848        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4849        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4850        out.append(' ');
4851        out.append(mLeft);
4852        out.append(',');
4853        out.append(mTop);
4854        out.append('-');
4855        out.append(mRight);
4856        out.append(',');
4857        out.append(mBottom);
4858        final int id = getId();
4859        if (id != NO_ID) {
4860            out.append(" #");
4861            out.append(Integer.toHexString(id));
4862            final Resources r = mResources;
4863            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4864                try {
4865                    String pkgname;
4866                    switch (id&0xff000000) {
4867                        case 0x7f000000:
4868                            pkgname="app";
4869                            break;
4870                        case 0x01000000:
4871                            pkgname="android";
4872                            break;
4873                        default:
4874                            pkgname = r.getResourcePackageName(id);
4875                            break;
4876                    }
4877                    String typename = r.getResourceTypeName(id);
4878                    String entryname = r.getResourceEntryName(id);
4879                    out.append(" ");
4880                    out.append(pkgname);
4881                    out.append(":");
4882                    out.append(typename);
4883                    out.append("/");
4884                    out.append(entryname);
4885                } catch (Resources.NotFoundException e) {
4886                }
4887            }
4888        }
4889        out.append("}");
4890        return out.toString();
4891    }
4892
4893    /**
4894     * <p>
4895     * Initializes the fading edges from a given set of styled attributes. This
4896     * method should be called by subclasses that need fading edges and when an
4897     * instance of these subclasses is created programmatically rather than
4898     * being inflated from XML. This method is automatically called when the XML
4899     * is inflated.
4900     * </p>
4901     *
4902     * @param a the styled attributes set to initialize the fading edges from
4903     *
4904     * @removed
4905     */
4906    protected void initializeFadingEdge(TypedArray a) {
4907        // This method probably shouldn't have been included in the SDK to begin with.
4908        // It relies on 'a' having been initialized using an attribute filter array that is
4909        // not publicly available to the SDK. The old method has been renamed
4910        // to initializeFadingEdgeInternal and hidden for framework use only;
4911        // this one initializes using defaults to make it safe to call for apps.
4912
4913        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4914
4915        initializeFadingEdgeInternal(arr);
4916
4917        arr.recycle();
4918    }
4919
4920    /**
4921     * <p>
4922     * Initializes the fading edges from a given set of styled attributes. This
4923     * method should be called by subclasses that need fading edges and when an
4924     * instance of these subclasses is created programmatically rather than
4925     * being inflated from XML. This method is automatically called when the XML
4926     * is inflated.
4927     * </p>
4928     *
4929     * @param a the styled attributes set to initialize the fading edges from
4930     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4931     */
4932    protected void initializeFadingEdgeInternal(TypedArray a) {
4933        initScrollCache();
4934
4935        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4936                R.styleable.View_fadingEdgeLength,
4937                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4938    }
4939
4940    /**
4941     * Returns the size of the vertical faded edges used to indicate that more
4942     * content in this view is visible.
4943     *
4944     * @return The size in pixels of the vertical faded edge or 0 if vertical
4945     *         faded edges are not enabled for this view.
4946     * @attr ref android.R.styleable#View_fadingEdgeLength
4947     */
4948    public int getVerticalFadingEdgeLength() {
4949        if (isVerticalFadingEdgeEnabled()) {
4950            ScrollabilityCache cache = mScrollCache;
4951            if (cache != null) {
4952                return cache.fadingEdgeLength;
4953            }
4954        }
4955        return 0;
4956    }
4957
4958    /**
4959     * Set the size of the faded edge used to indicate that more content in this
4960     * view is available.  Will not change whether the fading edge is enabled; use
4961     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4962     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4963     * for the vertical or horizontal fading edges.
4964     *
4965     * @param length The size in pixels of the faded edge used to indicate that more
4966     *        content in this view is visible.
4967     */
4968    public void setFadingEdgeLength(int length) {
4969        initScrollCache();
4970        mScrollCache.fadingEdgeLength = length;
4971    }
4972
4973    /**
4974     * Returns the size of the horizontal faded edges used to indicate that more
4975     * content in this view is visible.
4976     *
4977     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4978     *         faded edges are not enabled for this view.
4979     * @attr ref android.R.styleable#View_fadingEdgeLength
4980     */
4981    public int getHorizontalFadingEdgeLength() {
4982        if (isHorizontalFadingEdgeEnabled()) {
4983            ScrollabilityCache cache = mScrollCache;
4984            if (cache != null) {
4985                return cache.fadingEdgeLength;
4986            }
4987        }
4988        return 0;
4989    }
4990
4991    /**
4992     * Returns the width of the vertical scrollbar.
4993     *
4994     * @return The width in pixels of the vertical scrollbar or 0 if there
4995     *         is no vertical scrollbar.
4996     */
4997    public int getVerticalScrollbarWidth() {
4998        ScrollabilityCache cache = mScrollCache;
4999        if (cache != null) {
5000            ScrollBarDrawable scrollBar = cache.scrollBar;
5001            if (scrollBar != null) {
5002                int size = scrollBar.getSize(true);
5003                if (size <= 0) {
5004                    size = cache.scrollBarSize;
5005                }
5006                return size;
5007            }
5008            return 0;
5009        }
5010        return 0;
5011    }
5012
5013    /**
5014     * Returns the height of the horizontal scrollbar.
5015     *
5016     * @return The height in pixels of the horizontal scrollbar or 0 if
5017     *         there is no horizontal scrollbar.
5018     */
5019    protected int getHorizontalScrollbarHeight() {
5020        ScrollabilityCache cache = mScrollCache;
5021        if (cache != null) {
5022            ScrollBarDrawable scrollBar = cache.scrollBar;
5023            if (scrollBar != null) {
5024                int size = scrollBar.getSize(false);
5025                if (size <= 0) {
5026                    size = cache.scrollBarSize;
5027                }
5028                return size;
5029            }
5030            return 0;
5031        }
5032        return 0;
5033    }
5034
5035    /**
5036     * <p>
5037     * Initializes the scrollbars from a given set of styled attributes. This
5038     * method should be called by subclasses that need scrollbars and when an
5039     * instance of these subclasses is created programmatically rather than
5040     * being inflated from XML. This method is automatically called when the XML
5041     * is inflated.
5042     * </p>
5043     *
5044     * @param a the styled attributes set to initialize the scrollbars from
5045     *
5046     * @removed
5047     */
5048    protected void initializeScrollbars(TypedArray a) {
5049        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5050        // using the View filter array which is not available to the SDK. As such, internal
5051        // framework usage now uses initializeScrollbarsInternal and we grab a default
5052        // TypedArray with the right filter instead here.
5053        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5054
5055        initializeScrollbarsInternal(arr);
5056
5057        // We ignored the method parameter. Recycle the one we actually did use.
5058        arr.recycle();
5059    }
5060
5061    /**
5062     * <p>
5063     * Initializes the scrollbars from a given set of styled attributes. This
5064     * method should be called by subclasses that need scrollbars and when an
5065     * instance of these subclasses is created programmatically rather than
5066     * being inflated from XML. This method is automatically called when the XML
5067     * is inflated.
5068     * </p>
5069     *
5070     * @param a the styled attributes set to initialize the scrollbars from
5071     * @hide
5072     */
5073    protected void initializeScrollbarsInternal(TypedArray a) {
5074        initScrollCache();
5075
5076        final ScrollabilityCache scrollabilityCache = mScrollCache;
5077
5078        if (scrollabilityCache.scrollBar == null) {
5079            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5080            scrollabilityCache.scrollBar.setState(getDrawableState());
5081            scrollabilityCache.scrollBar.setCallback(this);
5082        }
5083
5084        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5085
5086        if (!fadeScrollbars) {
5087            scrollabilityCache.state = ScrollabilityCache.ON;
5088        }
5089        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5090
5091
5092        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5093                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5094                        .getScrollBarFadeDuration());
5095        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5096                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5097                ViewConfiguration.getScrollDefaultDelay());
5098
5099
5100        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5101                com.android.internal.R.styleable.View_scrollbarSize,
5102                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5103
5104        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5105        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5106
5107        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5108        if (thumb != null) {
5109            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5110        }
5111
5112        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5113                false);
5114        if (alwaysDraw) {
5115            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5116        }
5117
5118        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5119        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5120
5121        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5122        if (thumb != null) {
5123            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5124        }
5125
5126        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5127                false);
5128        if (alwaysDraw) {
5129            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5130        }
5131
5132        // Apply layout direction to the new Drawables if needed
5133        final int layoutDirection = getLayoutDirection();
5134        if (track != null) {
5135            track.setLayoutDirection(layoutDirection);
5136        }
5137        if (thumb != null) {
5138            thumb.setLayoutDirection(layoutDirection);
5139        }
5140
5141        // Re-apply user/background padding so that scrollbar(s) get added
5142        resolvePadding();
5143    }
5144
5145    private void initializeScrollIndicatorsInternal() {
5146        // Some day maybe we'll break this into top/left/start/etc. and let the
5147        // client control it. Until then, you can have any scroll indicator you
5148        // want as long as it's a 1dp foreground-colored rectangle.
5149        if (mScrollIndicatorDrawable == null) {
5150            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5151        }
5152    }
5153
5154    /**
5155     * <p>
5156     * Initalizes the scrollability cache if necessary.
5157     * </p>
5158     */
5159    private void initScrollCache() {
5160        if (mScrollCache == null) {
5161            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5162        }
5163    }
5164
5165    private ScrollabilityCache getScrollCache() {
5166        initScrollCache();
5167        return mScrollCache;
5168    }
5169
5170    /**
5171     * Set the position of the vertical scroll bar. Should be one of
5172     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5173     * {@link #SCROLLBAR_POSITION_RIGHT}.
5174     *
5175     * @param position Where the vertical scroll bar should be positioned.
5176     */
5177    public void setVerticalScrollbarPosition(int position) {
5178        if (mVerticalScrollbarPosition != position) {
5179            mVerticalScrollbarPosition = position;
5180            computeOpaqueFlags();
5181            resolvePadding();
5182        }
5183    }
5184
5185    /**
5186     * @return The position where the vertical scroll bar will show, if applicable.
5187     * @see #setVerticalScrollbarPosition(int)
5188     */
5189    public int getVerticalScrollbarPosition() {
5190        return mVerticalScrollbarPosition;
5191    }
5192
5193    boolean isOnScrollbar(float x, float y) {
5194        if (mScrollCache == null) {
5195            return false;
5196        }
5197        x += getScrollX();
5198        y += getScrollY();
5199        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5200            final Rect bounds = mScrollCache.mScrollBarBounds;
5201            getVerticalScrollBarBounds(bounds);
5202            if (bounds.contains((int)x, (int)y)) {
5203                return true;
5204            }
5205        }
5206        if (isHorizontalScrollBarEnabled()) {
5207            final Rect bounds = mScrollCache.mScrollBarBounds;
5208            getHorizontalScrollBarBounds(bounds);
5209            if (bounds.contains((int)x, (int)y)) {
5210                return true;
5211            }
5212        }
5213        return false;
5214    }
5215
5216    boolean isOnScrollbarThumb(float x, float y) {
5217        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5218    }
5219
5220    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5221        if (mScrollCache == null) {
5222            return false;
5223        }
5224        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5225            x += getScrollX();
5226            y += getScrollY();
5227            final Rect bounds = mScrollCache.mScrollBarBounds;
5228            getVerticalScrollBarBounds(bounds);
5229            final int range = computeVerticalScrollRange();
5230            final int offset = computeVerticalScrollOffset();
5231            final int extent = computeVerticalScrollExtent();
5232            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5233                    extent, range);
5234            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5235                    extent, range, offset);
5236            final int thumbTop = bounds.top + thumbOffset;
5237            if (x >= bounds.left && x <= bounds.right && y >= thumbTop
5238                    && y <= thumbTop + thumbLength) {
5239                return true;
5240            }
5241        }
5242        return false;
5243    }
5244
5245    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5246        if (mScrollCache == null) {
5247            return false;
5248        }
5249        if (isHorizontalScrollBarEnabled()) {
5250            x += getScrollX();
5251            y += getScrollY();
5252            final Rect bounds = mScrollCache.mScrollBarBounds;
5253            getHorizontalScrollBarBounds(bounds);
5254            final int range = computeHorizontalScrollRange();
5255            final int offset = computeHorizontalScrollOffset();
5256            final int extent = computeHorizontalScrollExtent();
5257            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5258                    extent, range);
5259            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5260                    extent, range, offset);
5261            final int thumbLeft = bounds.left + thumbOffset;
5262            if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
5263                    && y <= bounds.bottom) {
5264                return true;
5265            }
5266        }
5267        return false;
5268    }
5269
5270    boolean isDraggingScrollBar() {
5271        return mScrollCache != null
5272                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5273    }
5274
5275    /**
5276     * Sets the state of all scroll indicators.
5277     * <p>
5278     * See {@link #setScrollIndicators(int, int)} for usage information.
5279     *
5280     * @param indicators a bitmask of indicators that should be enabled, or
5281     *                   {@code 0} to disable all indicators
5282     * @see #setScrollIndicators(int, int)
5283     * @see #getScrollIndicators()
5284     * @attr ref android.R.styleable#View_scrollIndicators
5285     */
5286    public void setScrollIndicators(@ScrollIndicators int indicators) {
5287        setScrollIndicators(indicators,
5288                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5289    }
5290
5291    /**
5292     * Sets the state of the scroll indicators specified by the mask. To change
5293     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5294     * <p>
5295     * When a scroll indicator is enabled, it will be displayed if the view
5296     * can scroll in the direction of the indicator.
5297     * <p>
5298     * Multiple indicator types may be enabled or disabled by passing the
5299     * logical OR of the desired types. If multiple types are specified, they
5300     * will all be set to the same enabled state.
5301     * <p>
5302     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5303     *
5304     * @param indicators the indicator direction, or the logical OR of multiple
5305     *             indicator directions. One or more of:
5306     *             <ul>
5307     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5308     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5309     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5310     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5311     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5312     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5313     *             </ul>
5314     * @see #setScrollIndicators(int)
5315     * @see #getScrollIndicators()
5316     * @attr ref android.R.styleable#View_scrollIndicators
5317     */
5318    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5319        // Shift and sanitize mask.
5320        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5321        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5322
5323        // Shift and mask indicators.
5324        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5325        indicators &= mask;
5326
5327        // Merge with non-masked flags.
5328        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5329
5330        if (mPrivateFlags3 != updatedFlags) {
5331            mPrivateFlags3 = updatedFlags;
5332
5333            if (indicators != 0) {
5334                initializeScrollIndicatorsInternal();
5335            }
5336            invalidate();
5337        }
5338    }
5339
5340    /**
5341     * Returns a bitmask representing the enabled scroll indicators.
5342     * <p>
5343     * For example, if the top and left scroll indicators are enabled and all
5344     * other indicators are disabled, the return value will be
5345     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5346     * <p>
5347     * To check whether the bottom scroll indicator is enabled, use the value
5348     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5349     *
5350     * @return a bitmask representing the enabled scroll indicators
5351     */
5352    @ScrollIndicators
5353    public int getScrollIndicators() {
5354        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5355                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5356    }
5357
5358    ListenerInfo getListenerInfo() {
5359        if (mListenerInfo != null) {
5360            return mListenerInfo;
5361        }
5362        mListenerInfo = new ListenerInfo();
5363        return mListenerInfo;
5364    }
5365
5366    /**
5367     * Register a callback to be invoked when the scroll X or Y positions of
5368     * this view change.
5369     * <p>
5370     * <b>Note:</b> Some views handle scrolling independently from View and may
5371     * have their own separate listeners for scroll-type events. For example,
5372     * {@link android.widget.ListView ListView} allows clients to register an
5373     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5374     * to listen for changes in list scroll position.
5375     *
5376     * @param l The listener to notify when the scroll X or Y position changes.
5377     * @see android.view.View#getScrollX()
5378     * @see android.view.View#getScrollY()
5379     */
5380    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5381        getListenerInfo().mOnScrollChangeListener = l;
5382    }
5383
5384    /**
5385     * Register a callback to be invoked when focus of this view changed.
5386     *
5387     * @param l The callback that will run.
5388     */
5389    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5390        getListenerInfo().mOnFocusChangeListener = l;
5391    }
5392
5393    /**
5394     * Add a listener that will be called when the bounds of the view change due to
5395     * layout processing.
5396     *
5397     * @param listener The listener that will be called when layout bounds change.
5398     */
5399    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5400        ListenerInfo li = getListenerInfo();
5401        if (li.mOnLayoutChangeListeners == null) {
5402            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5403        }
5404        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5405            li.mOnLayoutChangeListeners.add(listener);
5406        }
5407    }
5408
5409    /**
5410     * Remove a listener for layout changes.
5411     *
5412     * @param listener The listener for layout bounds change.
5413     */
5414    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5415        ListenerInfo li = mListenerInfo;
5416        if (li == null || li.mOnLayoutChangeListeners == null) {
5417            return;
5418        }
5419        li.mOnLayoutChangeListeners.remove(listener);
5420    }
5421
5422    /**
5423     * Add a listener for attach state changes.
5424     *
5425     * This listener will be called whenever this view is attached or detached
5426     * from a window. Remove the listener using
5427     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5428     *
5429     * @param listener Listener to attach
5430     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5431     */
5432    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5433        ListenerInfo li = getListenerInfo();
5434        if (li.mOnAttachStateChangeListeners == null) {
5435            li.mOnAttachStateChangeListeners
5436                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5437        }
5438        li.mOnAttachStateChangeListeners.add(listener);
5439    }
5440
5441    /**
5442     * Remove a listener for attach state changes. The listener will receive no further
5443     * notification of window attach/detach events.
5444     *
5445     * @param listener Listener to remove
5446     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5447     */
5448    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5449        ListenerInfo li = mListenerInfo;
5450        if (li == null || li.mOnAttachStateChangeListeners == null) {
5451            return;
5452        }
5453        li.mOnAttachStateChangeListeners.remove(listener);
5454    }
5455
5456    /**
5457     * Returns the focus-change callback registered for this view.
5458     *
5459     * @return The callback, or null if one is not registered.
5460     */
5461    public OnFocusChangeListener getOnFocusChangeListener() {
5462        ListenerInfo li = mListenerInfo;
5463        return li != null ? li.mOnFocusChangeListener : null;
5464    }
5465
5466    /**
5467     * Register a callback to be invoked when this view is clicked. If this view is not
5468     * clickable, it becomes clickable.
5469     *
5470     * @param l The callback that will run
5471     *
5472     * @see #setClickable(boolean)
5473     */
5474    public void setOnClickListener(@Nullable OnClickListener l) {
5475        if (!isClickable()) {
5476            setClickable(true);
5477        }
5478        getListenerInfo().mOnClickListener = l;
5479    }
5480
5481    /**
5482     * Return whether this view has an attached OnClickListener.  Returns
5483     * true if there is a listener, false if there is none.
5484     */
5485    public boolean hasOnClickListeners() {
5486        ListenerInfo li = mListenerInfo;
5487        return (li != null && li.mOnClickListener != null);
5488    }
5489
5490    /**
5491     * Register a callback to be invoked when this view is clicked and held. If this view is not
5492     * long clickable, it becomes long clickable.
5493     *
5494     * @param l The callback that will run
5495     *
5496     * @see #setLongClickable(boolean)
5497     */
5498    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5499        if (!isLongClickable()) {
5500            setLongClickable(true);
5501        }
5502        getListenerInfo().mOnLongClickListener = l;
5503    }
5504
5505    /**
5506     * Register a callback to be invoked when this view is context clicked. If the view is not
5507     * context clickable, it becomes context clickable.
5508     *
5509     * @param l The callback that will run
5510     * @see #setContextClickable(boolean)
5511     */
5512    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5513        if (!isContextClickable()) {
5514            setContextClickable(true);
5515        }
5516        getListenerInfo().mOnContextClickListener = l;
5517    }
5518
5519    /**
5520     * Register a callback to be invoked when the context menu for this view is
5521     * being built. If this view is not long clickable, it becomes long clickable.
5522     *
5523     * @param l The callback that will run
5524     *
5525     */
5526    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5527        if (!isLongClickable()) {
5528            setLongClickable(true);
5529        }
5530        getListenerInfo().mOnCreateContextMenuListener = l;
5531    }
5532
5533    /**
5534     * Set an observer to collect stats for each frame rendered for this view.
5535     *
5536     * @hide
5537     */
5538    public void addFrameMetricsListener(Window window,
5539            Window.OnFrameMetricsAvailableListener listener,
5540            Handler handler) {
5541        if (mAttachInfo != null) {
5542            if (mAttachInfo.mHardwareRenderer != null) {
5543                if (mFrameMetricsObservers == null) {
5544                    mFrameMetricsObservers = new ArrayList<>();
5545                }
5546
5547                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5548                        handler.getLooper(), listener);
5549                mFrameMetricsObservers.add(fmo);
5550                mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo);
5551            } else {
5552                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5553            }
5554        } else {
5555            if (mFrameMetricsObservers == null) {
5556                mFrameMetricsObservers = new ArrayList<>();
5557            }
5558
5559            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5560                    handler.getLooper(), listener);
5561            mFrameMetricsObservers.add(fmo);
5562        }
5563    }
5564
5565    /**
5566     * Remove observer configured to collect frame stats for this view.
5567     *
5568     * @hide
5569     */
5570    public void removeFrameMetricsListener(
5571            Window.OnFrameMetricsAvailableListener listener) {
5572        ThreadedRenderer renderer = getHardwareRenderer();
5573        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
5574        if (fmo == null) {
5575            throw new IllegalArgumentException(
5576                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
5577        }
5578
5579        if (mFrameMetricsObservers != null) {
5580            mFrameMetricsObservers.remove(fmo);
5581            if (renderer != null) {
5582                renderer.removeFrameMetricsObserver(fmo);
5583            }
5584        }
5585    }
5586
5587    private void registerPendingFrameMetricsObservers() {
5588        if (mFrameMetricsObservers != null) {
5589            ThreadedRenderer renderer = getHardwareRenderer();
5590            if (renderer != null) {
5591                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
5592                    renderer.addFrameMetricsObserver(fmo);
5593                }
5594            } else {
5595                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5596            }
5597        }
5598    }
5599
5600    private FrameMetricsObserver findFrameMetricsObserver(
5601            Window.OnFrameMetricsAvailableListener listener) {
5602        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
5603            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
5604            if (observer.mListener == listener) {
5605                return observer;
5606            }
5607        }
5608
5609        return null;
5610    }
5611
5612    /**
5613     * Call this view's OnClickListener, if it is defined.  Performs all normal
5614     * actions associated with clicking: reporting accessibility event, playing
5615     * a sound, etc.
5616     *
5617     * @return True there was an assigned OnClickListener that was called, false
5618     *         otherwise is returned.
5619     */
5620    public boolean performClick() {
5621        final boolean result;
5622        final ListenerInfo li = mListenerInfo;
5623        if (li != null && li.mOnClickListener != null) {
5624            playSoundEffect(SoundEffectConstants.CLICK);
5625            li.mOnClickListener.onClick(this);
5626            result = true;
5627        } else {
5628            result = false;
5629        }
5630
5631        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5632        return result;
5633    }
5634
5635    /**
5636     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5637     * this only calls the listener, and does not do any associated clicking
5638     * actions like reporting an accessibility event.
5639     *
5640     * @return True there was an assigned OnClickListener that was called, false
5641     *         otherwise is returned.
5642     */
5643    public boolean callOnClick() {
5644        ListenerInfo li = mListenerInfo;
5645        if (li != null && li.mOnClickListener != null) {
5646            li.mOnClickListener.onClick(this);
5647            return true;
5648        }
5649        return false;
5650    }
5651
5652    /**
5653     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5654     * context menu if the OnLongClickListener did not consume the event.
5655     *
5656     * @return {@code true} if one of the above receivers consumed the event,
5657     *         {@code false} otherwise
5658     */
5659    public boolean performLongClick() {
5660        return performLongClickInternal(mLongClickX, mLongClickY);
5661    }
5662
5663    /**
5664     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5665     * context menu if the OnLongClickListener did not consume the event,
5666     * anchoring it to an (x,y) coordinate.
5667     *
5668     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5669     *          to disable anchoring
5670     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5671     *          to disable anchoring
5672     * @return {@code true} if one of the above receivers consumed the event,
5673     *         {@code false} otherwise
5674     */
5675    public boolean performLongClick(float x, float y) {
5676        mLongClickX = x;
5677        mLongClickY = y;
5678        final boolean handled = performLongClick();
5679        mLongClickX = Float.NaN;
5680        mLongClickY = Float.NaN;
5681        return handled;
5682    }
5683
5684    /**
5685     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5686     * context menu if the OnLongClickListener did not consume the event,
5687     * optionally anchoring it to an (x,y) coordinate.
5688     *
5689     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5690     *          to disable anchoring
5691     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5692     *          to disable anchoring
5693     * @return {@code true} if one of the above receivers consumed the event,
5694     *         {@code false} otherwise
5695     */
5696    private boolean performLongClickInternal(float x, float y) {
5697        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5698
5699        boolean handled = false;
5700        final ListenerInfo li = mListenerInfo;
5701        if (li != null && li.mOnLongClickListener != null) {
5702            handled = li.mOnLongClickListener.onLongClick(View.this);
5703        }
5704        if (!handled) {
5705            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5706            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5707        }
5708        if (handled) {
5709            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5710        }
5711        return handled;
5712    }
5713
5714    /**
5715     * Call this view's OnContextClickListener, if it is defined.
5716     *
5717     * @param x the x coordinate of the context click
5718     * @param y the y coordinate of the context click
5719     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5720     *         otherwise.
5721     */
5722    public boolean performContextClick(float x, float y) {
5723        return performContextClick();
5724    }
5725
5726    /**
5727     * Call this view's OnContextClickListener, if it is defined.
5728     *
5729     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5730     *         otherwise.
5731     */
5732    public boolean performContextClick() {
5733        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5734
5735        boolean handled = false;
5736        ListenerInfo li = mListenerInfo;
5737        if (li != null && li.mOnContextClickListener != null) {
5738            handled = li.mOnContextClickListener.onContextClick(View.this);
5739        }
5740        if (handled) {
5741            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5742        }
5743        return handled;
5744    }
5745
5746    /**
5747     * Performs button-related actions during a touch down event.
5748     *
5749     * @param event The event.
5750     * @return True if the down was consumed.
5751     *
5752     * @hide
5753     */
5754    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5755        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5756            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5757            showContextMenu(event.getX(), event.getY());
5758            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5759            return true;
5760        }
5761        return false;
5762    }
5763
5764    /**
5765     * Shows the context menu for this view.
5766     *
5767     * @return {@code true} if the context menu was shown, {@code false}
5768     *         otherwise
5769     * @see #showContextMenu(float, float)
5770     */
5771    public boolean showContextMenu() {
5772        return getParent().showContextMenuForChild(this);
5773    }
5774
5775    /**
5776     * Shows the context menu for this view anchored to the specified
5777     * view-relative coordinate.
5778     *
5779     * @param x the X coordinate in pixels relative to the view to which the
5780     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5781     * @param y the Y coordinate in pixels relative to the view to which the
5782     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5783     * @return {@code true} if the context menu was shown, {@code false}
5784     *         otherwise
5785     */
5786    public boolean showContextMenu(float x, float y) {
5787        return getParent().showContextMenuForChild(this, x, y);
5788    }
5789
5790    /**
5791     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5792     *
5793     * @param callback Callback that will control the lifecycle of the action mode
5794     * @return The new action mode if it is started, null otherwise
5795     *
5796     * @see ActionMode
5797     * @see #startActionMode(android.view.ActionMode.Callback, int)
5798     */
5799    public ActionMode startActionMode(ActionMode.Callback callback) {
5800        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5801    }
5802
5803    /**
5804     * Start an action mode with the given type.
5805     *
5806     * @param callback Callback that will control the lifecycle of the action mode
5807     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5808     * @return The new action mode if it is started, null otherwise
5809     *
5810     * @see ActionMode
5811     */
5812    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5813        ViewParent parent = getParent();
5814        if (parent == null) return null;
5815        try {
5816            return parent.startActionModeForChild(this, callback, type);
5817        } catch (AbstractMethodError ame) {
5818            // Older implementations of custom views might not implement this.
5819            return parent.startActionModeForChild(this, callback);
5820        }
5821    }
5822
5823    /**
5824     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5825     * Context, creating a unique View identifier to retrieve the result.
5826     *
5827     * @param intent The Intent to be started.
5828     * @param requestCode The request code to use.
5829     * @hide
5830     */
5831    public void startActivityForResult(Intent intent, int requestCode) {
5832        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5833        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5834    }
5835
5836    /**
5837     * If this View corresponds to the calling who, dispatches the activity result.
5838     * @param who The identifier for the targeted View to receive the result.
5839     * @param requestCode The integer request code originally supplied to
5840     *                    startActivityForResult(), allowing you to identify who this
5841     *                    result came from.
5842     * @param resultCode The integer result code returned by the child activity
5843     *                   through its setResult().
5844     * @param data An Intent, which can return result data to the caller
5845     *               (various data can be attached to Intent "extras").
5846     * @return {@code true} if the activity result was dispatched.
5847     * @hide
5848     */
5849    public boolean dispatchActivityResult(
5850            String who, int requestCode, int resultCode, Intent data) {
5851        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5852            onActivityResult(requestCode, resultCode, data);
5853            mStartActivityRequestWho = null;
5854            return true;
5855        }
5856        return false;
5857    }
5858
5859    /**
5860     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5861     *
5862     * @param requestCode The integer request code originally supplied to
5863     *                    startActivityForResult(), allowing you to identify who this
5864     *                    result came from.
5865     * @param resultCode The integer result code returned by the child activity
5866     *                   through its setResult().
5867     * @param data An Intent, which can return result data to the caller
5868     *               (various data can be attached to Intent "extras").
5869     * @hide
5870     */
5871    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5872        // Do nothing.
5873    }
5874
5875    /**
5876     * Register a callback to be invoked when a hardware key is pressed in this view.
5877     * Key presses in software input methods will generally not trigger the methods of
5878     * this listener.
5879     * @param l the key listener to attach to this view
5880     */
5881    public void setOnKeyListener(OnKeyListener l) {
5882        getListenerInfo().mOnKeyListener = l;
5883    }
5884
5885    /**
5886     * Register a callback to be invoked when a touch event is sent to this view.
5887     * @param l the touch listener to attach to this view
5888     */
5889    public void setOnTouchListener(OnTouchListener l) {
5890        getListenerInfo().mOnTouchListener = l;
5891    }
5892
5893    /**
5894     * Register a callback to be invoked when a generic motion event is sent to this view.
5895     * @param l the generic motion listener to attach to this view
5896     */
5897    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5898        getListenerInfo().mOnGenericMotionListener = l;
5899    }
5900
5901    /**
5902     * Register a callback to be invoked when a hover event is sent to this view.
5903     * @param l the hover listener to attach to this view
5904     */
5905    public void setOnHoverListener(OnHoverListener l) {
5906        getListenerInfo().mOnHoverListener = l;
5907    }
5908
5909    /**
5910     * Register a drag event listener callback object for this View. The parameter is
5911     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5912     * View, the system calls the
5913     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5914     * @param l An implementation of {@link android.view.View.OnDragListener}.
5915     */
5916    public void setOnDragListener(OnDragListener l) {
5917        getListenerInfo().mOnDragListener = l;
5918    }
5919
5920    /**
5921     * Give this view focus. This will cause
5922     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5923     *
5924     * Note: this does not check whether this {@link View} should get focus, it just
5925     * gives it focus no matter what.  It should only be called internally by framework
5926     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5927     *
5928     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5929     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5930     *        focus moved when requestFocus() is called. It may not always
5931     *        apply, in which case use the default View.FOCUS_DOWN.
5932     * @param previouslyFocusedRect The rectangle of the view that had focus
5933     *        prior in this View's coordinate system.
5934     */
5935    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5936        if (DBG) {
5937            System.out.println(this + " requestFocus()");
5938        }
5939
5940        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5941            mPrivateFlags |= PFLAG_FOCUSED;
5942
5943            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5944
5945            if (mParent != null) {
5946                mParent.requestChildFocus(this, this);
5947            }
5948
5949            if (mAttachInfo != null) {
5950                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5951            }
5952
5953            onFocusChanged(true, direction, previouslyFocusedRect);
5954            refreshDrawableState();
5955        }
5956    }
5957
5958    /**
5959     * Sets this view's preference for reveal behavior when it gains focus.
5960     *
5961     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
5962     * this view would prefer to be brought fully into view when it gains focus.
5963     * For example, a text field that a user is meant to type into. Other views such
5964     * as scrolling containers may prefer to opt-out of this behavior.</p>
5965     *
5966     * <p>The default value for views is true, though subclasses may change this
5967     * based on their preferred behavior.</p>
5968     *
5969     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
5970     *
5971     * @see #getRevealOnFocusHint()
5972     */
5973    public final void setRevealOnFocusHint(boolean revealOnFocus) {
5974        if (revealOnFocus) {
5975            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
5976        } else {
5977            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
5978        }
5979    }
5980
5981    /**
5982     * Returns this view's preference for reveal behavior when it gains focus.
5983     *
5984     * <p>When this method returns true for a child view requesting focus, ancestor
5985     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
5986     * should make a best effort to make the newly focused child fully visible to the user.
5987     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
5988     * other properties affecting visibility to the user as part of the focus change.</p>
5989     *
5990     * @return true if this view would prefer to become fully visible when it gains focus,
5991     *         false if it would prefer not to disrupt scroll positioning
5992     *
5993     * @see #setRevealOnFocusHint(boolean)
5994     */
5995    public final boolean getRevealOnFocusHint() {
5996        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
5997    }
5998
5999    /**
6000     * Populates <code>outRect</code> with the hotspot bounds. By default,
6001     * the hotspot bounds are identical to the screen bounds.
6002     *
6003     * @param outRect rect to populate with hotspot bounds
6004     * @hide Only for internal use by views and widgets.
6005     */
6006    public void getHotspotBounds(Rect outRect) {
6007        final Drawable background = getBackground();
6008        if (background != null) {
6009            background.getHotspotBounds(outRect);
6010        } else {
6011            getBoundsOnScreen(outRect);
6012        }
6013    }
6014
6015    /**
6016     * Request that a rectangle of this view be visible on the screen,
6017     * scrolling if necessary just enough.
6018     *
6019     * <p>A View should call this if it maintains some notion of which part
6020     * of its content is interesting.  For example, a text editing view
6021     * should call this when its cursor moves.
6022     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6023     * It should not be affected by which part of the View is currently visible or its scroll
6024     * position.
6025     *
6026     * @param rectangle The rectangle in the View's content coordinate space
6027     * @return Whether any parent scrolled.
6028     */
6029    public boolean requestRectangleOnScreen(Rect rectangle) {
6030        return requestRectangleOnScreen(rectangle, false);
6031    }
6032
6033    /**
6034     * Request that a rectangle of this view be visible on the screen,
6035     * scrolling if necessary just enough.
6036     *
6037     * <p>A View should call this if it maintains some notion of which part
6038     * of its content is interesting.  For example, a text editing view
6039     * should call this when its cursor moves.
6040     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6041     * It should not be affected by which part of the View is currently visible or its scroll
6042     * position.
6043     * <p>When <code>immediate</code> is set to true, scrolling will not be
6044     * animated.
6045     *
6046     * @param rectangle The rectangle in the View's content coordinate space
6047     * @param immediate True to forbid animated scrolling, false otherwise
6048     * @return Whether any parent scrolled.
6049     */
6050    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6051        if (mParent == null) {
6052            return false;
6053        }
6054
6055        View child = this;
6056
6057        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6058        position.set(rectangle);
6059
6060        ViewParent parent = mParent;
6061        boolean scrolled = false;
6062        while (parent != null) {
6063            rectangle.set((int) position.left, (int) position.top,
6064                    (int) position.right, (int) position.bottom);
6065
6066            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6067
6068            if (!(parent instanceof View)) {
6069                break;
6070            }
6071
6072            // move it from child's content coordinate space to parent's content coordinate space
6073            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6074
6075            child = (View) parent;
6076            parent = child.getParent();
6077        }
6078
6079        return scrolled;
6080    }
6081
6082    /**
6083     * Called when this view wants to give up focus. If focus is cleared
6084     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6085     * <p>
6086     * <strong>Note:</strong> When a View clears focus the framework is trying
6087     * to give focus to the first focusable View from the top. Hence, if this
6088     * View is the first from the top that can take focus, then all callbacks
6089     * related to clearing focus will be invoked after which the framework will
6090     * give focus to this view.
6091     * </p>
6092     */
6093    public void clearFocus() {
6094        if (DBG) {
6095            System.out.println(this + " clearFocus()");
6096        }
6097
6098        clearFocusInternal(null, true, true);
6099    }
6100
6101    /**
6102     * Clears focus from the view, optionally propagating the change up through
6103     * the parent hierarchy and requesting that the root view place new focus.
6104     *
6105     * @param propagate whether to propagate the change up through the parent
6106     *            hierarchy
6107     * @param refocus when propagate is true, specifies whether to request the
6108     *            root view place new focus
6109     */
6110    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6111        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6112            mPrivateFlags &= ~PFLAG_FOCUSED;
6113
6114            if (propagate && mParent != null) {
6115                mParent.clearChildFocus(this);
6116            }
6117
6118            onFocusChanged(false, 0, null);
6119            refreshDrawableState();
6120
6121            if (propagate && (!refocus || !rootViewRequestFocus())) {
6122                notifyGlobalFocusCleared(this);
6123            }
6124        }
6125    }
6126
6127    void notifyGlobalFocusCleared(View oldFocus) {
6128        if (oldFocus != null && mAttachInfo != null) {
6129            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6130        }
6131    }
6132
6133    boolean rootViewRequestFocus() {
6134        final View root = getRootView();
6135        return root != null && root.requestFocus();
6136    }
6137
6138    /**
6139     * Called internally by the view system when a new view is getting focus.
6140     * This is what clears the old focus.
6141     * <p>
6142     * <b>NOTE:</b> The parent view's focused child must be updated manually
6143     * after calling this method. Otherwise, the view hierarchy may be left in
6144     * an inconstent state.
6145     */
6146    void unFocus(View focused) {
6147        if (DBG) {
6148            System.out.println(this + " unFocus()");
6149        }
6150
6151        clearFocusInternal(focused, false, false);
6152    }
6153
6154    /**
6155     * Returns true if this view has focus itself, or is the ancestor of the
6156     * view that has focus.
6157     *
6158     * @return True if this view has or contains focus, false otherwise.
6159     */
6160    @ViewDebug.ExportedProperty(category = "focus")
6161    public boolean hasFocus() {
6162        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6163    }
6164
6165    /**
6166     * Returns true if this view is focusable or if it contains a reachable View
6167     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
6168     * is a View whose parents do not block descendants focus.
6169     *
6170     * Only {@link #VISIBLE} views are considered focusable.
6171     *
6172     * @return True if the view is focusable or if the view contains a focusable
6173     *         View, false otherwise.
6174     *
6175     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6176     * @see ViewGroup#getTouchscreenBlocksFocus()
6177     */
6178    public boolean hasFocusable() {
6179        if (!isFocusableInTouchMode()) {
6180            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6181                final ViewGroup g = (ViewGroup) p;
6182                if (g.shouldBlockFocusForTouchscreen()) {
6183                    return false;
6184                }
6185            }
6186        }
6187        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
6188    }
6189
6190    /**
6191     * Called by the view system when the focus state of this view changes.
6192     * When the focus change event is caused by directional navigation, direction
6193     * and previouslyFocusedRect provide insight into where the focus is coming from.
6194     * When overriding, be sure to call up through to the super class so that
6195     * the standard focus handling will occur.
6196     *
6197     * @param gainFocus True if the View has focus; false otherwise.
6198     * @param direction The direction focus has moved when requestFocus()
6199     *                  is called to give this view focus. Values are
6200     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6201     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6202     *                  It may not always apply, in which case use the default.
6203     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6204     *        system, of the previously focused view.  If applicable, this will be
6205     *        passed in as finer grained information about where the focus is coming
6206     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6207     */
6208    @CallSuper
6209    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6210            @Nullable Rect previouslyFocusedRect) {
6211        if (gainFocus) {
6212            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6213        } else {
6214            notifyViewAccessibilityStateChangedIfNeeded(
6215                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6216        }
6217
6218        InputMethodManager imm = InputMethodManager.peekInstance();
6219        if (!gainFocus) {
6220            if (isPressed()) {
6221                setPressed(false);
6222            }
6223            if (imm != null && mAttachInfo != null
6224                    && mAttachInfo.mHasWindowFocus) {
6225                imm.focusOut(this);
6226            }
6227            onFocusLost();
6228        } else if (imm != null && mAttachInfo != null
6229                && mAttachInfo.mHasWindowFocus) {
6230            imm.focusIn(this);
6231        }
6232
6233        invalidate(true);
6234        ListenerInfo li = mListenerInfo;
6235        if (li != null && li.mOnFocusChangeListener != null) {
6236            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6237        }
6238
6239        if (mAttachInfo != null) {
6240            mAttachInfo.mKeyDispatchState.reset(this);
6241        }
6242    }
6243
6244    /**
6245     * Sends an accessibility event of the given type. If accessibility is
6246     * not enabled this method has no effect. The default implementation calls
6247     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6248     * to populate information about the event source (this View), then calls
6249     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6250     * populate the text content of the event source including its descendants,
6251     * and last calls
6252     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6253     * on its parent to request sending of the event to interested parties.
6254     * <p>
6255     * If an {@link AccessibilityDelegate} has been specified via calling
6256     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6257     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6258     * responsible for handling this call.
6259     * </p>
6260     *
6261     * @param eventType The type of the event to send, as defined by several types from
6262     * {@link android.view.accessibility.AccessibilityEvent}, such as
6263     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6264     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6265     *
6266     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6267     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6268     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6269     * @see AccessibilityDelegate
6270     */
6271    public void sendAccessibilityEvent(int eventType) {
6272        if (mAccessibilityDelegate != null) {
6273            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6274        } else {
6275            sendAccessibilityEventInternal(eventType);
6276        }
6277    }
6278
6279    /**
6280     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6281     * {@link AccessibilityEvent} to make an announcement which is related to some
6282     * sort of a context change for which none of the events representing UI transitions
6283     * is a good fit. For example, announcing a new page in a book. If accessibility
6284     * is not enabled this method does nothing.
6285     *
6286     * @param text The announcement text.
6287     */
6288    public void announceForAccessibility(CharSequence text) {
6289        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6290            AccessibilityEvent event = AccessibilityEvent.obtain(
6291                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6292            onInitializeAccessibilityEvent(event);
6293            event.getText().add(text);
6294            event.setContentDescription(null);
6295            mParent.requestSendAccessibilityEvent(this, event);
6296        }
6297    }
6298
6299    /**
6300     * @see #sendAccessibilityEvent(int)
6301     *
6302     * Note: Called from the default {@link AccessibilityDelegate}.
6303     *
6304     * @hide
6305     */
6306    public void sendAccessibilityEventInternal(int eventType) {
6307        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6308            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6309        }
6310    }
6311
6312    /**
6313     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6314     * takes as an argument an empty {@link AccessibilityEvent} and does not
6315     * perform a check whether accessibility is enabled.
6316     * <p>
6317     * If an {@link AccessibilityDelegate} has been specified via calling
6318     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6319     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6320     * is responsible for handling this call.
6321     * </p>
6322     *
6323     * @param event The event to send.
6324     *
6325     * @see #sendAccessibilityEvent(int)
6326     */
6327    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6328        if (mAccessibilityDelegate != null) {
6329            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6330        } else {
6331            sendAccessibilityEventUncheckedInternal(event);
6332        }
6333    }
6334
6335    /**
6336     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6337     *
6338     * Note: Called from the default {@link AccessibilityDelegate}.
6339     *
6340     * @hide
6341     */
6342    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6343        if (!isShown()) {
6344            return;
6345        }
6346        onInitializeAccessibilityEvent(event);
6347        // Only a subset of accessibility events populates text content.
6348        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6349            dispatchPopulateAccessibilityEvent(event);
6350        }
6351        // In the beginning we called #isShown(), so we know that getParent() is not null.
6352        getParent().requestSendAccessibilityEvent(this, event);
6353    }
6354
6355    /**
6356     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6357     * to its children for adding their text content to the event. Note that the
6358     * event text is populated in a separate dispatch path since we add to the
6359     * event not only the text of the source but also the text of all its descendants.
6360     * A typical implementation will call
6361     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6362     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6363     * on each child. Override this method if custom population of the event text
6364     * content is required.
6365     * <p>
6366     * If an {@link AccessibilityDelegate} has been specified via calling
6367     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6368     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6369     * is responsible for handling this call.
6370     * </p>
6371     * <p>
6372     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6373     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6374     * </p>
6375     *
6376     * @param event The event.
6377     *
6378     * @return True if the event population was completed.
6379     */
6380    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6381        if (mAccessibilityDelegate != null) {
6382            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6383        } else {
6384            return dispatchPopulateAccessibilityEventInternal(event);
6385        }
6386    }
6387
6388    /**
6389     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6390     *
6391     * Note: Called from the default {@link AccessibilityDelegate}.
6392     *
6393     * @hide
6394     */
6395    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6396        onPopulateAccessibilityEvent(event);
6397        return false;
6398    }
6399
6400    /**
6401     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6402     * giving a chance to this View to populate the accessibility event with its
6403     * text content. While this method is free to modify event
6404     * attributes other than text content, doing so should normally be performed in
6405     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6406     * <p>
6407     * Example: Adding formatted date string to an accessibility event in addition
6408     *          to the text added by the super implementation:
6409     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6410     *     super.onPopulateAccessibilityEvent(event);
6411     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6412     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6413     *         mCurrentDate.getTimeInMillis(), flags);
6414     *     event.getText().add(selectedDateUtterance);
6415     * }</pre>
6416     * <p>
6417     * If an {@link AccessibilityDelegate} has been specified via calling
6418     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6419     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6420     * is responsible for handling this call.
6421     * </p>
6422     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6423     * information to the event, in case the default implementation has basic information to add.
6424     * </p>
6425     *
6426     * @param event The accessibility event which to populate.
6427     *
6428     * @see #sendAccessibilityEvent(int)
6429     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6430     */
6431    @CallSuper
6432    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6433        if (mAccessibilityDelegate != null) {
6434            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6435        } else {
6436            onPopulateAccessibilityEventInternal(event);
6437        }
6438    }
6439
6440    /**
6441     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6442     *
6443     * Note: Called from the default {@link AccessibilityDelegate}.
6444     *
6445     * @hide
6446     */
6447    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6448    }
6449
6450    /**
6451     * Initializes an {@link AccessibilityEvent} with information about
6452     * this View which is the event source. In other words, the source of
6453     * an accessibility event is the view whose state change triggered firing
6454     * the event.
6455     * <p>
6456     * Example: Setting the password property of an event in addition
6457     *          to properties set by the super implementation:
6458     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6459     *     super.onInitializeAccessibilityEvent(event);
6460     *     event.setPassword(true);
6461     * }</pre>
6462     * <p>
6463     * If an {@link AccessibilityDelegate} has been specified via calling
6464     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6465     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6466     * is responsible for handling this call.
6467     * </p>
6468     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6469     * information to the event, in case the default implementation has basic information to add.
6470     * </p>
6471     * @param event The event to initialize.
6472     *
6473     * @see #sendAccessibilityEvent(int)
6474     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6475     */
6476    @CallSuper
6477    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6478        if (mAccessibilityDelegate != null) {
6479            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6480        } else {
6481            onInitializeAccessibilityEventInternal(event);
6482        }
6483    }
6484
6485    /**
6486     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6487     *
6488     * Note: Called from the default {@link AccessibilityDelegate}.
6489     *
6490     * @hide
6491     */
6492    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6493        event.setSource(this);
6494        event.setClassName(getAccessibilityClassName());
6495        event.setPackageName(getContext().getPackageName());
6496        event.setEnabled(isEnabled());
6497        event.setContentDescription(mContentDescription);
6498
6499        switch (event.getEventType()) {
6500            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6501                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6502                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6503                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6504                event.setItemCount(focusablesTempList.size());
6505                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6506                if (mAttachInfo != null) {
6507                    focusablesTempList.clear();
6508                }
6509            } break;
6510            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6511                CharSequence text = getIterableTextForAccessibility();
6512                if (text != null && text.length() > 0) {
6513                    event.setFromIndex(getAccessibilitySelectionStart());
6514                    event.setToIndex(getAccessibilitySelectionEnd());
6515                    event.setItemCount(text.length());
6516                }
6517            } break;
6518        }
6519    }
6520
6521    /**
6522     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6523     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6524     * This method is responsible for obtaining an accessibility node info from a
6525     * pool of reusable instances and calling
6526     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6527     * initialize the former.
6528     * <p>
6529     * Note: The client is responsible for recycling the obtained instance by calling
6530     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6531     * </p>
6532     *
6533     * @return A populated {@link AccessibilityNodeInfo}.
6534     *
6535     * @see AccessibilityNodeInfo
6536     */
6537    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6538        if (mAccessibilityDelegate != null) {
6539            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6540        } else {
6541            return createAccessibilityNodeInfoInternal();
6542        }
6543    }
6544
6545    /**
6546     * @see #createAccessibilityNodeInfo()
6547     *
6548     * @hide
6549     */
6550    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6551        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6552        if (provider != null) {
6553            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6554        } else {
6555            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6556            onInitializeAccessibilityNodeInfo(info);
6557            return info;
6558        }
6559    }
6560
6561    /**
6562     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6563     * The base implementation sets:
6564     * <ul>
6565     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6566     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6567     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6568     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6569     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6570     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6571     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6572     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6573     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6574     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6575     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6576     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6577     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6578     * </ul>
6579     * <p>
6580     * Subclasses should override this method, call the super implementation,
6581     * and set additional attributes.
6582     * </p>
6583     * <p>
6584     * If an {@link AccessibilityDelegate} has been specified via calling
6585     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6586     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6587     * is responsible for handling this call.
6588     * </p>
6589     *
6590     * @param info The instance to initialize.
6591     */
6592    @CallSuper
6593    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6594        if (mAccessibilityDelegate != null) {
6595            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6596        } else {
6597            onInitializeAccessibilityNodeInfoInternal(info);
6598        }
6599    }
6600
6601    /**
6602     * Gets the location of this view in screen coordinates.
6603     *
6604     * @param outRect The output location
6605     * @hide
6606     */
6607    public void getBoundsOnScreen(Rect outRect) {
6608        getBoundsOnScreen(outRect, false);
6609    }
6610
6611    /**
6612     * Gets the location of this view in screen coordinates.
6613     *
6614     * @param outRect The output location
6615     * @param clipToParent Whether to clip child bounds to the parent ones.
6616     * @hide
6617     */
6618    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6619        if (mAttachInfo == null) {
6620            return;
6621        }
6622
6623        RectF position = mAttachInfo.mTmpTransformRect;
6624        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6625
6626        if (!hasIdentityMatrix()) {
6627            getMatrix().mapRect(position);
6628        }
6629
6630        position.offset(mLeft, mTop);
6631
6632        ViewParent parent = mParent;
6633        while (parent instanceof View) {
6634            View parentView = (View) parent;
6635
6636            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6637
6638            if (clipToParent) {
6639                position.left = Math.max(position.left, 0);
6640                position.top = Math.max(position.top, 0);
6641                position.right = Math.min(position.right, parentView.getWidth());
6642                position.bottom = Math.min(position.bottom, parentView.getHeight());
6643            }
6644
6645            if (!parentView.hasIdentityMatrix()) {
6646                parentView.getMatrix().mapRect(position);
6647            }
6648
6649            position.offset(parentView.mLeft, parentView.mTop);
6650
6651            parent = parentView.mParent;
6652        }
6653
6654        if (parent instanceof ViewRootImpl) {
6655            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6656            position.offset(0, -viewRootImpl.mCurScrollY);
6657        }
6658
6659        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6660
6661        outRect.set(Math.round(position.left), Math.round(position.top),
6662                Math.round(position.right), Math.round(position.bottom));
6663    }
6664
6665    /**
6666     * Return the class name of this object to be used for accessibility purposes.
6667     * Subclasses should only override this if they are implementing something that
6668     * should be seen as a completely new class of view when used by accessibility,
6669     * unrelated to the class it is deriving from.  This is used to fill in
6670     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6671     */
6672    public CharSequence getAccessibilityClassName() {
6673        return View.class.getName();
6674    }
6675
6676    /**
6677     * Called when assist structure is being retrieved from a view as part of
6678     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6679     * @param structure Fill in with structured view data.  The default implementation
6680     * fills in all data that can be inferred from the view itself.
6681     */
6682    public void onProvideStructure(ViewStructure structure) {
6683        final int id = mID;
6684        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6685                && (id&0x0000ffff) != 0) {
6686            String pkg, type, entry;
6687            try {
6688                final Resources res = getResources();
6689                entry = res.getResourceEntryName(id);
6690                type = res.getResourceTypeName(id);
6691                pkg = res.getResourcePackageName(id);
6692            } catch (Resources.NotFoundException e) {
6693                entry = type = pkg = null;
6694            }
6695            structure.setId(id, pkg, type, entry);
6696        } else {
6697            structure.setId(id, null, null, null);
6698        }
6699        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6700        if (!hasIdentityMatrix()) {
6701            structure.setTransformation(getMatrix());
6702        }
6703        structure.setElevation(getZ());
6704        structure.setVisibility(getVisibility());
6705        structure.setEnabled(isEnabled());
6706        if (isClickable()) {
6707            structure.setClickable(true);
6708        }
6709        if (isFocusable()) {
6710            structure.setFocusable(true);
6711        }
6712        if (isFocused()) {
6713            structure.setFocused(true);
6714        }
6715        if (isAccessibilityFocused()) {
6716            structure.setAccessibilityFocused(true);
6717        }
6718        if (isSelected()) {
6719            structure.setSelected(true);
6720        }
6721        if (isActivated()) {
6722            structure.setActivated(true);
6723        }
6724        if (isLongClickable()) {
6725            structure.setLongClickable(true);
6726        }
6727        if (this instanceof Checkable) {
6728            structure.setCheckable(true);
6729            if (((Checkable)this).isChecked()) {
6730                structure.setChecked(true);
6731            }
6732        }
6733        if (isContextClickable()) {
6734            structure.setContextClickable(true);
6735        }
6736        structure.setClassName(getAccessibilityClassName().toString());
6737        structure.setContentDescription(getContentDescription());
6738    }
6739
6740    /**
6741     * Called when assist structure is being retrieved from a view as part of
6742     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6743     * generate additional virtual structure under this view.  The defaullt implementation
6744     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6745     * view's virtual accessibility nodes, if any.  You can override this for a more
6746     * optimal implementation providing this data.
6747     */
6748    public void onProvideVirtualStructure(ViewStructure structure) {
6749        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6750        if (provider != null) {
6751            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6752            structure.setChildCount(1);
6753            ViewStructure root = structure.newChild(0);
6754            populateVirtualStructure(root, provider, info);
6755            info.recycle();
6756        }
6757    }
6758
6759    private void populateVirtualStructure(ViewStructure structure,
6760            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6761        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6762                null, null, null);
6763        Rect rect = structure.getTempRect();
6764        info.getBoundsInParent(rect);
6765        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6766        structure.setVisibility(VISIBLE);
6767        structure.setEnabled(info.isEnabled());
6768        if (info.isClickable()) {
6769            structure.setClickable(true);
6770        }
6771        if (info.isFocusable()) {
6772            structure.setFocusable(true);
6773        }
6774        if (info.isFocused()) {
6775            structure.setFocused(true);
6776        }
6777        if (info.isAccessibilityFocused()) {
6778            structure.setAccessibilityFocused(true);
6779        }
6780        if (info.isSelected()) {
6781            structure.setSelected(true);
6782        }
6783        if (info.isLongClickable()) {
6784            structure.setLongClickable(true);
6785        }
6786        if (info.isCheckable()) {
6787            structure.setCheckable(true);
6788            if (info.isChecked()) {
6789                structure.setChecked(true);
6790            }
6791        }
6792        if (info.isContextClickable()) {
6793            structure.setContextClickable(true);
6794        }
6795        CharSequence cname = info.getClassName();
6796        structure.setClassName(cname != null ? cname.toString() : null);
6797        structure.setContentDescription(info.getContentDescription());
6798        if (info.getText() != null || info.getError() != null) {
6799            structure.setText(info.getText(), info.getTextSelectionStart(),
6800                    info.getTextSelectionEnd());
6801        }
6802        final int NCHILDREN = info.getChildCount();
6803        if (NCHILDREN > 0) {
6804            structure.setChildCount(NCHILDREN);
6805            for (int i=0; i<NCHILDREN; i++) {
6806                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6807                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6808                ViewStructure child = structure.newChild(i);
6809                populateVirtualStructure(child, provider, cinfo);
6810                cinfo.recycle();
6811            }
6812        }
6813    }
6814
6815    /**
6816     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6817     * implementation calls {@link #onProvideStructure} and
6818     * {@link #onProvideVirtualStructure}.
6819     */
6820    public void dispatchProvideStructure(ViewStructure structure) {
6821        if (!isAssistBlocked()) {
6822            onProvideStructure(structure);
6823            onProvideVirtualStructure(structure);
6824        } else {
6825            structure.setClassName(getAccessibilityClassName().toString());
6826            structure.setAssistBlocked(true);
6827        }
6828    }
6829
6830    /**
6831     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6832     *
6833     * Note: Called from the default {@link AccessibilityDelegate}.
6834     *
6835     * @hide
6836     */
6837    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6838        if (mAttachInfo == null) {
6839            return;
6840        }
6841
6842        Rect bounds = mAttachInfo.mTmpInvalRect;
6843
6844        getDrawingRect(bounds);
6845        info.setBoundsInParent(bounds);
6846
6847        getBoundsOnScreen(bounds, true);
6848        info.setBoundsInScreen(bounds);
6849
6850        ViewParent parent = getParentForAccessibility();
6851        if (parent instanceof View) {
6852            info.setParent((View) parent);
6853        }
6854
6855        if (mID != View.NO_ID) {
6856            View rootView = getRootView();
6857            if (rootView == null) {
6858                rootView = this;
6859            }
6860
6861            View label = rootView.findLabelForView(this, mID);
6862            if (label != null) {
6863                info.setLabeledBy(label);
6864            }
6865
6866            if ((mAttachInfo.mAccessibilityFetchFlags
6867                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6868                    && Resources.resourceHasPackage(mID)) {
6869                try {
6870                    String viewId = getResources().getResourceName(mID);
6871                    info.setViewIdResourceName(viewId);
6872                } catch (Resources.NotFoundException nfe) {
6873                    /* ignore */
6874                }
6875            }
6876        }
6877
6878        if (mLabelForId != View.NO_ID) {
6879            View rootView = getRootView();
6880            if (rootView == null) {
6881                rootView = this;
6882            }
6883            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6884            if (labeled != null) {
6885                info.setLabelFor(labeled);
6886            }
6887        }
6888
6889        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6890            View rootView = getRootView();
6891            if (rootView == null) {
6892                rootView = this;
6893            }
6894            View next = rootView.findViewInsideOutShouldExist(this,
6895                    mAccessibilityTraversalBeforeId);
6896            if (next != null && next.includeForAccessibility()) {
6897                info.setTraversalBefore(next);
6898            }
6899        }
6900
6901        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6902            View rootView = getRootView();
6903            if (rootView == null) {
6904                rootView = this;
6905            }
6906            View next = rootView.findViewInsideOutShouldExist(this,
6907                    mAccessibilityTraversalAfterId);
6908            if (next != null && next.includeForAccessibility()) {
6909                info.setTraversalAfter(next);
6910            }
6911        }
6912
6913        info.setVisibleToUser(isVisibleToUser());
6914
6915        if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags
6916                & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) {
6917            info.setImportantForAccessibility(isImportantForAccessibility());
6918        } else {
6919            info.setImportantForAccessibility(true);
6920        }
6921
6922        info.setPackageName(mContext.getPackageName());
6923        info.setClassName(getAccessibilityClassName());
6924        info.setContentDescription(getContentDescription());
6925
6926        info.setEnabled(isEnabled());
6927        info.setClickable(isClickable());
6928        info.setFocusable(isFocusable());
6929        info.setFocused(isFocused());
6930        info.setAccessibilityFocused(isAccessibilityFocused());
6931        info.setSelected(isSelected());
6932        info.setLongClickable(isLongClickable());
6933        info.setContextClickable(isContextClickable());
6934        info.setLiveRegion(getAccessibilityLiveRegion());
6935
6936        // TODO: These make sense only if we are in an AdapterView but all
6937        // views can be selected. Maybe from accessibility perspective
6938        // we should report as selectable view in an AdapterView.
6939        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6940        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6941
6942        if (isFocusable()) {
6943            if (isFocused()) {
6944                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6945            } else {
6946                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6947            }
6948        }
6949
6950        if (!isAccessibilityFocused()) {
6951            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6952        } else {
6953            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6954        }
6955
6956        if (isClickable() && isEnabled()) {
6957            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6958        }
6959
6960        if (isLongClickable() && isEnabled()) {
6961            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6962        }
6963
6964        if (isContextClickable() && isEnabled()) {
6965            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6966        }
6967
6968        CharSequence text = getIterableTextForAccessibility();
6969        if (text != null && text.length() > 0) {
6970            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6971
6972            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6973            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6974            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6975            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6976                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6977                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6978        }
6979
6980        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6981        populateAccessibilityNodeInfoDrawingOrderInParent(info);
6982    }
6983
6984    /**
6985     * Determine the order in which this view will be drawn relative to its siblings for a11y
6986     *
6987     * @param info The info whose drawing order should be populated
6988     */
6989    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
6990        /*
6991         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
6992         * drawing order may not be well-defined, and some Views with custom drawing order may
6993         * not be initialized sufficiently to respond properly getChildDrawingOrder.
6994         */
6995        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
6996            info.setDrawingOrder(0);
6997            return;
6998        }
6999        int drawingOrderInParent = 1;
7000        // Iterate up the hierarchy if parents are not important for a11y
7001        View viewAtDrawingLevel = this;
7002        final ViewParent parent = getParentForAccessibility();
7003        while (viewAtDrawingLevel != parent) {
7004            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7005            if (!(currentParent instanceof ViewGroup)) {
7006                // Should only happen for the Decor
7007                drawingOrderInParent = 0;
7008                break;
7009            } else {
7010                final ViewGroup parentGroup = (ViewGroup) currentParent;
7011                final int childCount = parentGroup.getChildCount();
7012                if (childCount > 1) {
7013                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7014                    if (preorderedList != null) {
7015                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7016                        for (int i = 0; i < childDrawIndex; i++) {
7017                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7018                        }
7019                    } else {
7020                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7021                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7022                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7023                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7024                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7025                        if (childDrawIndex != 0) {
7026                            for (int i = 0; i < numChildrenToIterate; i++) {
7027                                final int otherDrawIndex = (customOrder ?
7028                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7029                                if (otherDrawIndex < childDrawIndex) {
7030                                    drawingOrderInParent +=
7031                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7032                                }
7033                            }
7034                        }
7035                    }
7036                }
7037            }
7038            viewAtDrawingLevel = (View) currentParent;
7039        }
7040        info.setDrawingOrder(drawingOrderInParent);
7041    }
7042
7043    private static int numViewsForAccessibility(View view) {
7044        if (view != null) {
7045            if (view.includeForAccessibility()) {
7046                return 1;
7047            } else if (view instanceof ViewGroup) {
7048                return ((ViewGroup) view).getNumChildrenForAccessibility();
7049            }
7050        }
7051        return 0;
7052    }
7053
7054    private View findLabelForView(View view, int labeledId) {
7055        if (mMatchLabelForPredicate == null) {
7056            mMatchLabelForPredicate = new MatchLabelForPredicate();
7057        }
7058        mMatchLabelForPredicate.mLabeledId = labeledId;
7059        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7060    }
7061
7062    /**
7063     * Computes whether this view is visible to the user. Such a view is
7064     * attached, visible, all its predecessors are visible, it is not clipped
7065     * entirely by its predecessors, and has an alpha greater than zero.
7066     *
7067     * @return Whether the view is visible on the screen.
7068     *
7069     * @hide
7070     */
7071    protected boolean isVisibleToUser() {
7072        return isVisibleToUser(null);
7073    }
7074
7075    /**
7076     * Computes whether the given portion of this view is visible to the user.
7077     * Such a view is attached, visible, all its predecessors are visible,
7078     * has an alpha greater than zero, and the specified portion is not
7079     * clipped entirely by its predecessors.
7080     *
7081     * @param boundInView the portion of the view to test; coordinates should be relative; may be
7082     *                    <code>null</code>, and the entire view will be tested in this case.
7083     *                    When <code>true</code> is returned by the function, the actual visible
7084     *                    region will be stored in this parameter; that is, if boundInView is fully
7085     *                    contained within the view, no modification will be made, otherwise regions
7086     *                    outside of the visible area of the view will be clipped.
7087     *
7088     * @return Whether the specified portion of the view is visible on the screen.
7089     *
7090     * @hide
7091     */
7092    protected boolean isVisibleToUser(Rect boundInView) {
7093        if (mAttachInfo != null) {
7094            // Attached to invisible window means this view is not visible.
7095            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
7096                return false;
7097            }
7098            // An invisible predecessor or one with alpha zero means
7099            // that this view is not visible to the user.
7100            Object current = this;
7101            while (current instanceof View) {
7102                View view = (View) current;
7103                // We have attach info so this view is attached and there is no
7104                // need to check whether we reach to ViewRootImpl on the way up.
7105                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
7106                        view.getVisibility() != VISIBLE) {
7107                    return false;
7108                }
7109                current = view.mParent;
7110            }
7111            // Check if the view is entirely covered by its predecessors.
7112            Rect visibleRect = mAttachInfo.mTmpInvalRect;
7113            Point offset = mAttachInfo.mPoint;
7114            if (!getGlobalVisibleRect(visibleRect, offset)) {
7115                return false;
7116            }
7117            // Check if the visible portion intersects the rectangle of interest.
7118            if (boundInView != null) {
7119                visibleRect.offset(-offset.x, -offset.y);
7120                return boundInView.intersect(visibleRect);
7121            }
7122            return true;
7123        }
7124        return false;
7125    }
7126
7127    /**
7128     * Returns the delegate for implementing accessibility support via
7129     * composition. For more details see {@link AccessibilityDelegate}.
7130     *
7131     * @return The delegate, or null if none set.
7132     *
7133     * @hide
7134     */
7135    public AccessibilityDelegate getAccessibilityDelegate() {
7136        return mAccessibilityDelegate;
7137    }
7138
7139    /**
7140     * Sets a delegate for implementing accessibility support via composition
7141     * (as opposed to inheritance). For more details, see
7142     * {@link AccessibilityDelegate}.
7143     * <p>
7144     * <strong>Note:</strong> On platform versions prior to
7145     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
7146     * views in the {@code android.widget.*} package are called <i>before</i>
7147     * host methods. This prevents certain properties such as class name from
7148     * being modified by overriding
7149     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
7150     * as any changes will be overwritten by the host class.
7151     * <p>
7152     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
7153     * methods are called <i>after</i> host methods, which all properties to be
7154     * modified without being overwritten by the host class.
7155     *
7156     * @param delegate the object to which accessibility method calls should be
7157     *                 delegated
7158     * @see AccessibilityDelegate
7159     */
7160    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
7161        mAccessibilityDelegate = delegate;
7162    }
7163
7164    /**
7165     * Gets the provider for managing a virtual view hierarchy rooted at this View
7166     * and reported to {@link android.accessibilityservice.AccessibilityService}s
7167     * that explore the window content.
7168     * <p>
7169     * If this method returns an instance, this instance is responsible for managing
7170     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
7171     * View including the one representing the View itself. Similarly the returned
7172     * instance is responsible for performing accessibility actions on any virtual
7173     * view or the root view itself.
7174     * </p>
7175     * <p>
7176     * If an {@link AccessibilityDelegate} has been specified via calling
7177     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7178     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
7179     * is responsible for handling this call.
7180     * </p>
7181     *
7182     * @return The provider.
7183     *
7184     * @see AccessibilityNodeProvider
7185     */
7186    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
7187        if (mAccessibilityDelegate != null) {
7188            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
7189        } else {
7190            return null;
7191        }
7192    }
7193
7194    /**
7195     * Gets the unique identifier of this view on the screen for accessibility purposes.
7196     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
7197     *
7198     * @return The view accessibility id.
7199     *
7200     * @hide
7201     */
7202    public int getAccessibilityViewId() {
7203        if (mAccessibilityViewId == NO_ID) {
7204            mAccessibilityViewId = sNextAccessibilityViewId++;
7205        }
7206        return mAccessibilityViewId;
7207    }
7208
7209    /**
7210     * Gets the unique identifier of the window in which this View reseides.
7211     *
7212     * @return The window accessibility id.
7213     *
7214     * @hide
7215     */
7216    public int getAccessibilityWindowId() {
7217        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
7218                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
7219    }
7220
7221    /**
7222     * Returns the {@link View}'s content description.
7223     * <p>
7224     * <strong>Note:</strong> Do not override this method, as it will have no
7225     * effect on the content description presented to accessibility services.
7226     * You must call {@link #setContentDescription(CharSequence)} to modify the
7227     * content description.
7228     *
7229     * @return the content description
7230     * @see #setContentDescription(CharSequence)
7231     * @attr ref android.R.styleable#View_contentDescription
7232     */
7233    @ViewDebug.ExportedProperty(category = "accessibility")
7234    public CharSequence getContentDescription() {
7235        return mContentDescription;
7236    }
7237
7238    /**
7239     * Sets the {@link View}'s content description.
7240     * <p>
7241     * A content description briefly describes the view and is primarily used
7242     * for accessibility support to determine how a view should be presented to
7243     * the user. In the case of a view with no textual representation, such as
7244     * {@link android.widget.ImageButton}, a useful content description
7245     * explains what the view does. For example, an image button with a phone
7246     * icon that is used to place a call may use "Call" as its content
7247     * description. An image of a floppy disk that is used to save a file may
7248     * use "Save".
7249     *
7250     * @param contentDescription The content description.
7251     * @see #getContentDescription()
7252     * @attr ref android.R.styleable#View_contentDescription
7253     */
7254    @RemotableViewMethod
7255    public void setContentDescription(CharSequence contentDescription) {
7256        if (mContentDescription == null) {
7257            if (contentDescription == null) {
7258                return;
7259            }
7260        } else if (mContentDescription.equals(contentDescription)) {
7261            return;
7262        }
7263        mContentDescription = contentDescription;
7264        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
7265        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
7266            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
7267            notifySubtreeAccessibilityStateChangedIfNeeded();
7268        } else {
7269            notifyViewAccessibilityStateChangedIfNeeded(
7270                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
7271        }
7272    }
7273
7274    /**
7275     * Sets the id of a view before which this one is visited in accessibility traversal.
7276     * A screen-reader must visit the content of this view before the content of the one
7277     * it precedes. For example, if view B is set to be before view A, then a screen-reader
7278     * will traverse the entire content of B before traversing the entire content of A,
7279     * regardles of what traversal strategy it is using.
7280     * <p>
7281     * Views that do not have specified before/after relationships are traversed in order
7282     * determined by the screen-reader.
7283     * </p>
7284     * <p>
7285     * Setting that this view is before a view that is not important for accessibility
7286     * or if this view is not important for accessibility will have no effect as the
7287     * screen-reader is not aware of unimportant views.
7288     * </p>
7289     *
7290     * @param beforeId The id of a view this one precedes in accessibility traversal.
7291     *
7292     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
7293     *
7294     * @see #setImportantForAccessibility(int)
7295     */
7296    @RemotableViewMethod
7297    public void setAccessibilityTraversalBefore(int beforeId) {
7298        if (mAccessibilityTraversalBeforeId == beforeId) {
7299            return;
7300        }
7301        mAccessibilityTraversalBeforeId = beforeId;
7302        notifyViewAccessibilityStateChangedIfNeeded(
7303                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7304    }
7305
7306    /**
7307     * Gets the id of a view before which this one is visited in accessibility traversal.
7308     *
7309     * @return The id of a view this one precedes in accessibility traversal if
7310     *         specified, otherwise {@link #NO_ID}.
7311     *
7312     * @see #setAccessibilityTraversalBefore(int)
7313     */
7314    public int getAccessibilityTraversalBefore() {
7315        return mAccessibilityTraversalBeforeId;
7316    }
7317
7318    /**
7319     * Sets the id of a view after which this one is visited in accessibility traversal.
7320     * A screen-reader must visit the content of the other view before the content of this
7321     * one. For example, if view B is set to be after view A, then a screen-reader
7322     * will traverse the entire content of A before traversing the entire content of B,
7323     * regardles of what traversal strategy it is using.
7324     * <p>
7325     * Views that do not have specified before/after relationships are traversed in order
7326     * determined by the screen-reader.
7327     * </p>
7328     * <p>
7329     * Setting that this view is after a view that is not important for accessibility
7330     * or if this view is not important for accessibility will have no effect as the
7331     * screen-reader is not aware of unimportant views.
7332     * </p>
7333     *
7334     * @param afterId The id of a view this one succedees in accessibility traversal.
7335     *
7336     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
7337     *
7338     * @see #setImportantForAccessibility(int)
7339     */
7340    @RemotableViewMethod
7341    public void setAccessibilityTraversalAfter(int afterId) {
7342        if (mAccessibilityTraversalAfterId == afterId) {
7343            return;
7344        }
7345        mAccessibilityTraversalAfterId = afterId;
7346        notifyViewAccessibilityStateChangedIfNeeded(
7347                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7348    }
7349
7350    /**
7351     * Gets the id of a view after which this one is visited in accessibility traversal.
7352     *
7353     * @return The id of a view this one succeedes in accessibility traversal if
7354     *         specified, otherwise {@link #NO_ID}.
7355     *
7356     * @see #setAccessibilityTraversalAfter(int)
7357     */
7358    public int getAccessibilityTraversalAfter() {
7359        return mAccessibilityTraversalAfterId;
7360    }
7361
7362    /**
7363     * Gets the id of a view for which this view serves as a label for
7364     * accessibility purposes.
7365     *
7366     * @return The labeled view id.
7367     */
7368    @ViewDebug.ExportedProperty(category = "accessibility")
7369    public int getLabelFor() {
7370        return mLabelForId;
7371    }
7372
7373    /**
7374     * Sets the id of a view for which this view serves as a label for
7375     * accessibility purposes.
7376     *
7377     * @param id The labeled view id.
7378     */
7379    @RemotableViewMethod
7380    public void setLabelFor(@IdRes int id) {
7381        if (mLabelForId == id) {
7382            return;
7383        }
7384        mLabelForId = id;
7385        if (mLabelForId != View.NO_ID
7386                && mID == View.NO_ID) {
7387            mID = generateViewId();
7388        }
7389        notifyViewAccessibilityStateChangedIfNeeded(
7390                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7391    }
7392
7393    /**
7394     * Invoked whenever this view loses focus, either by losing window focus or by losing
7395     * focus within its window. This method can be used to clear any state tied to the
7396     * focus. For instance, if a button is held pressed with the trackball and the window
7397     * loses focus, this method can be used to cancel the press.
7398     *
7399     * Subclasses of View overriding this method should always call super.onFocusLost().
7400     *
7401     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7402     * @see #onWindowFocusChanged(boolean)
7403     *
7404     * @hide pending API council approval
7405     */
7406    @CallSuper
7407    protected void onFocusLost() {
7408        resetPressedState();
7409    }
7410
7411    private void resetPressedState() {
7412        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7413            return;
7414        }
7415
7416        if (isPressed()) {
7417            setPressed(false);
7418
7419            if (!mHasPerformedLongPress) {
7420                removeLongPressCallback();
7421            }
7422        }
7423    }
7424
7425    /**
7426     * Returns true if this view has focus
7427     *
7428     * @return True if this view has focus, false otherwise.
7429     */
7430    @ViewDebug.ExportedProperty(category = "focus")
7431    public boolean isFocused() {
7432        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7433    }
7434
7435    /**
7436     * Find the view in the hierarchy rooted at this view that currently has
7437     * focus.
7438     *
7439     * @return The view that currently has focus, or null if no focused view can
7440     *         be found.
7441     */
7442    public View findFocus() {
7443        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7444    }
7445
7446    /**
7447     * Indicates whether this view is one of the set of scrollable containers in
7448     * its window.
7449     *
7450     * @return whether this view is one of the set of scrollable containers in
7451     * its window
7452     *
7453     * @attr ref android.R.styleable#View_isScrollContainer
7454     */
7455    public boolean isScrollContainer() {
7456        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7457    }
7458
7459    /**
7460     * Change whether this view is one of the set of scrollable containers in
7461     * its window.  This will be used to determine whether the window can
7462     * resize or must pan when a soft input area is open -- scrollable
7463     * containers allow the window to use resize mode since the container
7464     * will appropriately shrink.
7465     *
7466     * @attr ref android.R.styleable#View_isScrollContainer
7467     */
7468    public void setScrollContainer(boolean isScrollContainer) {
7469        if (isScrollContainer) {
7470            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7471                mAttachInfo.mScrollContainers.add(this);
7472                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7473            }
7474            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7475        } else {
7476            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7477                mAttachInfo.mScrollContainers.remove(this);
7478            }
7479            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7480        }
7481    }
7482
7483    /**
7484     * Returns the quality of the drawing cache.
7485     *
7486     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7487     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7488     *
7489     * @see #setDrawingCacheQuality(int)
7490     * @see #setDrawingCacheEnabled(boolean)
7491     * @see #isDrawingCacheEnabled()
7492     *
7493     * @attr ref android.R.styleable#View_drawingCacheQuality
7494     */
7495    @DrawingCacheQuality
7496    public int getDrawingCacheQuality() {
7497        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7498    }
7499
7500    /**
7501     * Set the drawing cache quality of this view. This value is used only when the
7502     * drawing cache is enabled
7503     *
7504     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7505     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7506     *
7507     * @see #getDrawingCacheQuality()
7508     * @see #setDrawingCacheEnabled(boolean)
7509     * @see #isDrawingCacheEnabled()
7510     *
7511     * @attr ref android.R.styleable#View_drawingCacheQuality
7512     */
7513    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7514        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7515    }
7516
7517    /**
7518     * Returns whether the screen should remain on, corresponding to the current
7519     * value of {@link #KEEP_SCREEN_ON}.
7520     *
7521     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7522     *
7523     * @see #setKeepScreenOn(boolean)
7524     *
7525     * @attr ref android.R.styleable#View_keepScreenOn
7526     */
7527    public boolean getKeepScreenOn() {
7528        return (mViewFlags & KEEP_SCREEN_ON) != 0;
7529    }
7530
7531    /**
7532     * Controls whether the screen should remain on, modifying the
7533     * value of {@link #KEEP_SCREEN_ON}.
7534     *
7535     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7536     *
7537     * @see #getKeepScreenOn()
7538     *
7539     * @attr ref android.R.styleable#View_keepScreenOn
7540     */
7541    public void setKeepScreenOn(boolean keepScreenOn) {
7542        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7543    }
7544
7545    /**
7546     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7547     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7548     *
7549     * @attr ref android.R.styleable#View_nextFocusLeft
7550     */
7551    public int getNextFocusLeftId() {
7552        return mNextFocusLeftId;
7553    }
7554
7555    /**
7556     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7557     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7558     * decide automatically.
7559     *
7560     * @attr ref android.R.styleable#View_nextFocusLeft
7561     */
7562    public void setNextFocusLeftId(int nextFocusLeftId) {
7563        mNextFocusLeftId = nextFocusLeftId;
7564    }
7565
7566    /**
7567     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7568     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7569     *
7570     * @attr ref android.R.styleable#View_nextFocusRight
7571     */
7572    public int getNextFocusRightId() {
7573        return mNextFocusRightId;
7574    }
7575
7576    /**
7577     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7578     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7579     * decide automatically.
7580     *
7581     * @attr ref android.R.styleable#View_nextFocusRight
7582     */
7583    public void setNextFocusRightId(int nextFocusRightId) {
7584        mNextFocusRightId = nextFocusRightId;
7585    }
7586
7587    /**
7588     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7589     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7590     *
7591     * @attr ref android.R.styleable#View_nextFocusUp
7592     */
7593    public int getNextFocusUpId() {
7594        return mNextFocusUpId;
7595    }
7596
7597    /**
7598     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7599     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7600     * decide automatically.
7601     *
7602     * @attr ref android.R.styleable#View_nextFocusUp
7603     */
7604    public void setNextFocusUpId(int nextFocusUpId) {
7605        mNextFocusUpId = nextFocusUpId;
7606    }
7607
7608    /**
7609     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7610     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7611     *
7612     * @attr ref android.R.styleable#View_nextFocusDown
7613     */
7614    public int getNextFocusDownId() {
7615        return mNextFocusDownId;
7616    }
7617
7618    /**
7619     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7620     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7621     * decide automatically.
7622     *
7623     * @attr ref android.R.styleable#View_nextFocusDown
7624     */
7625    public void setNextFocusDownId(int nextFocusDownId) {
7626        mNextFocusDownId = nextFocusDownId;
7627    }
7628
7629    /**
7630     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7631     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7632     *
7633     * @attr ref android.R.styleable#View_nextFocusForward
7634     */
7635    public int getNextFocusForwardId() {
7636        return mNextFocusForwardId;
7637    }
7638
7639    /**
7640     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7641     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7642     * decide automatically.
7643     *
7644     * @attr ref android.R.styleable#View_nextFocusForward
7645     */
7646    public void setNextFocusForwardId(int nextFocusForwardId) {
7647        mNextFocusForwardId = nextFocusForwardId;
7648    }
7649
7650    /**
7651     * Returns the visibility of this view and all of its ancestors
7652     *
7653     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7654     */
7655    public boolean isShown() {
7656        View current = this;
7657        //noinspection ConstantConditions
7658        do {
7659            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7660                return false;
7661            }
7662            ViewParent parent = current.mParent;
7663            if (parent == null) {
7664                return false; // We are not attached to the view root
7665            }
7666            if (!(parent instanceof View)) {
7667                return true;
7668            }
7669            current = (View) parent;
7670        } while (current != null);
7671
7672        return false;
7673    }
7674
7675    /**
7676     * Called by the view hierarchy when the content insets for a window have
7677     * changed, to allow it to adjust its content to fit within those windows.
7678     * The content insets tell you the space that the status bar, input method,
7679     * and other system windows infringe on the application's window.
7680     *
7681     * <p>You do not normally need to deal with this function, since the default
7682     * window decoration given to applications takes care of applying it to the
7683     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7684     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7685     * and your content can be placed under those system elements.  You can then
7686     * use this method within your view hierarchy if you have parts of your UI
7687     * which you would like to ensure are not being covered.
7688     *
7689     * <p>The default implementation of this method simply applies the content
7690     * insets to the view's padding, consuming that content (modifying the
7691     * insets to be 0), and returning true.  This behavior is off by default, but can
7692     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7693     *
7694     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7695     * insets object is propagated down the hierarchy, so any changes made to it will
7696     * be seen by all following views (including potentially ones above in
7697     * the hierarchy since this is a depth-first traversal).  The first view
7698     * that returns true will abort the entire traversal.
7699     *
7700     * <p>The default implementation works well for a situation where it is
7701     * used with a container that covers the entire window, allowing it to
7702     * apply the appropriate insets to its content on all edges.  If you need
7703     * a more complicated layout (such as two different views fitting system
7704     * windows, one on the top of the window, and one on the bottom),
7705     * you can override the method and handle the insets however you would like.
7706     * Note that the insets provided by the framework are always relative to the
7707     * far edges of the window, not accounting for the location of the called view
7708     * within that window.  (In fact when this method is called you do not yet know
7709     * where the layout will place the view, as it is done before layout happens.)
7710     *
7711     * <p>Note: unlike many View methods, there is no dispatch phase to this
7712     * call.  If you are overriding it in a ViewGroup and want to allow the
7713     * call to continue to your children, you must be sure to call the super
7714     * implementation.
7715     *
7716     * <p>Here is a sample layout that makes use of fitting system windows
7717     * to have controls for a video view placed inside of the window decorations
7718     * that it hides and shows.  This can be used with code like the second
7719     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7720     *
7721     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7722     *
7723     * @param insets Current content insets of the window.  Prior to
7724     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7725     * the insets or else you and Android will be unhappy.
7726     *
7727     * @return {@code true} if this view applied the insets and it should not
7728     * continue propagating further down the hierarchy, {@code false} otherwise.
7729     * @see #getFitsSystemWindows()
7730     * @see #setFitsSystemWindows(boolean)
7731     * @see #setSystemUiVisibility(int)
7732     *
7733     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7734     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7735     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7736     * to implement handling their own insets.
7737     */
7738    protected boolean fitSystemWindows(Rect insets) {
7739        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7740            if (insets == null) {
7741                // Null insets by definition have already been consumed.
7742                // This call cannot apply insets since there are none to apply,
7743                // so return false.
7744                return false;
7745            }
7746            // If we're not in the process of dispatching the newer apply insets call,
7747            // that means we're not in the compatibility path. Dispatch into the newer
7748            // apply insets path and take things from there.
7749            try {
7750                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7751                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7752            } finally {
7753                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7754            }
7755        } else {
7756            // We're being called from the newer apply insets path.
7757            // Perform the standard fallback behavior.
7758            return fitSystemWindowsInt(insets);
7759        }
7760    }
7761
7762    private boolean fitSystemWindowsInt(Rect insets) {
7763        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7764            mUserPaddingStart = UNDEFINED_PADDING;
7765            mUserPaddingEnd = UNDEFINED_PADDING;
7766            Rect localInsets = sThreadLocal.get();
7767            if (localInsets == null) {
7768                localInsets = new Rect();
7769                sThreadLocal.set(localInsets);
7770            }
7771            boolean res = computeFitSystemWindows(insets, localInsets);
7772            mUserPaddingLeftInitial = localInsets.left;
7773            mUserPaddingRightInitial = localInsets.right;
7774            internalSetPadding(localInsets.left, localInsets.top,
7775                    localInsets.right, localInsets.bottom);
7776            return res;
7777        }
7778        return false;
7779    }
7780
7781    /**
7782     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7783     *
7784     * <p>This method should be overridden by views that wish to apply a policy different from or
7785     * in addition to the default behavior. Clients that wish to force a view subtree
7786     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7787     *
7788     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7789     * it will be called during dispatch instead of this method. The listener may optionally
7790     * call this method from its own implementation if it wishes to apply the view's default
7791     * insets policy in addition to its own.</p>
7792     *
7793     * <p>Implementations of this method should either return the insets parameter unchanged
7794     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7795     * that this view applied itself. This allows new inset types added in future platform
7796     * versions to pass through existing implementations unchanged without being erroneously
7797     * consumed.</p>
7798     *
7799     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7800     * property is set then the view will consume the system window insets and apply them
7801     * as padding for the view.</p>
7802     *
7803     * @param insets Insets to apply
7804     * @return The supplied insets with any applied insets consumed
7805     */
7806    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7807        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7808            // We weren't called from within a direct call to fitSystemWindows,
7809            // call into it as a fallback in case we're in a class that overrides it
7810            // and has logic to perform.
7811            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7812                return insets.consumeSystemWindowInsets();
7813            }
7814        } else {
7815            // We were called from within a direct call to fitSystemWindows.
7816            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7817                return insets.consumeSystemWindowInsets();
7818            }
7819        }
7820        return insets;
7821    }
7822
7823    /**
7824     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7825     * window insets to this view. The listener's
7826     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7827     * method will be called instead of the view's
7828     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7829     *
7830     * @param listener Listener to set
7831     *
7832     * @see #onApplyWindowInsets(WindowInsets)
7833     */
7834    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7835        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7836    }
7837
7838    /**
7839     * Request to apply the given window insets to this view or another view in its subtree.
7840     *
7841     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7842     * obscured by window decorations or overlays. This can include the status and navigation bars,
7843     * action bars, input methods and more. New inset categories may be added in the future.
7844     * The method returns the insets provided minus any that were applied by this view or its
7845     * children.</p>
7846     *
7847     * <p>Clients wishing to provide custom behavior should override the
7848     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7849     * {@link OnApplyWindowInsetsListener} via the
7850     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7851     * method.</p>
7852     *
7853     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7854     * </p>
7855     *
7856     * @param insets Insets to apply
7857     * @return The provided insets minus the insets that were consumed
7858     */
7859    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7860        try {
7861            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7862            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7863                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7864            } else {
7865                return onApplyWindowInsets(insets);
7866            }
7867        } finally {
7868            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7869        }
7870    }
7871
7872    /**
7873     * Compute the view's coordinate within the surface.
7874     *
7875     * <p>Computes the coordinates of this view in its surface. The argument
7876     * must be an array of two integers. After the method returns, the array
7877     * contains the x and y location in that order.</p>
7878     * @hide
7879     * @param location an array of two integers in which to hold the coordinates
7880     */
7881    public void getLocationInSurface(@Size(2) int[] location) {
7882        getLocationInWindow(location);
7883        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
7884            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
7885            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
7886        }
7887    }
7888
7889    /**
7890     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7891     * only available if the view is attached.
7892     *
7893     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7894     */
7895    public WindowInsets getRootWindowInsets() {
7896        if (mAttachInfo != null) {
7897            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7898        }
7899        return null;
7900    }
7901
7902    /**
7903     * @hide Compute the insets that should be consumed by this view and the ones
7904     * that should propagate to those under it.
7905     */
7906    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7907        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7908                || mAttachInfo == null
7909                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7910                        && !mAttachInfo.mOverscanRequested)) {
7911            outLocalInsets.set(inoutInsets);
7912            inoutInsets.set(0, 0, 0, 0);
7913            return true;
7914        } else {
7915            // The application wants to take care of fitting system window for
7916            // the content...  however we still need to take care of any overscan here.
7917            final Rect overscan = mAttachInfo.mOverscanInsets;
7918            outLocalInsets.set(overscan);
7919            inoutInsets.left -= overscan.left;
7920            inoutInsets.top -= overscan.top;
7921            inoutInsets.right -= overscan.right;
7922            inoutInsets.bottom -= overscan.bottom;
7923            return false;
7924        }
7925    }
7926
7927    /**
7928     * Compute insets that should be consumed by this view and the ones that should propagate
7929     * to those under it.
7930     *
7931     * @param in Insets currently being processed by this View, likely received as a parameter
7932     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7933     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7934     *                       by this view
7935     * @return Insets that should be passed along to views under this one
7936     */
7937    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7938        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7939                || mAttachInfo == null
7940                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7941            outLocalInsets.set(in.getSystemWindowInsets());
7942            return in.consumeSystemWindowInsets();
7943        } else {
7944            outLocalInsets.set(0, 0, 0, 0);
7945            return in;
7946        }
7947    }
7948
7949    /**
7950     * Sets whether or not this view should account for system screen decorations
7951     * such as the status bar and inset its content; that is, controlling whether
7952     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7953     * executed.  See that method for more details.
7954     *
7955     * <p>Note that if you are providing your own implementation of
7956     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7957     * flag to true -- your implementation will be overriding the default
7958     * implementation that checks this flag.
7959     *
7960     * @param fitSystemWindows If true, then the default implementation of
7961     * {@link #fitSystemWindows(Rect)} will be executed.
7962     *
7963     * @attr ref android.R.styleable#View_fitsSystemWindows
7964     * @see #getFitsSystemWindows()
7965     * @see #fitSystemWindows(Rect)
7966     * @see #setSystemUiVisibility(int)
7967     */
7968    public void setFitsSystemWindows(boolean fitSystemWindows) {
7969        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7970    }
7971
7972    /**
7973     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7974     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7975     * will be executed.
7976     *
7977     * @return {@code true} if the default implementation of
7978     * {@link #fitSystemWindows(Rect)} will be executed.
7979     *
7980     * @attr ref android.R.styleable#View_fitsSystemWindows
7981     * @see #setFitsSystemWindows(boolean)
7982     * @see #fitSystemWindows(Rect)
7983     * @see #setSystemUiVisibility(int)
7984     */
7985    @ViewDebug.ExportedProperty
7986    public boolean getFitsSystemWindows() {
7987        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7988    }
7989
7990    /** @hide */
7991    public boolean fitsSystemWindows() {
7992        return getFitsSystemWindows();
7993    }
7994
7995    /**
7996     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7997     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7998     */
7999    public void requestFitSystemWindows() {
8000        if (mParent != null) {
8001            mParent.requestFitSystemWindows();
8002        }
8003    }
8004
8005    /**
8006     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8007     */
8008    public void requestApplyInsets() {
8009        requestFitSystemWindows();
8010    }
8011
8012    /**
8013     * For use by PhoneWindow to make its own system window fitting optional.
8014     * @hide
8015     */
8016    public void makeOptionalFitsSystemWindows() {
8017        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8018    }
8019
8020    /**
8021     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8022     * treat them as such.
8023     * @hide
8024     */
8025    public void getOutsets(Rect outOutsetRect) {
8026        if (mAttachInfo != null) {
8027            outOutsetRect.set(mAttachInfo.mOutsets);
8028        } else {
8029            outOutsetRect.setEmpty();
8030        }
8031    }
8032
8033    /**
8034     * Returns the visibility status for this view.
8035     *
8036     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8037     * @attr ref android.R.styleable#View_visibility
8038     */
8039    @ViewDebug.ExportedProperty(mapping = {
8040        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8041        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8042        @ViewDebug.IntToString(from = GONE,      to = "GONE")
8043    })
8044    @Visibility
8045    public int getVisibility() {
8046        return mViewFlags & VISIBILITY_MASK;
8047    }
8048
8049    /**
8050     * Set the enabled state of this view.
8051     *
8052     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8053     * @attr ref android.R.styleable#View_visibility
8054     */
8055    @RemotableViewMethod
8056    public void setVisibility(@Visibility int visibility) {
8057        setFlags(visibility, VISIBILITY_MASK);
8058    }
8059
8060    /**
8061     * Returns the enabled status for this view. The interpretation of the
8062     * enabled state varies by subclass.
8063     *
8064     * @return True if this view is enabled, false otherwise.
8065     */
8066    @ViewDebug.ExportedProperty
8067    public boolean isEnabled() {
8068        return (mViewFlags & ENABLED_MASK) == ENABLED;
8069    }
8070
8071    /**
8072     * Set the enabled state of this view. The interpretation of the enabled
8073     * state varies by subclass.
8074     *
8075     * @param enabled True if this view is enabled, false otherwise.
8076     */
8077    @RemotableViewMethod
8078    public void setEnabled(boolean enabled) {
8079        if (enabled == isEnabled()) return;
8080
8081        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
8082
8083        /*
8084         * The View most likely has to change its appearance, so refresh
8085         * the drawable state.
8086         */
8087        refreshDrawableState();
8088
8089        // Invalidate too, since the default behavior for views is to be
8090        // be drawn at 50% alpha rather than to change the drawable.
8091        invalidate(true);
8092
8093        if (!enabled) {
8094            cancelPendingInputEvents();
8095        }
8096    }
8097
8098    /**
8099     * Set whether this view can receive the focus.
8100     *
8101     * Setting this to false will also ensure that this view is not focusable
8102     * in touch mode.
8103     *
8104     * @param focusable If true, this view can receive the focus.
8105     *
8106     * @see #setFocusableInTouchMode(boolean)
8107     * @attr ref android.R.styleable#View_focusable
8108     */
8109    public void setFocusable(boolean focusable) {
8110        if (!focusable) {
8111            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
8112        }
8113        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
8114    }
8115
8116    /**
8117     * Set whether this view can receive focus while in touch mode.
8118     *
8119     * Setting this to true will also ensure that this view is focusable.
8120     *
8121     * @param focusableInTouchMode If true, this view can receive the focus while
8122     *   in touch mode.
8123     *
8124     * @see #setFocusable(boolean)
8125     * @attr ref android.R.styleable#View_focusableInTouchMode
8126     */
8127    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
8128        // Focusable in touch mode should always be set before the focusable flag
8129        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
8130        // which, in touch mode, will not successfully request focus on this view
8131        // because the focusable in touch mode flag is not set
8132        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
8133        if (focusableInTouchMode) {
8134            setFlags(FOCUSABLE, FOCUSABLE_MASK);
8135        }
8136    }
8137
8138    /**
8139     * Set whether this view should have sound effects enabled for events such as
8140     * clicking and touching.
8141     *
8142     * <p>You may wish to disable sound effects for a view if you already play sounds,
8143     * for instance, a dial key that plays dtmf tones.
8144     *
8145     * @param soundEffectsEnabled whether sound effects are enabled for this view.
8146     * @see #isSoundEffectsEnabled()
8147     * @see #playSoundEffect(int)
8148     * @attr ref android.R.styleable#View_soundEffectsEnabled
8149     */
8150    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
8151        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
8152    }
8153
8154    /**
8155     * @return whether this view should have sound effects enabled for events such as
8156     *     clicking and touching.
8157     *
8158     * @see #setSoundEffectsEnabled(boolean)
8159     * @see #playSoundEffect(int)
8160     * @attr ref android.R.styleable#View_soundEffectsEnabled
8161     */
8162    @ViewDebug.ExportedProperty
8163    public boolean isSoundEffectsEnabled() {
8164        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
8165    }
8166
8167    /**
8168     * Set whether this view should have haptic feedback for events such as
8169     * long presses.
8170     *
8171     * <p>You may wish to disable haptic feedback if your view already controls
8172     * its own haptic feedback.
8173     *
8174     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
8175     * @see #isHapticFeedbackEnabled()
8176     * @see #performHapticFeedback(int)
8177     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8178     */
8179    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
8180        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
8181    }
8182
8183    /**
8184     * @return whether this view should have haptic feedback enabled for events
8185     * long presses.
8186     *
8187     * @see #setHapticFeedbackEnabled(boolean)
8188     * @see #performHapticFeedback(int)
8189     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8190     */
8191    @ViewDebug.ExportedProperty
8192    public boolean isHapticFeedbackEnabled() {
8193        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
8194    }
8195
8196    /**
8197     * Returns the layout direction for this view.
8198     *
8199     * @return One of {@link #LAYOUT_DIRECTION_LTR},
8200     *   {@link #LAYOUT_DIRECTION_RTL},
8201     *   {@link #LAYOUT_DIRECTION_INHERIT} or
8202     *   {@link #LAYOUT_DIRECTION_LOCALE}.
8203     *
8204     * @attr ref android.R.styleable#View_layoutDirection
8205     *
8206     * @hide
8207     */
8208    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8209        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
8210        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
8211        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
8212        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
8213    })
8214    @LayoutDir
8215    public int getRawLayoutDirection() {
8216        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
8217    }
8218
8219    /**
8220     * Set the layout direction for this view. This will propagate a reset of layout direction
8221     * resolution to the view's children and resolve layout direction for this view.
8222     *
8223     * @param layoutDirection the layout direction to set. Should be one of:
8224     *
8225     * {@link #LAYOUT_DIRECTION_LTR},
8226     * {@link #LAYOUT_DIRECTION_RTL},
8227     * {@link #LAYOUT_DIRECTION_INHERIT},
8228     * {@link #LAYOUT_DIRECTION_LOCALE}.
8229     *
8230     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
8231     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
8232     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
8233     *
8234     * @attr ref android.R.styleable#View_layoutDirection
8235     */
8236    @RemotableViewMethod
8237    public void setLayoutDirection(@LayoutDir int layoutDirection) {
8238        if (getRawLayoutDirection() != layoutDirection) {
8239            // Reset the current layout direction and the resolved one
8240            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
8241            resetRtlProperties();
8242            // Set the new layout direction (filtered)
8243            mPrivateFlags2 |=
8244                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
8245            // We need to resolve all RTL properties as they all depend on layout direction
8246            resolveRtlPropertiesIfNeeded();
8247            requestLayout();
8248            invalidate(true);
8249        }
8250    }
8251
8252    /**
8253     * Returns the resolved layout direction for this view.
8254     *
8255     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
8256     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
8257     *
8258     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
8259     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
8260     *
8261     * @attr ref android.R.styleable#View_layoutDirection
8262     */
8263    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8264        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
8265        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
8266    })
8267    @ResolvedLayoutDir
8268    public int getLayoutDirection() {
8269        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
8270        if (targetSdkVersion < JELLY_BEAN_MR1) {
8271            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
8272            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
8273        }
8274        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
8275                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
8276    }
8277
8278    /**
8279     * Indicates whether or not this view's layout is right-to-left. This is resolved from
8280     * layout attribute and/or the inherited value from the parent
8281     *
8282     * @return true if the layout is right-to-left.
8283     *
8284     * @hide
8285     */
8286    @ViewDebug.ExportedProperty(category = "layout")
8287    public boolean isLayoutRtl() {
8288        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
8289    }
8290
8291    /**
8292     * Indicates whether the view is currently tracking transient state that the
8293     * app should not need to concern itself with saving and restoring, but that
8294     * the framework should take special note to preserve when possible.
8295     *
8296     * <p>A view with transient state cannot be trivially rebound from an external
8297     * data source, such as an adapter binding item views in a list. This may be
8298     * because the view is performing an animation, tracking user selection
8299     * of content, or similar.</p>
8300     *
8301     * @return true if the view has transient state
8302     */
8303    @ViewDebug.ExportedProperty(category = "layout")
8304    public boolean hasTransientState() {
8305        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
8306    }
8307
8308    /**
8309     * Set whether this view is currently tracking transient state that the
8310     * framework should attempt to preserve when possible. This flag is reference counted,
8311     * so every call to setHasTransientState(true) should be paired with a later call
8312     * to setHasTransientState(false).
8313     *
8314     * <p>A view with transient state cannot be trivially rebound from an external
8315     * data source, such as an adapter binding item views in a list. This may be
8316     * because the view is performing an animation, tracking user selection
8317     * of content, or similar.</p>
8318     *
8319     * @param hasTransientState true if this view has transient state
8320     */
8321    public void setHasTransientState(boolean hasTransientState) {
8322        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
8323                mTransientStateCount - 1;
8324        if (mTransientStateCount < 0) {
8325            mTransientStateCount = 0;
8326            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
8327                    "unmatched pair of setHasTransientState calls");
8328        } else if ((hasTransientState && mTransientStateCount == 1) ||
8329                (!hasTransientState && mTransientStateCount == 0)) {
8330            // update flag if we've just incremented up from 0 or decremented down to 0
8331            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
8332                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
8333            if (mParent != null) {
8334                try {
8335                    mParent.childHasTransientStateChanged(this, hasTransientState);
8336                } catch (AbstractMethodError e) {
8337                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8338                            " does not fully implement ViewParent", e);
8339                }
8340            }
8341        }
8342    }
8343
8344    /**
8345     * Returns true if this view is currently attached to a window.
8346     */
8347    public boolean isAttachedToWindow() {
8348        return mAttachInfo != null;
8349    }
8350
8351    /**
8352     * Returns true if this view has been through at least one layout since it
8353     * was last attached to or detached from a window.
8354     */
8355    public boolean isLaidOut() {
8356        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
8357    }
8358
8359    /**
8360     * If this view doesn't do any drawing on its own, set this flag to
8361     * allow further optimizations. By default, this flag is not set on
8362     * View, but could be set on some View subclasses such as ViewGroup.
8363     *
8364     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8365     * you should clear this flag.
8366     *
8367     * @param willNotDraw whether or not this View draw on its own
8368     */
8369    public void setWillNotDraw(boolean willNotDraw) {
8370        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8371    }
8372
8373    /**
8374     * Returns whether or not this View draws on its own.
8375     *
8376     * @return true if this view has nothing to draw, false otherwise
8377     */
8378    @ViewDebug.ExportedProperty(category = "drawing")
8379    public boolean willNotDraw() {
8380        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8381    }
8382
8383    /**
8384     * When a View's drawing cache is enabled, drawing is redirected to an
8385     * offscreen bitmap. Some views, like an ImageView, must be able to
8386     * bypass this mechanism if they already draw a single bitmap, to avoid
8387     * unnecessary usage of the memory.
8388     *
8389     * @param willNotCacheDrawing true if this view does not cache its
8390     *        drawing, false otherwise
8391     */
8392    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8393        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8394    }
8395
8396    /**
8397     * Returns whether or not this View can cache its drawing or not.
8398     *
8399     * @return true if this view does not cache its drawing, false otherwise
8400     */
8401    @ViewDebug.ExportedProperty(category = "drawing")
8402    public boolean willNotCacheDrawing() {
8403        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8404    }
8405
8406    /**
8407     * Indicates whether this view reacts to click events or not.
8408     *
8409     * @return true if the view is clickable, false otherwise
8410     *
8411     * @see #setClickable(boolean)
8412     * @attr ref android.R.styleable#View_clickable
8413     */
8414    @ViewDebug.ExportedProperty
8415    public boolean isClickable() {
8416        return (mViewFlags & CLICKABLE) == CLICKABLE;
8417    }
8418
8419    /**
8420     * Enables or disables click events for this view. When a view
8421     * is clickable it will change its state to "pressed" on every click.
8422     * Subclasses should set the view clickable to visually react to
8423     * user's clicks.
8424     *
8425     * @param clickable true to make the view clickable, false otherwise
8426     *
8427     * @see #isClickable()
8428     * @attr ref android.R.styleable#View_clickable
8429     */
8430    public void setClickable(boolean clickable) {
8431        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8432    }
8433
8434    /**
8435     * Indicates whether this view reacts to long click events or not.
8436     *
8437     * @return true if the view is long clickable, false otherwise
8438     *
8439     * @see #setLongClickable(boolean)
8440     * @attr ref android.R.styleable#View_longClickable
8441     */
8442    public boolean isLongClickable() {
8443        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8444    }
8445
8446    /**
8447     * Enables or disables long click events for this view. When a view is long
8448     * clickable it reacts to the user holding down the button for a longer
8449     * duration than a tap. This event can either launch the listener or a
8450     * context menu.
8451     *
8452     * @param longClickable true to make the view long clickable, false otherwise
8453     * @see #isLongClickable()
8454     * @attr ref android.R.styleable#View_longClickable
8455     */
8456    public void setLongClickable(boolean longClickable) {
8457        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8458    }
8459
8460    /**
8461     * Indicates whether this view reacts to context clicks or not.
8462     *
8463     * @return true if the view is context clickable, false otherwise
8464     * @see #setContextClickable(boolean)
8465     * @attr ref android.R.styleable#View_contextClickable
8466     */
8467    public boolean isContextClickable() {
8468        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8469    }
8470
8471    /**
8472     * Enables or disables context clicking for this view. This event can launch the listener.
8473     *
8474     * @param contextClickable true to make the view react to a context click, false otherwise
8475     * @see #isContextClickable()
8476     * @attr ref android.R.styleable#View_contextClickable
8477     */
8478    public void setContextClickable(boolean contextClickable) {
8479        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8480    }
8481
8482    /**
8483     * Sets the pressed state for this view and provides a touch coordinate for
8484     * animation hinting.
8485     *
8486     * @param pressed Pass true to set the View's internal state to "pressed",
8487     *            or false to reverts the View's internal state from a
8488     *            previously set "pressed" state.
8489     * @param x The x coordinate of the touch that caused the press
8490     * @param y The y coordinate of the touch that caused the press
8491     */
8492    private void setPressed(boolean pressed, float x, float y) {
8493        if (pressed) {
8494            drawableHotspotChanged(x, y);
8495        }
8496
8497        setPressed(pressed);
8498    }
8499
8500    /**
8501     * Sets the pressed state for this view.
8502     *
8503     * @see #isClickable()
8504     * @see #setClickable(boolean)
8505     *
8506     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8507     *        the View's internal state from a previously set "pressed" state.
8508     */
8509    public void setPressed(boolean pressed) {
8510        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8511
8512        if (pressed) {
8513            mPrivateFlags |= PFLAG_PRESSED;
8514        } else {
8515            mPrivateFlags &= ~PFLAG_PRESSED;
8516        }
8517
8518        if (needsRefresh) {
8519            refreshDrawableState();
8520        }
8521        dispatchSetPressed(pressed);
8522    }
8523
8524    /**
8525     * Dispatch setPressed to all of this View's children.
8526     *
8527     * @see #setPressed(boolean)
8528     *
8529     * @param pressed The new pressed state
8530     */
8531    protected void dispatchSetPressed(boolean pressed) {
8532    }
8533
8534    /**
8535     * Indicates whether the view is currently in pressed state. Unless
8536     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8537     * the pressed state.
8538     *
8539     * @see #setPressed(boolean)
8540     * @see #isClickable()
8541     * @see #setClickable(boolean)
8542     *
8543     * @return true if the view is currently pressed, false otherwise
8544     */
8545    @ViewDebug.ExportedProperty
8546    public boolean isPressed() {
8547        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8548    }
8549
8550    /**
8551     * @hide
8552     * Indicates whether this view will participate in data collection through
8553     * {@link ViewStructure}.  If true, it will not provide any data
8554     * for itself or its children.  If false, the normal data collection will be allowed.
8555     *
8556     * @return Returns false if assist data collection is not blocked, else true.
8557     *
8558     * @see #setAssistBlocked(boolean)
8559     * @attr ref android.R.styleable#View_assistBlocked
8560     */
8561    public boolean isAssistBlocked() {
8562        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8563    }
8564
8565    /**
8566     * @hide
8567     * Controls whether assist data collection from this view and its children is enabled
8568     * (that is, whether {@link #onProvideStructure} and
8569     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8570     * allowing normal assist collection.  Setting this to false will disable assist collection.
8571     *
8572     * @param enabled Set to true to <em>disable</em> assist data collection, or false
8573     * (the default) to allow it.
8574     *
8575     * @see #isAssistBlocked()
8576     * @see #onProvideStructure
8577     * @see #onProvideVirtualStructure
8578     * @attr ref android.R.styleable#View_assistBlocked
8579     */
8580    public void setAssistBlocked(boolean enabled) {
8581        if (enabled) {
8582            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8583        } else {
8584            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8585        }
8586    }
8587
8588    /**
8589     * Indicates whether this view will save its state (that is,
8590     * whether its {@link #onSaveInstanceState} method will be called).
8591     *
8592     * @return Returns true if the view state saving is enabled, else false.
8593     *
8594     * @see #setSaveEnabled(boolean)
8595     * @attr ref android.R.styleable#View_saveEnabled
8596     */
8597    public boolean isSaveEnabled() {
8598        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8599    }
8600
8601    /**
8602     * Controls whether the saving of this view's state is
8603     * enabled (that is, whether its {@link #onSaveInstanceState} method
8604     * will be called).  Note that even if freezing is enabled, the
8605     * view still must have an id assigned to it (via {@link #setId(int)})
8606     * for its state to be saved.  This flag can only disable the
8607     * saving of this view; any child views may still have their state saved.
8608     *
8609     * @param enabled Set to false to <em>disable</em> state saving, or true
8610     * (the default) to allow it.
8611     *
8612     * @see #isSaveEnabled()
8613     * @see #setId(int)
8614     * @see #onSaveInstanceState()
8615     * @attr ref android.R.styleable#View_saveEnabled
8616     */
8617    public void setSaveEnabled(boolean enabled) {
8618        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8619    }
8620
8621    /**
8622     * Gets whether the framework should discard touches when the view's
8623     * window is obscured by another visible window.
8624     * Refer to the {@link View} security documentation for more details.
8625     *
8626     * @return True if touch filtering is enabled.
8627     *
8628     * @see #setFilterTouchesWhenObscured(boolean)
8629     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8630     */
8631    @ViewDebug.ExportedProperty
8632    public boolean getFilterTouchesWhenObscured() {
8633        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8634    }
8635
8636    /**
8637     * Sets whether the framework should discard touches when the view's
8638     * window is obscured by another visible window.
8639     * Refer to the {@link View} security documentation for more details.
8640     *
8641     * @param enabled True if touch filtering should be enabled.
8642     *
8643     * @see #getFilterTouchesWhenObscured
8644     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8645     */
8646    public void setFilterTouchesWhenObscured(boolean enabled) {
8647        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8648                FILTER_TOUCHES_WHEN_OBSCURED);
8649    }
8650
8651    /**
8652     * Indicates whether the entire hierarchy under this view will save its
8653     * state when a state saving traversal occurs from its parent.  The default
8654     * is true; if false, these views will not be saved unless
8655     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8656     *
8657     * @return Returns true if the view state saving from parent is enabled, else false.
8658     *
8659     * @see #setSaveFromParentEnabled(boolean)
8660     */
8661    public boolean isSaveFromParentEnabled() {
8662        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8663    }
8664
8665    /**
8666     * Controls whether the entire hierarchy under this view will save its
8667     * state when a state saving traversal occurs from its parent.  The default
8668     * is true; if false, these views will not be saved unless
8669     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8670     *
8671     * @param enabled Set to false to <em>disable</em> state saving, or true
8672     * (the default) to allow it.
8673     *
8674     * @see #isSaveFromParentEnabled()
8675     * @see #setId(int)
8676     * @see #onSaveInstanceState()
8677     */
8678    public void setSaveFromParentEnabled(boolean enabled) {
8679        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8680    }
8681
8682
8683    /**
8684     * Returns whether this View is able to take focus.
8685     *
8686     * @return True if this view can take focus, or false otherwise.
8687     * @attr ref android.R.styleable#View_focusable
8688     */
8689    @ViewDebug.ExportedProperty(category = "focus")
8690    public final boolean isFocusable() {
8691        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8692    }
8693
8694    /**
8695     * When a view is focusable, it may not want to take focus when in touch mode.
8696     * For example, a button would like focus when the user is navigating via a D-pad
8697     * so that the user can click on it, but once the user starts touching the screen,
8698     * the button shouldn't take focus
8699     * @return Whether the view is focusable in touch mode.
8700     * @attr ref android.R.styleable#View_focusableInTouchMode
8701     */
8702    @ViewDebug.ExportedProperty
8703    public final boolean isFocusableInTouchMode() {
8704        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8705    }
8706
8707    /**
8708     * Find the nearest view in the specified direction that can take focus.
8709     * This does not actually give focus to that view.
8710     *
8711     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8712     *
8713     * @return The nearest focusable in the specified direction, or null if none
8714     *         can be found.
8715     */
8716    public View focusSearch(@FocusRealDirection int direction) {
8717        if (mParent != null) {
8718            return mParent.focusSearch(this, direction);
8719        } else {
8720            return null;
8721        }
8722    }
8723
8724    /**
8725     * This method is the last chance for the focused view and its ancestors to
8726     * respond to an arrow key. This is called when the focused view did not
8727     * consume the key internally, nor could the view system find a new view in
8728     * the requested direction to give focus to.
8729     *
8730     * @param focused The currently focused view.
8731     * @param direction The direction focus wants to move. One of FOCUS_UP,
8732     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8733     * @return True if the this view consumed this unhandled move.
8734     */
8735    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8736        return false;
8737    }
8738
8739    /**
8740     * If a user manually specified the next view id for a particular direction,
8741     * use the root to look up the view.
8742     * @param root The root view of the hierarchy containing this view.
8743     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8744     * or FOCUS_BACKWARD.
8745     * @return The user specified next view, or null if there is none.
8746     */
8747    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8748        switch (direction) {
8749            case FOCUS_LEFT:
8750                if (mNextFocusLeftId == View.NO_ID) return null;
8751                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8752            case FOCUS_RIGHT:
8753                if (mNextFocusRightId == View.NO_ID) return null;
8754                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8755            case FOCUS_UP:
8756                if (mNextFocusUpId == View.NO_ID) return null;
8757                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8758            case FOCUS_DOWN:
8759                if (mNextFocusDownId == View.NO_ID) return null;
8760                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8761            case FOCUS_FORWARD:
8762                if (mNextFocusForwardId == View.NO_ID) return null;
8763                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8764            case FOCUS_BACKWARD: {
8765                if (mID == View.NO_ID) return null;
8766                final int id = mID;
8767                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8768                    @Override
8769                    public boolean apply(View t) {
8770                        return t.mNextFocusForwardId == id;
8771                    }
8772                });
8773            }
8774        }
8775        return null;
8776    }
8777
8778    private View findViewInsideOutShouldExist(View root, int id) {
8779        if (mMatchIdPredicate == null) {
8780            mMatchIdPredicate = new MatchIdPredicate();
8781        }
8782        mMatchIdPredicate.mId = id;
8783        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8784        if (result == null) {
8785            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8786        }
8787        return result;
8788    }
8789
8790    /**
8791     * Find and return all focusable views that are descendants of this view,
8792     * possibly including this view if it is focusable itself.
8793     *
8794     * @param direction The direction of the focus
8795     * @return A list of focusable views
8796     */
8797    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8798        ArrayList<View> result = new ArrayList<View>(24);
8799        addFocusables(result, direction);
8800        return result;
8801    }
8802
8803    /**
8804     * Add any focusable views that are descendants of this view (possibly
8805     * including this view if it is focusable itself) to views.  If we are in touch mode,
8806     * only add views that are also focusable in touch mode.
8807     *
8808     * @param views Focusable views found so far
8809     * @param direction The direction of the focus
8810     */
8811    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8812        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
8813    }
8814
8815    /**
8816     * Adds any focusable views that are descendants of this view (possibly
8817     * including this view if it is focusable itself) to views. This method
8818     * adds all focusable views regardless if we are in touch mode or
8819     * only views focusable in touch mode if we are in touch mode or
8820     * only views that can take accessibility focus if accessibility is enabled
8821     * depending on the focusable mode parameter.
8822     *
8823     * @param views Focusable views found so far or null if all we are interested is
8824     *        the number of focusables.
8825     * @param direction The direction of the focus.
8826     * @param focusableMode The type of focusables to be added.
8827     *
8828     * @see #FOCUSABLES_ALL
8829     * @see #FOCUSABLES_TOUCH_MODE
8830     */
8831    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8832            @FocusableMode int focusableMode) {
8833        if (views == null) {
8834            return;
8835        }
8836        if (!isFocusable()) {
8837            return;
8838        }
8839        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8840                && !isFocusableInTouchMode()) {
8841            return;
8842        }
8843        views.add(this);
8844    }
8845
8846    /**
8847     * Finds the Views that contain given text. The containment is case insensitive.
8848     * The search is performed by either the text that the View renders or the content
8849     * description that describes the view for accessibility purposes and the view does
8850     * not render or both. Clients can specify how the search is to be performed via
8851     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8852     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8853     *
8854     * @param outViews The output list of matching Views.
8855     * @param searched The text to match against.
8856     *
8857     * @see #FIND_VIEWS_WITH_TEXT
8858     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8859     * @see #setContentDescription(CharSequence)
8860     */
8861    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8862            @FindViewFlags int flags) {
8863        if (getAccessibilityNodeProvider() != null) {
8864            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8865                outViews.add(this);
8866            }
8867        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8868                && (searched != null && searched.length() > 0)
8869                && (mContentDescription != null && mContentDescription.length() > 0)) {
8870            String searchedLowerCase = searched.toString().toLowerCase();
8871            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8872            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8873                outViews.add(this);
8874            }
8875        }
8876    }
8877
8878    /**
8879     * Find and return all touchable views that are descendants of this view,
8880     * possibly including this view if it is touchable itself.
8881     *
8882     * @return A list of touchable views
8883     */
8884    public ArrayList<View> getTouchables() {
8885        ArrayList<View> result = new ArrayList<View>();
8886        addTouchables(result);
8887        return result;
8888    }
8889
8890    /**
8891     * Add any touchable views that are descendants of this view (possibly
8892     * including this view if it is touchable itself) to views.
8893     *
8894     * @param views Touchable views found so far
8895     */
8896    public void addTouchables(ArrayList<View> views) {
8897        final int viewFlags = mViewFlags;
8898
8899        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8900                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8901                && (viewFlags & ENABLED_MASK) == ENABLED) {
8902            views.add(this);
8903        }
8904    }
8905
8906    /**
8907     * Returns whether this View is accessibility focused.
8908     *
8909     * @return True if this View is accessibility focused.
8910     */
8911    public boolean isAccessibilityFocused() {
8912        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8913    }
8914
8915    /**
8916     * Call this to try to give accessibility focus to this view.
8917     *
8918     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8919     * returns false or the view is no visible or the view already has accessibility
8920     * focus.
8921     *
8922     * See also {@link #focusSearch(int)}, which is what you call to say that you
8923     * have focus, and you want your parent to look for the next one.
8924     *
8925     * @return Whether this view actually took accessibility focus.
8926     *
8927     * @hide
8928     */
8929    public boolean requestAccessibilityFocus() {
8930        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8931        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8932            return false;
8933        }
8934        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8935            return false;
8936        }
8937        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8938            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8939            ViewRootImpl viewRootImpl = getViewRootImpl();
8940            if (viewRootImpl != null) {
8941                viewRootImpl.setAccessibilityFocus(this, null);
8942            }
8943            invalidate();
8944            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8945            return true;
8946        }
8947        return false;
8948    }
8949
8950    /**
8951     * Call this to try to clear accessibility focus of this view.
8952     *
8953     * See also {@link #focusSearch(int)}, which is what you call to say that you
8954     * have focus, and you want your parent to look for the next one.
8955     *
8956     * @hide
8957     */
8958    public void clearAccessibilityFocus() {
8959        clearAccessibilityFocusNoCallbacks(0);
8960
8961        // Clear the global reference of accessibility focus if this view or
8962        // any of its descendants had accessibility focus. This will NOT send
8963        // an event or update internal state if focus is cleared from a
8964        // descendant view, which may leave views in inconsistent states.
8965        final ViewRootImpl viewRootImpl = getViewRootImpl();
8966        if (viewRootImpl != null) {
8967            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8968            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8969                viewRootImpl.setAccessibilityFocus(null, null);
8970            }
8971        }
8972    }
8973
8974    private void sendAccessibilityHoverEvent(int eventType) {
8975        // Since we are not delivering to a client accessibility events from not
8976        // important views (unless the clinet request that) we need to fire the
8977        // event from the deepest view exposed to the client. As a consequence if
8978        // the user crosses a not exposed view the client will see enter and exit
8979        // of the exposed predecessor followed by and enter and exit of that same
8980        // predecessor when entering and exiting the not exposed descendant. This
8981        // is fine since the client has a clear idea which view is hovered at the
8982        // price of a couple more events being sent. This is a simple and
8983        // working solution.
8984        View source = this;
8985        while (true) {
8986            if (source.includeForAccessibility()) {
8987                source.sendAccessibilityEvent(eventType);
8988                return;
8989            }
8990            ViewParent parent = source.getParent();
8991            if (parent instanceof View) {
8992                source = (View) parent;
8993            } else {
8994                return;
8995            }
8996        }
8997    }
8998
8999    /**
9000     * Clears accessibility focus without calling any callback methods
9001     * normally invoked in {@link #clearAccessibilityFocus()}. This method
9002     * is used separately from that one for clearing accessibility focus when
9003     * giving this focus to another view.
9004     *
9005     * @param action The action, if any, that led to focus being cleared. Set to
9006     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
9007     * the window.
9008     */
9009    void clearAccessibilityFocusNoCallbacks(int action) {
9010        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
9011            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
9012            invalidate();
9013            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9014                AccessibilityEvent event = AccessibilityEvent.obtain(
9015                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
9016                event.setAction(action);
9017                if (mAccessibilityDelegate != null) {
9018                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
9019                } else {
9020                    sendAccessibilityEventUnchecked(event);
9021                }
9022            }
9023        }
9024    }
9025
9026    /**
9027     * Call this to try to give focus to a specific view or to one of its
9028     * descendants.
9029     *
9030     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9031     * false), or if it is focusable and it is not focusable in touch mode
9032     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9033     *
9034     * See also {@link #focusSearch(int)}, which is what you call to say that you
9035     * have focus, and you want your parent to look for the next one.
9036     *
9037     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
9038     * {@link #FOCUS_DOWN} and <code>null</code>.
9039     *
9040     * @return Whether this view or one of its descendants actually took focus.
9041     */
9042    public final boolean requestFocus() {
9043        return requestFocus(View.FOCUS_DOWN);
9044    }
9045
9046    /**
9047     * Call this to try to give focus to a specific view or to one of its
9048     * descendants and give it a hint about what direction focus is heading.
9049     *
9050     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9051     * false), or if it is focusable and it is not focusable in touch mode
9052     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9053     *
9054     * See also {@link #focusSearch(int)}, which is what you call to say that you
9055     * have focus, and you want your parent to look for the next one.
9056     *
9057     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
9058     * <code>null</code> set for the previously focused rectangle.
9059     *
9060     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9061     * @return Whether this view or one of its descendants actually took focus.
9062     */
9063    public final boolean requestFocus(int direction) {
9064        return requestFocus(direction, null);
9065    }
9066
9067    /**
9068     * Call this to try to give focus to a specific view or to one of its descendants
9069     * and give it hints about the direction and a specific rectangle that the focus
9070     * is coming from.  The rectangle can help give larger views a finer grained hint
9071     * about where focus is coming from, and therefore, where to show selection, or
9072     * forward focus change internally.
9073     *
9074     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9075     * false), or if it is focusable and it is not focusable in touch mode
9076     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9077     *
9078     * A View will not take focus if it is not visible.
9079     *
9080     * A View will not take focus if one of its parents has
9081     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
9082     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
9083     *
9084     * See also {@link #focusSearch(int)}, which is what you call to say that you
9085     * have focus, and you want your parent to look for the next one.
9086     *
9087     * You may wish to override this method if your custom {@link View} has an internal
9088     * {@link View} that it wishes to forward the request to.
9089     *
9090     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9091     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
9092     *        to give a finer grained hint about where focus is coming from.  May be null
9093     *        if there is no hint.
9094     * @return Whether this view or one of its descendants actually took focus.
9095     */
9096    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
9097        return requestFocusNoSearch(direction, previouslyFocusedRect);
9098    }
9099
9100    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
9101        // need to be focusable
9102        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
9103                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9104            return false;
9105        }
9106
9107        // need to be focusable in touch mode if in touch mode
9108        if (isInTouchMode() &&
9109            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
9110               return false;
9111        }
9112
9113        // need to not have any parents blocking us
9114        if (hasAncestorThatBlocksDescendantFocus()) {
9115            return false;
9116        }
9117
9118        handleFocusGainInternal(direction, previouslyFocusedRect);
9119        return true;
9120    }
9121
9122    /**
9123     * Call this to try to give focus to a specific view or to one of its descendants. This is a
9124     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
9125     * touch mode to request focus when they are touched.
9126     *
9127     * @return Whether this view or one of its descendants actually took focus.
9128     *
9129     * @see #isInTouchMode()
9130     *
9131     */
9132    public final boolean requestFocusFromTouch() {
9133        // Leave touch mode if we need to
9134        if (isInTouchMode()) {
9135            ViewRootImpl viewRoot = getViewRootImpl();
9136            if (viewRoot != null) {
9137                viewRoot.ensureTouchMode(false);
9138            }
9139        }
9140        return requestFocus(View.FOCUS_DOWN);
9141    }
9142
9143    /**
9144     * @return Whether any ancestor of this view blocks descendant focus.
9145     */
9146    private boolean hasAncestorThatBlocksDescendantFocus() {
9147        final boolean focusableInTouchMode = isFocusableInTouchMode();
9148        ViewParent ancestor = mParent;
9149        while (ancestor instanceof ViewGroup) {
9150            final ViewGroup vgAncestor = (ViewGroup) ancestor;
9151            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
9152                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
9153                return true;
9154            } else {
9155                ancestor = vgAncestor.getParent();
9156            }
9157        }
9158        return false;
9159    }
9160
9161    /**
9162     * Gets the mode for determining whether this View is important for accessibility
9163     * which is if it fires accessibility events and if it is reported to
9164     * accessibility services that query the screen.
9165     *
9166     * @return The mode for determining whether a View is important for accessibility.
9167     *
9168     * @attr ref android.R.styleable#View_importantForAccessibility
9169     *
9170     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9171     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9172     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9173     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9174     */
9175    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
9176            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
9177            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
9178            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
9179            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
9180                    to = "noHideDescendants")
9181        })
9182    public int getImportantForAccessibility() {
9183        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9184                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9185    }
9186
9187    /**
9188     * Sets the live region mode for this view. This indicates to accessibility
9189     * services whether they should automatically notify the user about changes
9190     * to the view's content description or text, or to the content descriptions
9191     * or text of the view's children (where applicable).
9192     * <p>
9193     * For example, in a login screen with a TextView that displays an "incorrect
9194     * password" notification, that view should be marked as a live region with
9195     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9196     * <p>
9197     * To disable change notifications for this view, use
9198     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
9199     * mode for most views.
9200     * <p>
9201     * To indicate that the user should be notified of changes, use
9202     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9203     * <p>
9204     * If the view's changes should interrupt ongoing speech and notify the user
9205     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
9206     *
9207     * @param mode The live region mode for this view, one of:
9208     *        <ul>
9209     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
9210     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
9211     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
9212     *        </ul>
9213     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9214     */
9215    public void setAccessibilityLiveRegion(int mode) {
9216        if (mode != getAccessibilityLiveRegion()) {
9217            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9218            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
9219                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9220            notifyViewAccessibilityStateChangedIfNeeded(
9221                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9222        }
9223    }
9224
9225    /**
9226     * Gets the live region mode for this View.
9227     *
9228     * @return The live region mode for the view.
9229     *
9230     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9231     *
9232     * @see #setAccessibilityLiveRegion(int)
9233     */
9234    public int getAccessibilityLiveRegion() {
9235        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
9236                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
9237    }
9238
9239    /**
9240     * Sets how to determine whether this view is important for accessibility
9241     * which is if it fires accessibility events and if it is reported to
9242     * accessibility services that query the screen.
9243     *
9244     * @param mode How to determine whether this view is important for accessibility.
9245     *
9246     * @attr ref android.R.styleable#View_importantForAccessibility
9247     *
9248     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9249     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9250     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9251     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9252     */
9253    public void setImportantForAccessibility(int mode) {
9254        final int oldMode = getImportantForAccessibility();
9255        if (mode != oldMode) {
9256            final boolean hideDescendants =
9257                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
9258
9259            // If this node or its descendants are no longer important, try to
9260            // clear accessibility focus.
9261            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
9262                final View focusHost = findAccessibilityFocusHost(hideDescendants);
9263                if (focusHost != null) {
9264                    focusHost.clearAccessibilityFocus();
9265                }
9266            }
9267
9268            // If we're moving between AUTO and another state, we might not need
9269            // to send a subtree changed notification. We'll store the computed
9270            // importance, since we'll need to check it later to make sure.
9271            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
9272                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
9273            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
9274            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9275            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
9276                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9277            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
9278                notifySubtreeAccessibilityStateChangedIfNeeded();
9279            } else {
9280                notifyViewAccessibilityStateChangedIfNeeded(
9281                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9282            }
9283        }
9284    }
9285
9286    /**
9287     * Returns the view within this view's hierarchy that is hosting
9288     * accessibility focus.
9289     *
9290     * @param searchDescendants whether to search for focus in descendant views
9291     * @return the view hosting accessibility focus, or {@code null}
9292     */
9293    private View findAccessibilityFocusHost(boolean searchDescendants) {
9294        if (isAccessibilityFocusedViewOrHost()) {
9295            return this;
9296        }
9297
9298        if (searchDescendants) {
9299            final ViewRootImpl viewRoot = getViewRootImpl();
9300            if (viewRoot != null) {
9301                final View focusHost = viewRoot.getAccessibilityFocusedHost();
9302                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9303                    return focusHost;
9304                }
9305            }
9306        }
9307
9308        return null;
9309    }
9310
9311    /**
9312     * Computes whether this view should be exposed for accessibility. In
9313     * general, views that are interactive or provide information are exposed
9314     * while views that serve only as containers are hidden.
9315     * <p>
9316     * If an ancestor of this view has importance
9317     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
9318     * returns <code>false</code>.
9319     * <p>
9320     * Otherwise, the value is computed according to the view's
9321     * {@link #getImportantForAccessibility()} value:
9322     * <ol>
9323     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
9324     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
9325     * </code>
9326     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
9327     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
9328     * view satisfies any of the following:
9329     * <ul>
9330     * <li>Is actionable, e.g. {@link #isClickable()},
9331     * {@link #isLongClickable()}, or {@link #isFocusable()}
9332     * <li>Has an {@link AccessibilityDelegate}
9333     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
9334     * {@link OnKeyListener}, etc.
9335     * <li>Is an accessibility live region, e.g.
9336     * {@link #getAccessibilityLiveRegion()} is not
9337     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
9338     * </ul>
9339     * </ol>
9340     *
9341     * @return Whether the view is exposed for accessibility.
9342     * @see #setImportantForAccessibility(int)
9343     * @see #getImportantForAccessibility()
9344     */
9345    public boolean isImportantForAccessibility() {
9346        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9347                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9348        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
9349                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9350            return false;
9351        }
9352
9353        // Check parent mode to ensure we're not hidden.
9354        ViewParent parent = mParent;
9355        while (parent instanceof View) {
9356            if (((View) parent).getImportantForAccessibility()
9357                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9358                return false;
9359            }
9360            parent = parent.getParent();
9361        }
9362
9363        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
9364                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
9365                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
9366    }
9367
9368    /**
9369     * Gets the parent for accessibility purposes. Note that the parent for
9370     * accessibility is not necessary the immediate parent. It is the first
9371     * predecessor that is important for accessibility.
9372     *
9373     * @return The parent for accessibility purposes.
9374     */
9375    public ViewParent getParentForAccessibility() {
9376        if (mParent instanceof View) {
9377            View parentView = (View) mParent;
9378            if (parentView.includeForAccessibility()) {
9379                return mParent;
9380            } else {
9381                return mParent.getParentForAccessibility();
9382            }
9383        }
9384        return null;
9385    }
9386
9387    /**
9388     * Adds the children of this View relevant for accessibility to the given list
9389     * as output. Since some Views are not important for accessibility the added
9390     * child views are not necessarily direct children of this view, rather they are
9391     * the first level of descendants important for accessibility.
9392     *
9393     * @param outChildren The output list that will receive children for accessibility.
9394     */
9395    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
9396
9397    }
9398
9399    /**
9400     * Whether to regard this view for accessibility. A view is regarded for
9401     * accessibility if it is important for accessibility or the querying
9402     * accessibility service has explicitly requested that view not
9403     * important for accessibility are regarded.
9404     *
9405     * @return Whether to regard the view for accessibility.
9406     *
9407     * @hide
9408     */
9409    public boolean includeForAccessibility() {
9410        if (mAttachInfo != null) {
9411            return (mAttachInfo.mAccessibilityFetchFlags
9412                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
9413                    || isImportantForAccessibility();
9414        }
9415        return false;
9416    }
9417
9418    /**
9419     * Returns whether the View is considered actionable from
9420     * accessibility perspective. Such view are important for
9421     * accessibility.
9422     *
9423     * @return True if the view is actionable for accessibility.
9424     *
9425     * @hide
9426     */
9427    public boolean isActionableForAccessibility() {
9428        return (isClickable() || isLongClickable() || isFocusable());
9429    }
9430
9431    /**
9432     * Returns whether the View has registered callbacks which makes it
9433     * important for accessibility.
9434     *
9435     * @return True if the view is actionable for accessibility.
9436     */
9437    private boolean hasListenersForAccessibility() {
9438        ListenerInfo info = getListenerInfo();
9439        return mTouchDelegate != null || info.mOnKeyListener != null
9440                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
9441                || info.mOnHoverListener != null || info.mOnDragListener != null;
9442    }
9443
9444    /**
9445     * Notifies that the accessibility state of this view changed. The change
9446     * is local to this view and does not represent structural changes such
9447     * as children and parent. For example, the view became focusable. The
9448     * notification is at at most once every
9449     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9450     * to avoid unnecessary load to the system. Also once a view has a pending
9451     * notification this method is a NOP until the notification has been sent.
9452     *
9453     * @hide
9454     */
9455    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
9456        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9457            return;
9458        }
9459        if (mSendViewStateChangedAccessibilityEvent == null) {
9460            mSendViewStateChangedAccessibilityEvent =
9461                    new SendViewStateChangedAccessibilityEvent();
9462        }
9463        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9464    }
9465
9466    /**
9467     * Notifies that the accessibility state of this view changed. The change
9468     * is *not* local to this view and does represent structural changes such
9469     * as children and parent. For example, the view size changed. The
9470     * notification is at at most once every
9471     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9472     * to avoid unnecessary load to the system. Also once a view has a pending
9473     * notification this method is a NOP until the notification has been sent.
9474     *
9475     * @hide
9476     */
9477    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9478        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9479            return;
9480        }
9481        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9482            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9483            if (mParent != null) {
9484                try {
9485                    mParent.notifySubtreeAccessibilityStateChanged(
9486                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9487                } catch (AbstractMethodError e) {
9488                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9489                            " does not fully implement ViewParent", e);
9490                }
9491            }
9492        }
9493    }
9494
9495    /**
9496     * Change the visibility of the View without triggering any other changes. This is
9497     * important for transitions, where visibility changes should not adjust focus or
9498     * trigger a new layout. This is only used when the visibility has already been changed
9499     * and we need a transient value during an animation. When the animation completes,
9500     * the original visibility value is always restored.
9501     *
9502     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9503     * @hide
9504     */
9505    public void setTransitionVisibility(@Visibility int visibility) {
9506        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9507    }
9508
9509    /**
9510     * Reset the flag indicating the accessibility state of the subtree rooted
9511     * at this view changed.
9512     */
9513    void resetSubtreeAccessibilityStateChanged() {
9514        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9515    }
9516
9517    /**
9518     * Report an accessibility action to this view's parents for delegated processing.
9519     *
9520     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9521     * call this method to delegate an accessibility action to a supporting parent. If the parent
9522     * returns true from its
9523     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9524     * method this method will return true to signify that the action was consumed.</p>
9525     *
9526     * <p>This method is useful for implementing nested scrolling child views. If
9527     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9528     * a custom view implementation may invoke this method to allow a parent to consume the
9529     * scroll first. If this method returns true the custom view should skip its own scrolling
9530     * behavior.</p>
9531     *
9532     * @param action Accessibility action to delegate
9533     * @param arguments Optional action arguments
9534     * @return true if the action was consumed by a parent
9535     */
9536    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9537        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9538            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9539                return true;
9540            }
9541        }
9542        return false;
9543    }
9544
9545    /**
9546     * Performs the specified accessibility action on the view. For
9547     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9548     * <p>
9549     * If an {@link AccessibilityDelegate} has been specified via calling
9550     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9551     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9552     * is responsible for handling this call.
9553     * </p>
9554     *
9555     * <p>The default implementation will delegate
9556     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9557     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9558     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9559     *
9560     * @param action The action to perform.
9561     * @param arguments Optional action arguments.
9562     * @return Whether the action was performed.
9563     */
9564    public boolean performAccessibilityAction(int action, Bundle arguments) {
9565      if (mAccessibilityDelegate != null) {
9566          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9567      } else {
9568          return performAccessibilityActionInternal(action, arguments);
9569      }
9570    }
9571
9572   /**
9573    * @see #performAccessibilityAction(int, Bundle)
9574    *
9575    * Note: Called from the default {@link AccessibilityDelegate}.
9576    *
9577    * @hide
9578    */
9579    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9580        if (isNestedScrollingEnabled()
9581                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9582                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9583                || action == R.id.accessibilityActionScrollUp
9584                || action == R.id.accessibilityActionScrollLeft
9585                || action == R.id.accessibilityActionScrollDown
9586                || action == R.id.accessibilityActionScrollRight)) {
9587            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9588                return true;
9589            }
9590        }
9591
9592        switch (action) {
9593            case AccessibilityNodeInfo.ACTION_CLICK: {
9594                if (isClickable()) {
9595                    performClick();
9596                    return true;
9597                }
9598            } break;
9599            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9600                if (isLongClickable()) {
9601                    performLongClick();
9602                    return true;
9603                }
9604            } break;
9605            case AccessibilityNodeInfo.ACTION_FOCUS: {
9606                if (!hasFocus()) {
9607                    // Get out of touch mode since accessibility
9608                    // wants to move focus around.
9609                    getViewRootImpl().ensureTouchMode(false);
9610                    return requestFocus();
9611                }
9612            } break;
9613            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9614                if (hasFocus()) {
9615                    clearFocus();
9616                    return !isFocused();
9617                }
9618            } break;
9619            case AccessibilityNodeInfo.ACTION_SELECT: {
9620                if (!isSelected()) {
9621                    setSelected(true);
9622                    return isSelected();
9623                }
9624            } break;
9625            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9626                if (isSelected()) {
9627                    setSelected(false);
9628                    return !isSelected();
9629                }
9630            } break;
9631            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9632                if (!isAccessibilityFocused()) {
9633                    return requestAccessibilityFocus();
9634                }
9635            } break;
9636            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9637                if (isAccessibilityFocused()) {
9638                    clearAccessibilityFocus();
9639                    return true;
9640                }
9641            } break;
9642            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9643                if (arguments != null) {
9644                    final int granularity = arguments.getInt(
9645                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9646                    final boolean extendSelection = arguments.getBoolean(
9647                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9648                    return traverseAtGranularity(granularity, true, extendSelection);
9649                }
9650            } break;
9651            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9652                if (arguments != null) {
9653                    final int granularity = arguments.getInt(
9654                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9655                    final boolean extendSelection = arguments.getBoolean(
9656                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9657                    return traverseAtGranularity(granularity, false, extendSelection);
9658                }
9659            } break;
9660            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9661                CharSequence text = getIterableTextForAccessibility();
9662                if (text == null) {
9663                    return false;
9664                }
9665                final int start = (arguments != null) ? arguments.getInt(
9666                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9667                final int end = (arguments != null) ? arguments.getInt(
9668                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9669                // Only cursor position can be specified (selection length == 0)
9670                if ((getAccessibilitySelectionStart() != start
9671                        || getAccessibilitySelectionEnd() != end)
9672                        && (start == end)) {
9673                    setAccessibilitySelection(start, end);
9674                    notifyViewAccessibilityStateChangedIfNeeded(
9675                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9676                    return true;
9677                }
9678            } break;
9679            case R.id.accessibilityActionShowOnScreen: {
9680                if (mAttachInfo != null) {
9681                    final Rect r = mAttachInfo.mTmpInvalRect;
9682                    getDrawingRect(r);
9683                    return requestRectangleOnScreen(r, true);
9684                }
9685            } break;
9686            case R.id.accessibilityActionContextClick: {
9687                if (isContextClickable()) {
9688                    performContextClick();
9689                    return true;
9690                }
9691            } break;
9692        }
9693        return false;
9694    }
9695
9696    private boolean traverseAtGranularity(int granularity, boolean forward,
9697            boolean extendSelection) {
9698        CharSequence text = getIterableTextForAccessibility();
9699        if (text == null || text.length() == 0) {
9700            return false;
9701        }
9702        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9703        if (iterator == null) {
9704            return false;
9705        }
9706        int current = getAccessibilitySelectionEnd();
9707        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9708            current = forward ? 0 : text.length();
9709        }
9710        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9711        if (range == null) {
9712            return false;
9713        }
9714        final int segmentStart = range[0];
9715        final int segmentEnd = range[1];
9716        int selectionStart;
9717        int selectionEnd;
9718        if (extendSelection && isAccessibilitySelectionExtendable()) {
9719            selectionStart = getAccessibilitySelectionStart();
9720            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9721                selectionStart = forward ? segmentStart : segmentEnd;
9722            }
9723            selectionEnd = forward ? segmentEnd : segmentStart;
9724        } else {
9725            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9726        }
9727        setAccessibilitySelection(selectionStart, selectionEnd);
9728        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9729                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9730        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9731        return true;
9732    }
9733
9734    /**
9735     * Gets the text reported for accessibility purposes.
9736     *
9737     * @return The accessibility text.
9738     *
9739     * @hide
9740     */
9741    public CharSequence getIterableTextForAccessibility() {
9742        return getContentDescription();
9743    }
9744
9745    /**
9746     * Gets whether accessibility selection can be extended.
9747     *
9748     * @return If selection is extensible.
9749     *
9750     * @hide
9751     */
9752    public boolean isAccessibilitySelectionExtendable() {
9753        return false;
9754    }
9755
9756    /**
9757     * @hide
9758     */
9759    public int getAccessibilitySelectionStart() {
9760        return mAccessibilityCursorPosition;
9761    }
9762
9763    /**
9764     * @hide
9765     */
9766    public int getAccessibilitySelectionEnd() {
9767        return getAccessibilitySelectionStart();
9768    }
9769
9770    /**
9771     * @hide
9772     */
9773    public void setAccessibilitySelection(int start, int end) {
9774        if (start ==  end && end == mAccessibilityCursorPosition) {
9775            return;
9776        }
9777        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9778            mAccessibilityCursorPosition = start;
9779        } else {
9780            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9781        }
9782        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9783    }
9784
9785    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9786            int fromIndex, int toIndex) {
9787        if (mParent == null) {
9788            return;
9789        }
9790        AccessibilityEvent event = AccessibilityEvent.obtain(
9791                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9792        onInitializeAccessibilityEvent(event);
9793        onPopulateAccessibilityEvent(event);
9794        event.setFromIndex(fromIndex);
9795        event.setToIndex(toIndex);
9796        event.setAction(action);
9797        event.setMovementGranularity(granularity);
9798        mParent.requestSendAccessibilityEvent(this, event);
9799    }
9800
9801    /**
9802     * @hide
9803     */
9804    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9805        switch (granularity) {
9806            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9807                CharSequence text = getIterableTextForAccessibility();
9808                if (text != null && text.length() > 0) {
9809                    CharacterTextSegmentIterator iterator =
9810                        CharacterTextSegmentIterator.getInstance(
9811                                mContext.getResources().getConfiguration().locale);
9812                    iterator.initialize(text.toString());
9813                    return iterator;
9814                }
9815            } break;
9816            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9817                CharSequence text = getIterableTextForAccessibility();
9818                if (text != null && text.length() > 0) {
9819                    WordTextSegmentIterator iterator =
9820                        WordTextSegmentIterator.getInstance(
9821                                mContext.getResources().getConfiguration().locale);
9822                    iterator.initialize(text.toString());
9823                    return iterator;
9824                }
9825            } break;
9826            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9827                CharSequence text = getIterableTextForAccessibility();
9828                if (text != null && text.length() > 0) {
9829                    ParagraphTextSegmentIterator iterator =
9830                        ParagraphTextSegmentIterator.getInstance();
9831                    iterator.initialize(text.toString());
9832                    return iterator;
9833                }
9834            } break;
9835        }
9836        return null;
9837    }
9838
9839    /**
9840     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
9841     * and {@link #onFinishTemporaryDetach()}.
9842     */
9843    public final boolean isTemporarilyDetached() {
9844        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
9845    }
9846
9847    /**
9848     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
9849     * a container View.
9850     */
9851    @CallSuper
9852    public void dispatchStartTemporaryDetach() {
9853        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
9854        onStartTemporaryDetach();
9855    }
9856
9857    /**
9858     * This is called when a container is going to temporarily detach a child, with
9859     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9860     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9861     * {@link #onDetachedFromWindow()} when the container is done.
9862     */
9863    public void onStartTemporaryDetach() {
9864        removeUnsetPressCallback();
9865        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9866    }
9867
9868    /**
9869     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
9870     * a container View.
9871     */
9872    @CallSuper
9873    public void dispatchFinishTemporaryDetach() {
9874        onFinishTemporaryDetach();
9875        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
9876    }
9877
9878    /**
9879     * Called after {@link #onStartTemporaryDetach} when the container is done
9880     * changing the view.
9881     */
9882    public void onFinishTemporaryDetach() {
9883    }
9884
9885    /**
9886     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9887     * for this view's window.  Returns null if the view is not currently attached
9888     * to the window.  Normally you will not need to use this directly, but
9889     * just use the standard high-level event callbacks like
9890     * {@link #onKeyDown(int, KeyEvent)}.
9891     */
9892    public KeyEvent.DispatcherState getKeyDispatcherState() {
9893        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9894    }
9895
9896    /**
9897     * Dispatch a key event before it is processed by any input method
9898     * associated with the view hierarchy.  This can be used to intercept
9899     * key events in special situations before the IME consumes them; a
9900     * typical example would be handling the BACK key to update the application's
9901     * UI instead of allowing the IME to see it and close itself.
9902     *
9903     * @param event The key event to be dispatched.
9904     * @return True if the event was handled, false otherwise.
9905     */
9906    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9907        return onKeyPreIme(event.getKeyCode(), event);
9908    }
9909
9910    /**
9911     * Dispatch a key event to the next view on the focus path. This path runs
9912     * from the top of the view tree down to the currently focused view. If this
9913     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9914     * the next node down the focus path. This method also fires any key
9915     * listeners.
9916     *
9917     * @param event The key event to be dispatched.
9918     * @return True if the event was handled, false otherwise.
9919     */
9920    public boolean dispatchKeyEvent(KeyEvent event) {
9921        if (mInputEventConsistencyVerifier != null) {
9922            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9923        }
9924
9925        // Give any attached key listener a first crack at the event.
9926        //noinspection SimplifiableIfStatement
9927        ListenerInfo li = mListenerInfo;
9928        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9929                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9930            return true;
9931        }
9932
9933        if (event.dispatch(this, mAttachInfo != null
9934                ? mAttachInfo.mKeyDispatchState : null, this)) {
9935            return true;
9936        }
9937
9938        if (mInputEventConsistencyVerifier != null) {
9939            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9940        }
9941        return false;
9942    }
9943
9944    /**
9945     * Dispatches a key shortcut event.
9946     *
9947     * @param event The key event to be dispatched.
9948     * @return True if the event was handled by the view, false otherwise.
9949     */
9950    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9951        return onKeyShortcut(event.getKeyCode(), event);
9952    }
9953
9954    /**
9955     * Pass the touch screen motion event down to the target view, or this
9956     * view if it is the target.
9957     *
9958     * @param event The motion event to be dispatched.
9959     * @return True if the event was handled by the view, false otherwise.
9960     */
9961    public boolean dispatchTouchEvent(MotionEvent event) {
9962        // If the event should be handled by accessibility focus first.
9963        if (event.isTargetAccessibilityFocus()) {
9964            // We don't have focus or no virtual descendant has it, do not handle the event.
9965            if (!isAccessibilityFocusedViewOrHost()) {
9966                return false;
9967            }
9968            // We have focus and got the event, then use normal event dispatch.
9969            event.setTargetAccessibilityFocus(false);
9970        }
9971
9972        boolean result = false;
9973
9974        if (mInputEventConsistencyVerifier != null) {
9975            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9976        }
9977
9978        final int actionMasked = event.getActionMasked();
9979        if (actionMasked == MotionEvent.ACTION_DOWN) {
9980            // Defensive cleanup for new gesture
9981            stopNestedScroll();
9982        }
9983
9984        if (onFilterTouchEventForSecurity(event)) {
9985            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
9986                result = true;
9987            }
9988            //noinspection SimplifiableIfStatement
9989            ListenerInfo li = mListenerInfo;
9990            if (li != null && li.mOnTouchListener != null
9991                    && (mViewFlags & ENABLED_MASK) == ENABLED
9992                    && li.mOnTouchListener.onTouch(this, event)) {
9993                result = true;
9994            }
9995
9996            if (!result && onTouchEvent(event)) {
9997                result = true;
9998            }
9999        }
10000
10001        if (!result && mInputEventConsistencyVerifier != null) {
10002            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10003        }
10004
10005        // Clean up after nested scrolls if this is the end of a gesture;
10006        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
10007        // of the gesture.
10008        if (actionMasked == MotionEvent.ACTION_UP ||
10009                actionMasked == MotionEvent.ACTION_CANCEL ||
10010                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
10011            stopNestedScroll();
10012        }
10013
10014        return result;
10015    }
10016
10017    boolean isAccessibilityFocusedViewOrHost() {
10018        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
10019                .getAccessibilityFocusedHost() == this);
10020    }
10021
10022    /**
10023     * Filter the touch event to apply security policies.
10024     *
10025     * @param event The motion event to be filtered.
10026     * @return True if the event should be dispatched, false if the event should be dropped.
10027     *
10028     * @see #getFilterTouchesWhenObscured
10029     */
10030    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
10031        //noinspection RedundantIfStatement
10032        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
10033                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
10034            // Window is obscured, drop this touch.
10035            return false;
10036        }
10037        return true;
10038    }
10039
10040    /**
10041     * Pass a trackball motion event down to the focused view.
10042     *
10043     * @param event The motion event to be dispatched.
10044     * @return True if the event was handled by the view, false otherwise.
10045     */
10046    public boolean dispatchTrackballEvent(MotionEvent event) {
10047        if (mInputEventConsistencyVerifier != null) {
10048            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
10049        }
10050
10051        return onTrackballEvent(event);
10052    }
10053
10054    /**
10055     * Dispatch a generic motion event.
10056     * <p>
10057     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10058     * are delivered to the view under the pointer.  All other generic motion events are
10059     * delivered to the focused view.  Hover events are handled specially and are delivered
10060     * to {@link #onHoverEvent(MotionEvent)}.
10061     * </p>
10062     *
10063     * @param event The motion event to be dispatched.
10064     * @return True if the event was handled by the view, false otherwise.
10065     */
10066    public boolean dispatchGenericMotionEvent(MotionEvent event) {
10067        if (mInputEventConsistencyVerifier != null) {
10068            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
10069        }
10070
10071        final int source = event.getSource();
10072        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
10073            final int action = event.getAction();
10074            if (action == MotionEvent.ACTION_HOVER_ENTER
10075                    || action == MotionEvent.ACTION_HOVER_MOVE
10076                    || action == MotionEvent.ACTION_HOVER_EXIT) {
10077                if (dispatchHoverEvent(event)) {
10078                    return true;
10079                }
10080            } else if (dispatchGenericPointerEvent(event)) {
10081                return true;
10082            }
10083        } else if (dispatchGenericFocusedEvent(event)) {
10084            return true;
10085        }
10086
10087        if (dispatchGenericMotionEventInternal(event)) {
10088            return true;
10089        }
10090
10091        if (mInputEventConsistencyVerifier != null) {
10092            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10093        }
10094        return false;
10095    }
10096
10097    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
10098        //noinspection SimplifiableIfStatement
10099        ListenerInfo li = mListenerInfo;
10100        if (li != null && li.mOnGenericMotionListener != null
10101                && (mViewFlags & ENABLED_MASK) == ENABLED
10102                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
10103            return true;
10104        }
10105
10106        if (onGenericMotionEvent(event)) {
10107            return true;
10108        }
10109
10110        final int actionButton = event.getActionButton();
10111        switch (event.getActionMasked()) {
10112            case MotionEvent.ACTION_BUTTON_PRESS:
10113                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
10114                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10115                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10116                    if (performContextClick(event.getX(), event.getY())) {
10117                        mInContextButtonPress = true;
10118                        setPressed(true, event.getX(), event.getY());
10119                        removeTapCallback();
10120                        removeLongPressCallback();
10121                        return true;
10122                    }
10123                }
10124                break;
10125
10126            case MotionEvent.ACTION_BUTTON_RELEASE:
10127                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10128                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10129                    mInContextButtonPress = false;
10130                    mIgnoreNextUpEvent = true;
10131                }
10132                break;
10133        }
10134
10135        if (mInputEventConsistencyVerifier != null) {
10136            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10137        }
10138        return false;
10139    }
10140
10141    /**
10142     * Dispatch a hover event.
10143     * <p>
10144     * Do not call this method directly.
10145     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10146     * </p>
10147     *
10148     * @param event The motion event to be dispatched.
10149     * @return True if the event was handled by the view, false otherwise.
10150     */
10151    protected boolean dispatchHoverEvent(MotionEvent event) {
10152        ListenerInfo li = mListenerInfo;
10153        //noinspection SimplifiableIfStatement
10154        if (li != null && li.mOnHoverListener != null
10155                && (mViewFlags & ENABLED_MASK) == ENABLED
10156                && li.mOnHoverListener.onHover(this, event)) {
10157            return true;
10158        }
10159
10160        return onHoverEvent(event);
10161    }
10162
10163    /**
10164     * Returns true if the view has a child to which it has recently sent
10165     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
10166     * it does not have a hovered child, then it must be the innermost hovered view.
10167     * @hide
10168     */
10169    protected boolean hasHoveredChild() {
10170        return false;
10171    }
10172
10173    /**
10174     * Dispatch a generic motion event to the view under the first pointer.
10175     * <p>
10176     * Do not call this method directly.
10177     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10178     * </p>
10179     *
10180     * @param event The motion event to be dispatched.
10181     * @return True if the event was handled by the view, false otherwise.
10182     */
10183    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
10184        return false;
10185    }
10186
10187    /**
10188     * Dispatch a generic motion event to the currently focused view.
10189     * <p>
10190     * Do not call this method directly.
10191     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10192     * </p>
10193     *
10194     * @param event The motion event to be dispatched.
10195     * @return True if the event was handled by the view, false otherwise.
10196     */
10197    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
10198        return false;
10199    }
10200
10201    /**
10202     * Dispatch a pointer event.
10203     * <p>
10204     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
10205     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
10206     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
10207     * and should not be expected to handle other pointing device features.
10208     * </p>
10209     *
10210     * @param event The motion event to be dispatched.
10211     * @return True if the event was handled by the view, false otherwise.
10212     * @hide
10213     */
10214    public final boolean dispatchPointerEvent(MotionEvent event) {
10215        if (event.isTouchEvent()) {
10216            return dispatchTouchEvent(event);
10217        } else {
10218            return dispatchGenericMotionEvent(event);
10219        }
10220    }
10221
10222    /**
10223     * Called when the window containing this view gains or loses window focus.
10224     * ViewGroups should override to route to their children.
10225     *
10226     * @param hasFocus True if the window containing this view now has focus,
10227     *        false otherwise.
10228     */
10229    public void dispatchWindowFocusChanged(boolean hasFocus) {
10230        onWindowFocusChanged(hasFocus);
10231    }
10232
10233    /**
10234     * Called when the window containing this view gains or loses focus.  Note
10235     * that this is separate from view focus: to receive key events, both
10236     * your view and its window must have focus.  If a window is displayed
10237     * on top of yours that takes input focus, then your own window will lose
10238     * focus but the view focus will remain unchanged.
10239     *
10240     * @param hasWindowFocus True if the window containing this view now has
10241     *        focus, false otherwise.
10242     */
10243    public void onWindowFocusChanged(boolean hasWindowFocus) {
10244        InputMethodManager imm = InputMethodManager.peekInstance();
10245        if (!hasWindowFocus) {
10246            if (isPressed()) {
10247                setPressed(false);
10248            }
10249            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10250                imm.focusOut(this);
10251            }
10252            removeLongPressCallback();
10253            removeTapCallback();
10254            onFocusLost();
10255        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10256            imm.focusIn(this);
10257        }
10258        refreshDrawableState();
10259    }
10260
10261    /**
10262     * Returns true if this view is in a window that currently has window focus.
10263     * Note that this is not the same as the view itself having focus.
10264     *
10265     * @return True if this view is in a window that currently has window focus.
10266     */
10267    public boolean hasWindowFocus() {
10268        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
10269    }
10270
10271    /**
10272     * Dispatch a view visibility change down the view hierarchy.
10273     * ViewGroups should override to route to their children.
10274     * @param changedView The view whose visibility changed. Could be 'this' or
10275     * an ancestor view.
10276     * @param visibility The new visibility of changedView: {@link #VISIBLE},
10277     * {@link #INVISIBLE} or {@link #GONE}.
10278     */
10279    protected void dispatchVisibilityChanged(@NonNull View changedView,
10280            @Visibility int visibility) {
10281        onVisibilityChanged(changedView, visibility);
10282    }
10283
10284    /**
10285     * Called when the visibility of the view or an ancestor of the view has
10286     * changed.
10287     *
10288     * @param changedView The view whose visibility changed. May be
10289     *                    {@code this} or an ancestor view.
10290     * @param visibility The new visibility, one of {@link #VISIBLE},
10291     *                   {@link #INVISIBLE} or {@link #GONE}.
10292     */
10293    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
10294    }
10295
10296    /**
10297     * Dispatch a hint about whether this view is displayed. For instance, when
10298     * a View moves out of the screen, it might receives a display hint indicating
10299     * the view is not displayed. Applications should not <em>rely</em> on this hint
10300     * as there is no guarantee that they will receive one.
10301     *
10302     * @param hint A hint about whether or not this view is displayed:
10303     * {@link #VISIBLE} or {@link #INVISIBLE}.
10304     */
10305    public void dispatchDisplayHint(@Visibility int hint) {
10306        onDisplayHint(hint);
10307    }
10308
10309    /**
10310     * Gives this view a hint about whether is displayed or not. For instance, when
10311     * a View moves out of the screen, it might receives a display hint indicating
10312     * the view is not displayed. Applications should not <em>rely</em> on this hint
10313     * as there is no guarantee that they will receive one.
10314     *
10315     * @param hint A hint about whether or not this view is displayed:
10316     * {@link #VISIBLE} or {@link #INVISIBLE}.
10317     */
10318    protected void onDisplayHint(@Visibility int hint) {
10319    }
10320
10321    /**
10322     * Dispatch a window visibility change down the view hierarchy.
10323     * ViewGroups should override to route to their children.
10324     *
10325     * @param visibility The new visibility of the window.
10326     *
10327     * @see #onWindowVisibilityChanged(int)
10328     */
10329    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
10330        onWindowVisibilityChanged(visibility);
10331    }
10332
10333    /**
10334     * Called when the window containing has change its visibility
10335     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
10336     * that this tells you whether or not your window is being made visible
10337     * to the window manager; this does <em>not</em> tell you whether or not
10338     * your window is obscured by other windows on the screen, even if it
10339     * is itself visible.
10340     *
10341     * @param visibility The new visibility of the window.
10342     */
10343    protected void onWindowVisibilityChanged(@Visibility int visibility) {
10344        if (visibility == VISIBLE) {
10345            initialAwakenScrollBars();
10346        }
10347    }
10348
10349    /**
10350     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
10351     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
10352     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
10353     *
10354     * @param isVisible true if this view's visibility to the user is uninterrupted by its
10355     *                  ancestors or by window visibility
10356     * @return true if this view is visible to the user, not counting clipping or overlapping
10357     */
10358    @Visibility boolean dispatchVisibilityAggregated(boolean isVisible) {
10359        final boolean thisVisible = getVisibility() == VISIBLE;
10360        // If we're not visible but something is telling us we are, ignore it.
10361        if (thisVisible || !isVisible) {
10362            onVisibilityAggregated(isVisible);
10363        }
10364        return thisVisible && isVisible;
10365    }
10366
10367    /**
10368     * Called when the user-visibility of this View is potentially affected by a change
10369     * to this view itself, an ancestor view or the window this view is attached to.
10370     *
10371     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
10372     *                  and this view's window is also visible
10373     */
10374    @CallSuper
10375    public void onVisibilityAggregated(boolean isVisible) {
10376        if (isVisible && mAttachInfo != null) {
10377            initialAwakenScrollBars();
10378        }
10379
10380        final Drawable dr = mBackground;
10381        if (dr != null && isVisible != dr.isVisible()) {
10382            dr.setVisible(isVisible, false);
10383        }
10384        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
10385        if (fg != null && isVisible != fg.isVisible()) {
10386            fg.setVisible(isVisible, false);
10387        }
10388    }
10389
10390    /**
10391     * Returns the current visibility of the window this view is attached to
10392     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
10393     *
10394     * @return Returns the current visibility of the view's window.
10395     */
10396    @Visibility
10397    public int getWindowVisibility() {
10398        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
10399    }
10400
10401    /**
10402     * Retrieve the overall visible display size in which the window this view is
10403     * attached to has been positioned in.  This takes into account screen
10404     * decorations above the window, for both cases where the window itself
10405     * is being position inside of them or the window is being placed under
10406     * then and covered insets are used for the window to position its content
10407     * inside.  In effect, this tells you the available area where content can
10408     * be placed and remain visible to users.
10409     *
10410     * <p>This function requires an IPC back to the window manager to retrieve
10411     * the requested information, so should not be used in performance critical
10412     * code like drawing.
10413     *
10414     * @param outRect Filled in with the visible display frame.  If the view
10415     * is not attached to a window, this is simply the raw display size.
10416     */
10417    public void getWindowVisibleDisplayFrame(Rect outRect) {
10418        if (mAttachInfo != null) {
10419            try {
10420                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10421            } catch (RemoteException e) {
10422                return;
10423            }
10424            // XXX This is really broken, and probably all needs to be done
10425            // in the window manager, and we need to know more about whether
10426            // we want the area behind or in front of the IME.
10427            final Rect insets = mAttachInfo.mVisibleInsets;
10428            outRect.left += insets.left;
10429            outRect.top += insets.top;
10430            outRect.right -= insets.right;
10431            outRect.bottom -= insets.bottom;
10432            return;
10433        }
10434        // The view is not attached to a display so we don't have a context.
10435        // Make a best guess about the display size.
10436        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10437        d.getRectSize(outRect);
10438    }
10439
10440    /**
10441     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
10442     * is currently in without any insets.
10443     *
10444     * @hide
10445     */
10446    public void getWindowDisplayFrame(Rect outRect) {
10447        if (mAttachInfo != null) {
10448            try {
10449                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10450            } catch (RemoteException e) {
10451                return;
10452            }
10453            return;
10454        }
10455        // The view is not attached to a display so we don't have a context.
10456        // Make a best guess about the display size.
10457        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10458        d.getRectSize(outRect);
10459    }
10460
10461    /**
10462     * Dispatch a notification about a resource configuration change down
10463     * the view hierarchy.
10464     * ViewGroups should override to route to their children.
10465     *
10466     * @param newConfig The new resource configuration.
10467     *
10468     * @see #onConfigurationChanged(android.content.res.Configuration)
10469     */
10470    public void dispatchConfigurationChanged(Configuration newConfig) {
10471        onConfigurationChanged(newConfig);
10472    }
10473
10474    /**
10475     * Called when the current configuration of the resources being used
10476     * by the application have changed.  You can use this to decide when
10477     * to reload resources that can changed based on orientation and other
10478     * configuration characteristics.  You only need to use this if you are
10479     * not relying on the normal {@link android.app.Activity} mechanism of
10480     * recreating the activity instance upon a configuration change.
10481     *
10482     * @param newConfig The new resource configuration.
10483     */
10484    protected void onConfigurationChanged(Configuration newConfig) {
10485    }
10486
10487    /**
10488     * Private function to aggregate all per-view attributes in to the view
10489     * root.
10490     */
10491    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10492        performCollectViewAttributes(attachInfo, visibility);
10493    }
10494
10495    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10496        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
10497            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
10498                attachInfo.mKeepScreenOn = true;
10499            }
10500            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
10501            ListenerInfo li = mListenerInfo;
10502            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
10503                attachInfo.mHasSystemUiListeners = true;
10504            }
10505        }
10506    }
10507
10508    void needGlobalAttributesUpdate(boolean force) {
10509        final AttachInfo ai = mAttachInfo;
10510        if (ai != null && !ai.mRecomputeGlobalAttributes) {
10511            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
10512                    || ai.mHasSystemUiListeners) {
10513                ai.mRecomputeGlobalAttributes = true;
10514            }
10515        }
10516    }
10517
10518    /**
10519     * Returns whether the device is currently in touch mode.  Touch mode is entered
10520     * once the user begins interacting with the device by touch, and affects various
10521     * things like whether focus is always visible to the user.
10522     *
10523     * @return Whether the device is in touch mode.
10524     */
10525    @ViewDebug.ExportedProperty
10526    public boolean isInTouchMode() {
10527        if (mAttachInfo != null) {
10528            return mAttachInfo.mInTouchMode;
10529        } else {
10530            return ViewRootImpl.isInTouchMode();
10531        }
10532    }
10533
10534    /**
10535     * Returns the context the view is running in, through which it can
10536     * access the current theme, resources, etc.
10537     *
10538     * @return The view's Context.
10539     */
10540    @ViewDebug.CapturedViewProperty
10541    public final Context getContext() {
10542        return mContext;
10543    }
10544
10545    /**
10546     * Handle a key event before it is processed by any input method
10547     * associated with the view hierarchy.  This can be used to intercept
10548     * key events in special situations before the IME consumes them; a
10549     * typical example would be handling the BACK key to update the application's
10550     * UI instead of allowing the IME to see it and close itself.
10551     *
10552     * @param keyCode The value in event.getKeyCode().
10553     * @param event Description of the key event.
10554     * @return If you handled the event, return true. If you want to allow the
10555     *         event to be handled by the next receiver, return false.
10556     */
10557    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10558        return false;
10559    }
10560
10561    /**
10562     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10563     * KeyEvent.Callback.onKeyDown()}: perform press of the view
10564     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10565     * is released, if the view is enabled and clickable.
10566     * <p>
10567     * Key presses in software keyboards will generally NOT trigger this
10568     * listener, although some may elect to do so in some situations. Do not
10569     * rely on this to catch software key presses.
10570     *
10571     * @param keyCode a key code that represents the button pressed, from
10572     *                {@link android.view.KeyEvent}
10573     * @param event the KeyEvent object that defines the button action
10574     */
10575    public boolean onKeyDown(int keyCode, KeyEvent event) {
10576        if (KeyEvent.isConfirmKey(keyCode)) {
10577            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10578                return true;
10579            }
10580
10581            // Long clickable items don't necessarily have to be clickable.
10582            if (((mViewFlags & CLICKABLE) == CLICKABLE
10583                    || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10584                    && (event.getRepeatCount() == 0)) {
10585                // For the purposes of menu anchoring and drawable hotspots,
10586                // key events are considered to be at the center of the view.
10587                final float x = getWidth() / 2f;
10588                final float y = getHeight() / 2f;
10589                setPressed(true, x, y);
10590                checkForLongClick(0, x, y);
10591                return true;
10592            }
10593        }
10594
10595        return false;
10596    }
10597
10598    /**
10599     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
10600     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
10601     * the event).
10602     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10603     * although some may elect to do so in some situations. Do not rely on this to
10604     * catch software key presses.
10605     */
10606    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
10607        return false;
10608    }
10609
10610    /**
10611     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
10612     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
10613     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
10614     * or {@link KeyEvent#KEYCODE_SPACE} is released.
10615     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10616     * although some may elect to do so in some situations. Do not rely on this to
10617     * catch software key presses.
10618     *
10619     * @param keyCode A key code that represents the button pressed, from
10620     *                {@link android.view.KeyEvent}.
10621     * @param event   The KeyEvent object that defines the button action.
10622     */
10623    public boolean onKeyUp(int keyCode, KeyEvent event) {
10624        if (KeyEvent.isConfirmKey(keyCode)) {
10625            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10626                return true;
10627            }
10628            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
10629                setPressed(false);
10630
10631                if (!mHasPerformedLongPress) {
10632                    // This is a tap, so remove the longpress check
10633                    removeLongPressCallback();
10634                    return performClick();
10635                }
10636            }
10637        }
10638        return false;
10639    }
10640
10641    /**
10642     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10643     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
10644     * the event).
10645     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10646     * although some may elect to do so in some situations. Do not rely on this to
10647     * catch software key presses.
10648     *
10649     * @param keyCode     A key code that represents the button pressed, from
10650     *                    {@link android.view.KeyEvent}.
10651     * @param repeatCount The number of times the action was made.
10652     * @param event       The KeyEvent object that defines the button action.
10653     */
10654    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10655        return false;
10656    }
10657
10658    /**
10659     * Called on the focused view when a key shortcut event is not handled.
10660     * Override this method to implement local key shortcuts for the View.
10661     * Key shortcuts can also be implemented by setting the
10662     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10663     *
10664     * @param keyCode The value in event.getKeyCode().
10665     * @param event Description of the key event.
10666     * @return If you handled the event, return true. If you want to allow the
10667     *         event to be handled by the next receiver, return false.
10668     */
10669    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10670        return false;
10671    }
10672
10673    /**
10674     * Check whether the called view is a text editor, in which case it
10675     * would make sense to automatically display a soft input window for
10676     * it.  Subclasses should override this if they implement
10677     * {@link #onCreateInputConnection(EditorInfo)} to return true if
10678     * a call on that method would return a non-null InputConnection, and
10679     * they are really a first-class editor that the user would normally
10680     * start typing on when the go into a window containing your view.
10681     *
10682     * <p>The default implementation always returns false.  This does
10683     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10684     * will not be called or the user can not otherwise perform edits on your
10685     * view; it is just a hint to the system that this is not the primary
10686     * purpose of this view.
10687     *
10688     * @return Returns true if this view is a text editor, else false.
10689     */
10690    public boolean onCheckIsTextEditor() {
10691        return false;
10692    }
10693
10694    /**
10695     * Create a new InputConnection for an InputMethod to interact
10696     * with the view.  The default implementation returns null, since it doesn't
10697     * support input methods.  You can override this to implement such support.
10698     * This is only needed for views that take focus and text input.
10699     *
10700     * <p>When implementing this, you probably also want to implement
10701     * {@link #onCheckIsTextEditor()} to indicate you will return a
10702     * non-null InputConnection.</p>
10703     *
10704     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10705     * object correctly and in its entirety, so that the connected IME can rely
10706     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10707     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10708     * must be filled in with the correct cursor position for IMEs to work correctly
10709     * with your application.</p>
10710     *
10711     * @param outAttrs Fill in with attribute information about the connection.
10712     */
10713    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10714        return null;
10715    }
10716
10717    /**
10718     * Called by the {@link android.view.inputmethod.InputMethodManager}
10719     * when a view who is not the current
10720     * input connection target is trying to make a call on the manager.  The
10721     * default implementation returns false; you can override this to return
10722     * true for certain views if you are performing InputConnection proxying
10723     * to them.
10724     * @param view The View that is making the InputMethodManager call.
10725     * @return Return true to allow the call, false to reject.
10726     */
10727    public boolean checkInputConnectionProxy(View view) {
10728        return false;
10729    }
10730
10731    /**
10732     * Show the context menu for this view. It is not safe to hold on to the
10733     * menu after returning from this method.
10734     *
10735     * You should normally not overload this method. Overload
10736     * {@link #onCreateContextMenu(ContextMenu)} or define an
10737     * {@link OnCreateContextMenuListener} to add items to the context menu.
10738     *
10739     * @param menu The context menu to populate
10740     */
10741    public void createContextMenu(ContextMenu menu) {
10742        ContextMenuInfo menuInfo = getContextMenuInfo();
10743
10744        // Sets the current menu info so all items added to menu will have
10745        // my extra info set.
10746        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10747
10748        onCreateContextMenu(menu);
10749        ListenerInfo li = mListenerInfo;
10750        if (li != null && li.mOnCreateContextMenuListener != null) {
10751            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10752        }
10753
10754        // Clear the extra information so subsequent items that aren't mine don't
10755        // have my extra info.
10756        ((MenuBuilder)menu).setCurrentMenuInfo(null);
10757
10758        if (mParent != null) {
10759            mParent.createContextMenu(menu);
10760        }
10761    }
10762
10763    /**
10764     * Views should implement this if they have extra information to associate
10765     * with the context menu. The return result is supplied as a parameter to
10766     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10767     * callback.
10768     *
10769     * @return Extra information about the item for which the context menu
10770     *         should be shown. This information will vary across different
10771     *         subclasses of View.
10772     */
10773    protected ContextMenuInfo getContextMenuInfo() {
10774        return null;
10775    }
10776
10777    /**
10778     * Views should implement this if the view itself is going to add items to
10779     * the context menu.
10780     *
10781     * @param menu the context menu to populate
10782     */
10783    protected void onCreateContextMenu(ContextMenu menu) {
10784    }
10785
10786    /**
10787     * Implement this method to handle trackball motion events.  The
10788     * <em>relative</em> movement of the trackball since the last event
10789     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10790     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10791     * that a movement of 1 corresponds to the user pressing one DPAD key (so
10792     * they will often be fractional values, representing the more fine-grained
10793     * movement information available from a trackball).
10794     *
10795     * @param event The motion event.
10796     * @return True if the event was handled, false otherwise.
10797     */
10798    public boolean onTrackballEvent(MotionEvent event) {
10799        return false;
10800    }
10801
10802    /**
10803     * Implement this method to handle generic motion events.
10804     * <p>
10805     * Generic motion events describe joystick movements, mouse hovers, track pad
10806     * touches, scroll wheel movements and other input events.  The
10807     * {@link MotionEvent#getSource() source} of the motion event specifies
10808     * the class of input that was received.  Implementations of this method
10809     * must examine the bits in the source before processing the event.
10810     * The following code example shows how this is done.
10811     * </p><p>
10812     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10813     * are delivered to the view under the pointer.  All other generic motion events are
10814     * delivered to the focused view.
10815     * </p>
10816     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10817     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10818     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10819     *             // process the joystick movement...
10820     *             return true;
10821     *         }
10822     *     }
10823     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10824     *         switch (event.getAction()) {
10825     *             case MotionEvent.ACTION_HOVER_MOVE:
10826     *                 // process the mouse hover movement...
10827     *                 return true;
10828     *             case MotionEvent.ACTION_SCROLL:
10829     *                 // process the scroll wheel movement...
10830     *                 return true;
10831     *         }
10832     *     }
10833     *     return super.onGenericMotionEvent(event);
10834     * }</pre>
10835     *
10836     * @param event The generic motion event being processed.
10837     * @return True if the event was handled, false otherwise.
10838     */
10839    public boolean onGenericMotionEvent(MotionEvent event) {
10840        return false;
10841    }
10842
10843    /**
10844     * Implement this method to handle hover events.
10845     * <p>
10846     * This method is called whenever a pointer is hovering into, over, or out of the
10847     * bounds of a view and the view is not currently being touched.
10848     * Hover events are represented as pointer events with action
10849     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10850     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10851     * </p>
10852     * <ul>
10853     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10854     * when the pointer enters the bounds of the view.</li>
10855     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10856     * when the pointer has already entered the bounds of the view and has moved.</li>
10857     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10858     * when the pointer has exited the bounds of the view or when the pointer is
10859     * about to go down due to a button click, tap, or similar user action that
10860     * causes the view to be touched.</li>
10861     * </ul>
10862     * <p>
10863     * The view should implement this method to return true to indicate that it is
10864     * handling the hover event, such as by changing its drawable state.
10865     * </p><p>
10866     * The default implementation calls {@link #setHovered} to update the hovered state
10867     * of the view when a hover enter or hover exit event is received, if the view
10868     * is enabled and is clickable.  The default implementation also sends hover
10869     * accessibility events.
10870     * </p>
10871     *
10872     * @param event The motion event that describes the hover.
10873     * @return True if the view handled the hover event.
10874     *
10875     * @see #isHovered
10876     * @see #setHovered
10877     * @see #onHoverChanged
10878     */
10879    public boolean onHoverEvent(MotionEvent event) {
10880        // The root view may receive hover (or touch) events that are outside the bounds of
10881        // the window.  This code ensures that we only send accessibility events for
10882        // hovers that are actually within the bounds of the root view.
10883        final int action = event.getActionMasked();
10884        if (!mSendingHoverAccessibilityEvents) {
10885            if ((action == MotionEvent.ACTION_HOVER_ENTER
10886                    || action == MotionEvent.ACTION_HOVER_MOVE)
10887                    && !hasHoveredChild()
10888                    && pointInView(event.getX(), event.getY())) {
10889                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10890                mSendingHoverAccessibilityEvents = true;
10891            }
10892        } else {
10893            if (action == MotionEvent.ACTION_HOVER_EXIT
10894                    || (action == MotionEvent.ACTION_MOVE
10895                            && !pointInView(event.getX(), event.getY()))) {
10896                mSendingHoverAccessibilityEvents = false;
10897                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10898            }
10899        }
10900
10901        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
10902                && event.isFromSource(InputDevice.SOURCE_MOUSE)
10903                && isOnScrollbar(event.getX(), event.getY())) {
10904            awakenScrollBars();
10905        }
10906        if (isHoverable()) {
10907            switch (action) {
10908                case MotionEvent.ACTION_HOVER_ENTER:
10909                    setHovered(true);
10910                    break;
10911                case MotionEvent.ACTION_HOVER_EXIT:
10912                    setHovered(false);
10913                    break;
10914            }
10915
10916            // Dispatch the event to onGenericMotionEvent before returning true.
10917            // This is to provide compatibility with existing applications that
10918            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10919            // break because of the new default handling for hoverable views
10920            // in onHoverEvent.
10921            // Note that onGenericMotionEvent will be called by default when
10922            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10923            dispatchGenericMotionEventInternal(event);
10924            // The event was already handled by calling setHovered(), so always
10925            // return true.
10926            return true;
10927        }
10928
10929        return false;
10930    }
10931
10932    /**
10933     * Returns true if the view should handle {@link #onHoverEvent}
10934     * by calling {@link #setHovered} to change its hovered state.
10935     *
10936     * @return True if the view is hoverable.
10937     */
10938    private boolean isHoverable() {
10939        final int viewFlags = mViewFlags;
10940        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10941            return false;
10942        }
10943
10944        return (viewFlags & CLICKABLE) == CLICKABLE
10945                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10946                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10947    }
10948
10949    /**
10950     * Returns true if the view is currently hovered.
10951     *
10952     * @return True if the view is currently hovered.
10953     *
10954     * @see #setHovered
10955     * @see #onHoverChanged
10956     */
10957    @ViewDebug.ExportedProperty
10958    public boolean isHovered() {
10959        return (mPrivateFlags & PFLAG_HOVERED) != 0;
10960    }
10961
10962    /**
10963     * Sets whether the view is currently hovered.
10964     * <p>
10965     * Calling this method also changes the drawable state of the view.  This
10966     * enables the view to react to hover by using different drawable resources
10967     * to change its appearance.
10968     * </p><p>
10969     * The {@link #onHoverChanged} method is called when the hovered state changes.
10970     * </p>
10971     *
10972     * @param hovered True if the view is hovered.
10973     *
10974     * @see #isHovered
10975     * @see #onHoverChanged
10976     */
10977    public void setHovered(boolean hovered) {
10978        if (hovered) {
10979            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10980                mPrivateFlags |= PFLAG_HOVERED;
10981                refreshDrawableState();
10982                onHoverChanged(true);
10983            }
10984        } else {
10985            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10986                mPrivateFlags &= ~PFLAG_HOVERED;
10987                refreshDrawableState();
10988                onHoverChanged(false);
10989            }
10990        }
10991    }
10992
10993    /**
10994     * Implement this method to handle hover state changes.
10995     * <p>
10996     * This method is called whenever the hover state changes as a result of a
10997     * call to {@link #setHovered}.
10998     * </p>
10999     *
11000     * @param hovered The current hover state, as returned by {@link #isHovered}.
11001     *
11002     * @see #isHovered
11003     * @see #setHovered
11004     */
11005    public void onHoverChanged(boolean hovered) {
11006    }
11007
11008    /**
11009     * Handles scroll bar dragging by mouse input.
11010     *
11011     * @hide
11012     * @param event The motion event.
11013     *
11014     * @return true if the event was handled as a scroll bar dragging, false otherwise.
11015     */
11016    protected boolean handleScrollBarDragging(MotionEvent event) {
11017        if (mScrollCache == null) {
11018            return false;
11019        }
11020        final float x = event.getX();
11021        final float y = event.getY();
11022        final int action = event.getAction();
11023        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
11024                && action != MotionEvent.ACTION_DOWN)
11025                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
11026                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
11027            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11028            return false;
11029        }
11030
11031        switch (action) {
11032            case MotionEvent.ACTION_MOVE:
11033                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
11034                    return false;
11035                }
11036                if (mScrollCache.mScrollBarDraggingState
11037                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
11038                    final Rect bounds = mScrollCache.mScrollBarBounds;
11039                    getVerticalScrollBarBounds(bounds);
11040                    final int range = computeVerticalScrollRange();
11041                    final int offset = computeVerticalScrollOffset();
11042                    final int extent = computeVerticalScrollExtent();
11043
11044                    final int thumbLength = ScrollBarUtils.getThumbLength(
11045                            bounds.height(), bounds.width(), extent, range);
11046                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11047                            bounds.height(), thumbLength, extent, range, offset);
11048
11049                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
11050                    final float maxThumbOffset = bounds.height() - thumbLength;
11051                    final float newThumbOffset =
11052                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11053                    final int height = getHeight();
11054                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11055                            && height > 0 && extent > 0) {
11056                        final int newY = Math.round((range - extent)
11057                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
11058                        if (newY != getScrollY()) {
11059                            mScrollCache.mScrollBarDraggingPos = y;
11060                            setScrollY(newY);
11061                        }
11062                    }
11063                    return true;
11064                }
11065                if (mScrollCache.mScrollBarDraggingState
11066                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
11067                    final Rect bounds = mScrollCache.mScrollBarBounds;
11068                    getHorizontalScrollBarBounds(bounds);
11069                    final int range = computeHorizontalScrollRange();
11070                    final int offset = computeHorizontalScrollOffset();
11071                    final int extent = computeHorizontalScrollExtent();
11072
11073                    final int thumbLength = ScrollBarUtils.getThumbLength(
11074                            bounds.width(), bounds.height(), extent, range);
11075                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11076                            bounds.width(), thumbLength, extent, range, offset);
11077
11078                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
11079                    final float maxThumbOffset = bounds.width() - thumbLength;
11080                    final float newThumbOffset =
11081                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11082                    final int width = getWidth();
11083                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11084                            && width > 0 && extent > 0) {
11085                        final int newX = Math.round((range - extent)
11086                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
11087                        if (newX != getScrollX()) {
11088                            mScrollCache.mScrollBarDraggingPos = x;
11089                            setScrollX(newX);
11090                        }
11091                    }
11092                    return true;
11093                }
11094            case MotionEvent.ACTION_DOWN:
11095                if (mScrollCache.state == ScrollabilityCache.OFF) {
11096                    return false;
11097                }
11098                if (isOnVerticalScrollbarThumb(x, y)) {
11099                    mScrollCache.mScrollBarDraggingState =
11100                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
11101                    mScrollCache.mScrollBarDraggingPos = y;
11102                    return true;
11103                }
11104                if (isOnHorizontalScrollbarThumb(x, y)) {
11105                    mScrollCache.mScrollBarDraggingState =
11106                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
11107                    mScrollCache.mScrollBarDraggingPos = x;
11108                    return true;
11109                }
11110        }
11111        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11112        return false;
11113    }
11114
11115    /**
11116     * Implement this method to handle touch screen motion events.
11117     * <p>
11118     * If this method is used to detect click actions, it is recommended that
11119     * the actions be performed by implementing and calling
11120     * {@link #performClick()}. This will ensure consistent system behavior,
11121     * including:
11122     * <ul>
11123     * <li>obeying click sound preferences
11124     * <li>dispatching OnClickListener calls
11125     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
11126     * accessibility features are enabled
11127     * </ul>
11128     *
11129     * @param event The motion event.
11130     * @return True if the event was handled, false otherwise.
11131     */
11132    public boolean onTouchEvent(MotionEvent event) {
11133        final float x = event.getX();
11134        final float y = event.getY();
11135        final int viewFlags = mViewFlags;
11136        final int action = event.getAction();
11137
11138        if ((viewFlags & ENABLED_MASK) == DISABLED) {
11139            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
11140                setPressed(false);
11141            }
11142            // A disabled view that is clickable still consumes the touch
11143            // events, it just doesn't respond to them.
11144            return (((viewFlags & CLICKABLE) == CLICKABLE
11145                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
11146                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
11147        }
11148        if (mTouchDelegate != null) {
11149            if (mTouchDelegate.onTouchEvent(event)) {
11150                return true;
11151            }
11152        }
11153
11154        if (((viewFlags & CLICKABLE) == CLICKABLE ||
11155                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
11156                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
11157            switch (action) {
11158                case MotionEvent.ACTION_UP:
11159                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
11160                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
11161                        // take focus if we don't have it already and we should in
11162                        // touch mode.
11163                        boolean focusTaken = false;
11164                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
11165                            focusTaken = requestFocus();
11166                        }
11167
11168                        if (prepressed) {
11169                            // The button is being released before we actually
11170                            // showed it as pressed.  Make it show the pressed
11171                            // state now (before scheduling the click) to ensure
11172                            // the user sees it.
11173                            setPressed(true, x, y);
11174                       }
11175
11176                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
11177                            // This is a tap, so remove the longpress check
11178                            removeLongPressCallback();
11179
11180                            // Only perform take click actions if we were in the pressed state
11181                            if (!focusTaken) {
11182                                // Use a Runnable and post this rather than calling
11183                                // performClick directly. This lets other visual state
11184                                // of the view update before click actions start.
11185                                if (mPerformClick == null) {
11186                                    mPerformClick = new PerformClick();
11187                                }
11188                                if (!post(mPerformClick)) {
11189                                    performClick();
11190                                }
11191                            }
11192                        }
11193
11194                        if (mUnsetPressedState == null) {
11195                            mUnsetPressedState = new UnsetPressedState();
11196                        }
11197
11198                        if (prepressed) {
11199                            postDelayed(mUnsetPressedState,
11200                                    ViewConfiguration.getPressedStateDuration());
11201                        } else if (!post(mUnsetPressedState)) {
11202                            // If the post failed, unpress right now
11203                            mUnsetPressedState.run();
11204                        }
11205
11206                        removeTapCallback();
11207                    }
11208                    mIgnoreNextUpEvent = false;
11209                    break;
11210
11211                case MotionEvent.ACTION_DOWN:
11212                    mHasPerformedLongPress = false;
11213
11214                    if (performButtonActionOnTouchDown(event)) {
11215                        break;
11216                    }
11217
11218                    // Walk up the hierarchy to determine if we're inside a scrolling container.
11219                    boolean isInScrollingContainer = isInScrollingContainer();
11220
11221                    // For views inside a scrolling container, delay the pressed feedback for
11222                    // a short period in case this is a scroll.
11223                    if (isInScrollingContainer) {
11224                        mPrivateFlags |= PFLAG_PREPRESSED;
11225                        if (mPendingCheckForTap == null) {
11226                            mPendingCheckForTap = new CheckForTap();
11227                        }
11228                        mPendingCheckForTap.x = event.getX();
11229                        mPendingCheckForTap.y = event.getY();
11230                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
11231                    } else {
11232                        // Not inside a scrolling container, so show the feedback right away
11233                        setPressed(true, x, y);
11234                        checkForLongClick(0, x, y);
11235                    }
11236                    break;
11237
11238                case MotionEvent.ACTION_CANCEL:
11239                    setPressed(false);
11240                    removeTapCallback();
11241                    removeLongPressCallback();
11242                    mInContextButtonPress = false;
11243                    mHasPerformedLongPress = false;
11244                    mIgnoreNextUpEvent = false;
11245                    break;
11246
11247                case MotionEvent.ACTION_MOVE:
11248                    drawableHotspotChanged(x, y);
11249
11250                    // Be lenient about moving outside of buttons
11251                    if (!pointInView(x, y, mTouchSlop)) {
11252                        // Outside button
11253                        removeTapCallback();
11254                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
11255                            // Remove any future long press/tap checks
11256                            removeLongPressCallback();
11257
11258                            setPressed(false);
11259                        }
11260                    }
11261                    break;
11262            }
11263
11264            return true;
11265        }
11266
11267        return false;
11268    }
11269
11270    /**
11271     * @hide
11272     */
11273    public boolean isInScrollingContainer() {
11274        ViewParent p = getParent();
11275        while (p != null && p instanceof ViewGroup) {
11276            if (((ViewGroup) p).shouldDelayChildPressedState()) {
11277                return true;
11278            }
11279            p = p.getParent();
11280        }
11281        return false;
11282    }
11283
11284    /**
11285     * Remove the longpress detection timer.
11286     */
11287    private void removeLongPressCallback() {
11288        if (mPendingCheckForLongPress != null) {
11289          removeCallbacks(mPendingCheckForLongPress);
11290        }
11291    }
11292
11293    /**
11294     * Remove the pending click action
11295     */
11296    private void removePerformClickCallback() {
11297        if (mPerformClick != null) {
11298            removeCallbacks(mPerformClick);
11299        }
11300    }
11301
11302    /**
11303     * Remove the prepress detection timer.
11304     */
11305    private void removeUnsetPressCallback() {
11306        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
11307            setPressed(false);
11308            removeCallbacks(mUnsetPressedState);
11309        }
11310    }
11311
11312    /**
11313     * Remove the tap detection timer.
11314     */
11315    private void removeTapCallback() {
11316        if (mPendingCheckForTap != null) {
11317            mPrivateFlags &= ~PFLAG_PREPRESSED;
11318            removeCallbacks(mPendingCheckForTap);
11319        }
11320    }
11321
11322    /**
11323     * Cancels a pending long press.  Your subclass can use this if you
11324     * want the context menu to come up if the user presses and holds
11325     * at the same place, but you don't want it to come up if they press
11326     * and then move around enough to cause scrolling.
11327     */
11328    public void cancelLongPress() {
11329        removeLongPressCallback();
11330
11331        /*
11332         * The prepressed state handled by the tap callback is a display
11333         * construct, but the tap callback will post a long press callback
11334         * less its own timeout. Remove it here.
11335         */
11336        removeTapCallback();
11337    }
11338
11339    /**
11340     * Remove the pending callback for sending a
11341     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
11342     */
11343    private void removeSendViewScrolledAccessibilityEventCallback() {
11344        if (mSendViewScrolledAccessibilityEvent != null) {
11345            removeCallbacks(mSendViewScrolledAccessibilityEvent);
11346            mSendViewScrolledAccessibilityEvent.mIsPending = false;
11347        }
11348    }
11349
11350    /**
11351     * Sets the TouchDelegate for this View.
11352     */
11353    public void setTouchDelegate(TouchDelegate delegate) {
11354        mTouchDelegate = delegate;
11355    }
11356
11357    /**
11358     * Gets the TouchDelegate for this View.
11359     */
11360    public TouchDelegate getTouchDelegate() {
11361        return mTouchDelegate;
11362    }
11363
11364    /**
11365     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
11366     *
11367     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
11368     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
11369     * available. This method should only be called for touch events.
11370     *
11371     * <p class="note">This api is not intended for most applications. Buffered dispatch
11372     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
11373     * streams will not improve your input latency. Side effects include: increased latency,
11374     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
11375     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
11376     * you.</p>
11377     */
11378    public final void requestUnbufferedDispatch(MotionEvent event) {
11379        final int action = event.getAction();
11380        if (mAttachInfo == null
11381                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
11382                || !event.isTouchEvent()) {
11383            return;
11384        }
11385        mAttachInfo.mUnbufferedDispatchRequested = true;
11386    }
11387
11388    /**
11389     * Set flags controlling behavior of this view.
11390     *
11391     * @param flags Constant indicating the value which should be set
11392     * @param mask Constant indicating the bit range that should be changed
11393     */
11394    void setFlags(int flags, int mask) {
11395        final boolean accessibilityEnabled =
11396                AccessibilityManager.getInstance(mContext).isEnabled();
11397        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
11398
11399        int old = mViewFlags;
11400        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
11401
11402        int changed = mViewFlags ^ old;
11403        if (changed == 0) {
11404            return;
11405        }
11406        int privateFlags = mPrivateFlags;
11407
11408        /* Check if the FOCUSABLE bit has changed */
11409        if (((changed & FOCUSABLE_MASK) != 0) &&
11410                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
11411            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
11412                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
11413                /* Give up focus if we are no longer focusable */
11414                clearFocus();
11415            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
11416                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
11417                /*
11418                 * Tell the view system that we are now available to take focus
11419                 * if no one else already has it.
11420                 */
11421                if (mParent != null) mParent.focusableViewAvailable(this);
11422            }
11423        }
11424
11425        final int newVisibility = flags & VISIBILITY_MASK;
11426        if (newVisibility == VISIBLE) {
11427            if ((changed & VISIBILITY_MASK) != 0) {
11428                /*
11429                 * If this view is becoming visible, invalidate it in case it changed while
11430                 * it was not visible. Marking it drawn ensures that the invalidation will
11431                 * go through.
11432                 */
11433                mPrivateFlags |= PFLAG_DRAWN;
11434                invalidate(true);
11435
11436                needGlobalAttributesUpdate(true);
11437
11438                // a view becoming visible is worth notifying the parent
11439                // about in case nothing has focus.  even if this specific view
11440                // isn't focusable, it may contain something that is, so let
11441                // the root view try to give this focus if nothing else does.
11442                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
11443                    mParent.focusableViewAvailable(this);
11444                }
11445            }
11446        }
11447
11448        /* Check if the GONE bit has changed */
11449        if ((changed & GONE) != 0) {
11450            needGlobalAttributesUpdate(false);
11451            requestLayout();
11452
11453            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
11454                if (hasFocus()) clearFocus();
11455                clearAccessibilityFocus();
11456                destroyDrawingCache();
11457                if (mParent instanceof View) {
11458                    // GONE views noop invalidation, so invalidate the parent
11459                    ((View) mParent).invalidate(true);
11460                }
11461                // Mark the view drawn to ensure that it gets invalidated properly the next
11462                // time it is visible and gets invalidated
11463                mPrivateFlags |= PFLAG_DRAWN;
11464            }
11465            if (mAttachInfo != null) {
11466                mAttachInfo.mViewVisibilityChanged = true;
11467            }
11468        }
11469
11470        /* Check if the VISIBLE bit has changed */
11471        if ((changed & INVISIBLE) != 0) {
11472            needGlobalAttributesUpdate(false);
11473            /*
11474             * If this view is becoming invisible, set the DRAWN flag so that
11475             * the next invalidate() will not be skipped.
11476             */
11477            mPrivateFlags |= PFLAG_DRAWN;
11478
11479            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
11480                // root view becoming invisible shouldn't clear focus and accessibility focus
11481                if (getRootView() != this) {
11482                    if (hasFocus()) clearFocus();
11483                    clearAccessibilityFocus();
11484                }
11485            }
11486            if (mAttachInfo != null) {
11487                mAttachInfo.mViewVisibilityChanged = true;
11488            }
11489        }
11490
11491        if ((changed & VISIBILITY_MASK) != 0) {
11492            // If the view is invisible, cleanup its display list to free up resources
11493            if (newVisibility != VISIBLE && mAttachInfo != null) {
11494                cleanupDraw();
11495            }
11496
11497            if (mParent instanceof ViewGroup) {
11498                ((ViewGroup) mParent).onChildVisibilityChanged(this,
11499                        (changed & VISIBILITY_MASK), newVisibility);
11500                ((View) mParent).invalidate(true);
11501            } else if (mParent != null) {
11502                mParent.invalidateChild(this, null);
11503            }
11504
11505            if (mAttachInfo != null) {
11506                dispatchVisibilityChanged(this, newVisibility);
11507
11508                // Aggregated visibility changes are dispatched to attached views
11509                // in visible windows where the parent is currently shown/drawn
11510                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
11511                // discounting clipping or overlapping. This makes it a good place
11512                // to change animation states.
11513                if (mParent != null && getWindowVisibility() == VISIBLE &&
11514                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
11515                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
11516                }
11517                notifySubtreeAccessibilityStateChangedIfNeeded();
11518            }
11519        }
11520
11521        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
11522            destroyDrawingCache();
11523        }
11524
11525        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
11526            destroyDrawingCache();
11527            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11528            invalidateParentCaches();
11529        }
11530
11531        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
11532            destroyDrawingCache();
11533            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11534        }
11535
11536        if ((changed & DRAW_MASK) != 0) {
11537            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
11538                if (mBackground != null
11539                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
11540                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11541                } else {
11542                    mPrivateFlags |= PFLAG_SKIP_DRAW;
11543                }
11544            } else {
11545                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11546            }
11547            requestLayout();
11548            invalidate(true);
11549        }
11550
11551        if ((changed & KEEP_SCREEN_ON) != 0) {
11552            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
11553                mParent.recomputeViewAttributes(this);
11554            }
11555        }
11556
11557        if (accessibilityEnabled) {
11558            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
11559                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
11560                    || (changed & CONTEXT_CLICKABLE) != 0) {
11561                if (oldIncludeForAccessibility != includeForAccessibility()) {
11562                    notifySubtreeAccessibilityStateChangedIfNeeded();
11563                } else {
11564                    notifyViewAccessibilityStateChangedIfNeeded(
11565                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11566                }
11567            } else if ((changed & ENABLED_MASK) != 0) {
11568                notifyViewAccessibilityStateChangedIfNeeded(
11569                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11570            }
11571        }
11572    }
11573
11574    /**
11575     * Change the view's z order in the tree, so it's on top of other sibling
11576     * views. This ordering change may affect layout, if the parent container
11577     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
11578     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
11579     * method should be followed by calls to {@link #requestLayout()} and
11580     * {@link View#invalidate()} on the view's parent to force the parent to redraw
11581     * with the new child ordering.
11582     *
11583     * @see ViewGroup#bringChildToFront(View)
11584     */
11585    public void bringToFront() {
11586        if (mParent != null) {
11587            mParent.bringChildToFront(this);
11588        }
11589    }
11590
11591    /**
11592     * This is called in response to an internal scroll in this view (i.e., the
11593     * view scrolled its own contents). This is typically as a result of
11594     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
11595     * called.
11596     *
11597     * @param l Current horizontal scroll origin.
11598     * @param t Current vertical scroll origin.
11599     * @param oldl Previous horizontal scroll origin.
11600     * @param oldt Previous vertical scroll origin.
11601     */
11602    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
11603        notifySubtreeAccessibilityStateChangedIfNeeded();
11604
11605        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11606            postSendViewScrolledAccessibilityEventCallback();
11607        }
11608
11609        mBackgroundSizeChanged = true;
11610        if (mForegroundInfo != null) {
11611            mForegroundInfo.mBoundsChanged = true;
11612        }
11613
11614        final AttachInfo ai = mAttachInfo;
11615        if (ai != null) {
11616            ai.mViewScrollChanged = true;
11617        }
11618
11619        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
11620            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
11621        }
11622    }
11623
11624    /**
11625     * Interface definition for a callback to be invoked when the scroll
11626     * X or Y positions of a view change.
11627     * <p>
11628     * <b>Note:</b> Some views handle scrolling independently from View and may
11629     * have their own separate listeners for scroll-type events. For example,
11630     * {@link android.widget.ListView ListView} allows clients to register an
11631     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
11632     * to listen for changes in list scroll position.
11633     *
11634     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
11635     */
11636    public interface OnScrollChangeListener {
11637        /**
11638         * Called when the scroll position of a view changes.
11639         *
11640         * @param v The view whose scroll position has changed.
11641         * @param scrollX Current horizontal scroll origin.
11642         * @param scrollY Current vertical scroll origin.
11643         * @param oldScrollX Previous horizontal scroll origin.
11644         * @param oldScrollY Previous vertical scroll origin.
11645         */
11646        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
11647    }
11648
11649    /**
11650     * Interface definition for a callback to be invoked when the layout bounds of a view
11651     * changes due to layout processing.
11652     */
11653    public interface OnLayoutChangeListener {
11654        /**
11655         * Called when the layout bounds of a view changes due to layout processing.
11656         *
11657         * @param v The view whose bounds have changed.
11658         * @param left The new value of the view's left property.
11659         * @param top The new value of the view's top property.
11660         * @param right The new value of the view's right property.
11661         * @param bottom The new value of the view's bottom property.
11662         * @param oldLeft The previous value of the view's left property.
11663         * @param oldTop The previous value of the view's top property.
11664         * @param oldRight The previous value of the view's right property.
11665         * @param oldBottom The previous value of the view's bottom property.
11666         */
11667        void onLayoutChange(View v, int left, int top, int right, int bottom,
11668            int oldLeft, int oldTop, int oldRight, int oldBottom);
11669    }
11670
11671    /**
11672     * This is called during layout when the size of this view has changed. If
11673     * you were just added to the view hierarchy, you're called with the old
11674     * values of 0.
11675     *
11676     * @param w Current width of this view.
11677     * @param h Current height of this view.
11678     * @param oldw Old width of this view.
11679     * @param oldh Old height of this view.
11680     */
11681    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
11682    }
11683
11684    /**
11685     * Called by draw to draw the child views. This may be overridden
11686     * by derived classes to gain control just before its children are drawn
11687     * (but after its own view has been drawn).
11688     * @param canvas the canvas on which to draw the view
11689     */
11690    protected void dispatchDraw(Canvas canvas) {
11691
11692    }
11693
11694    /**
11695     * Gets the parent of this view. Note that the parent is a
11696     * ViewParent and not necessarily a View.
11697     *
11698     * @return Parent of this view.
11699     */
11700    public final ViewParent getParent() {
11701        return mParent;
11702    }
11703
11704    /**
11705     * Set the horizontal scrolled position of your view. This will cause a call to
11706     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11707     * invalidated.
11708     * @param value the x position to scroll to
11709     */
11710    public void setScrollX(int value) {
11711        scrollTo(value, mScrollY);
11712    }
11713
11714    /**
11715     * Set the vertical scrolled position of your view. This will cause a call to
11716     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11717     * invalidated.
11718     * @param value the y position to scroll to
11719     */
11720    public void setScrollY(int value) {
11721        scrollTo(mScrollX, value);
11722    }
11723
11724    /**
11725     * Return the scrolled left position of this view. This is the left edge of
11726     * the displayed part of your view. You do not need to draw any pixels
11727     * farther left, since those are outside of the frame of your view on
11728     * screen.
11729     *
11730     * @return The left edge of the displayed part of your view, in pixels.
11731     */
11732    public final int getScrollX() {
11733        return mScrollX;
11734    }
11735
11736    /**
11737     * Return the scrolled top position of this view. This is the top edge of
11738     * the displayed part of your view. You do not need to draw any pixels above
11739     * it, since those are outside of the frame of your view on screen.
11740     *
11741     * @return The top edge of the displayed part of your view, in pixels.
11742     */
11743    public final int getScrollY() {
11744        return mScrollY;
11745    }
11746
11747    /**
11748     * Return the width of the your view.
11749     *
11750     * @return The width of your view, in pixels.
11751     */
11752    @ViewDebug.ExportedProperty(category = "layout")
11753    public final int getWidth() {
11754        return mRight - mLeft;
11755    }
11756
11757    /**
11758     * Return the height of your view.
11759     *
11760     * @return The height of your view, in pixels.
11761     */
11762    @ViewDebug.ExportedProperty(category = "layout")
11763    public final int getHeight() {
11764        return mBottom - mTop;
11765    }
11766
11767    /**
11768     * Return the visible drawing bounds of your view. Fills in the output
11769     * rectangle with the values from getScrollX(), getScrollY(),
11770     * getWidth(), and getHeight(). These bounds do not account for any
11771     * transformation properties currently set on the view, such as
11772     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11773     *
11774     * @param outRect The (scrolled) drawing bounds of the view.
11775     */
11776    public void getDrawingRect(Rect outRect) {
11777        outRect.left = mScrollX;
11778        outRect.top = mScrollY;
11779        outRect.right = mScrollX + (mRight - mLeft);
11780        outRect.bottom = mScrollY + (mBottom - mTop);
11781    }
11782
11783    /**
11784     * Like {@link #getMeasuredWidthAndState()}, but only returns the
11785     * raw width component (that is the result is masked by
11786     * {@link #MEASURED_SIZE_MASK}).
11787     *
11788     * @return The raw measured width of this view.
11789     */
11790    public final int getMeasuredWidth() {
11791        return mMeasuredWidth & MEASURED_SIZE_MASK;
11792    }
11793
11794    /**
11795     * Return the full width measurement information for this view as computed
11796     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11797     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11798     * This should be used during measurement and layout calculations only. Use
11799     * {@link #getWidth()} to see how wide a view is after layout.
11800     *
11801     * @return The measured width of this view as a bit mask.
11802     */
11803    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11804            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11805                    name = "MEASURED_STATE_TOO_SMALL"),
11806    })
11807    public final int getMeasuredWidthAndState() {
11808        return mMeasuredWidth;
11809    }
11810
11811    /**
11812     * Like {@link #getMeasuredHeightAndState()}, but only returns the
11813     * raw width component (that is the result is masked by
11814     * {@link #MEASURED_SIZE_MASK}).
11815     *
11816     * @return The raw measured height of this view.
11817     */
11818    public final int getMeasuredHeight() {
11819        return mMeasuredHeight & MEASURED_SIZE_MASK;
11820    }
11821
11822    /**
11823     * Return the full height measurement information for this view as computed
11824     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11825     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11826     * This should be used during measurement and layout calculations only. Use
11827     * {@link #getHeight()} to see how wide a view is after layout.
11828     *
11829     * @return The measured width of this view as a bit mask.
11830     */
11831    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11832            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11833                    name = "MEASURED_STATE_TOO_SMALL"),
11834    })
11835    public final int getMeasuredHeightAndState() {
11836        return mMeasuredHeight;
11837    }
11838
11839    /**
11840     * Return only the state bits of {@link #getMeasuredWidthAndState()}
11841     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11842     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11843     * and the height component is at the shifted bits
11844     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11845     */
11846    public final int getMeasuredState() {
11847        return (mMeasuredWidth&MEASURED_STATE_MASK)
11848                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11849                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11850    }
11851
11852    /**
11853     * The transform matrix of this view, which is calculated based on the current
11854     * rotation, scale, and pivot properties.
11855     *
11856     * @see #getRotation()
11857     * @see #getScaleX()
11858     * @see #getScaleY()
11859     * @see #getPivotX()
11860     * @see #getPivotY()
11861     * @return The current transform matrix for the view
11862     */
11863    public Matrix getMatrix() {
11864        ensureTransformationInfo();
11865        final Matrix matrix = mTransformationInfo.mMatrix;
11866        mRenderNode.getMatrix(matrix);
11867        return matrix;
11868    }
11869
11870    /**
11871     * Returns true if the transform matrix is the identity matrix.
11872     * Recomputes the matrix if necessary.
11873     *
11874     * @return True if the transform matrix is the identity matrix, false otherwise.
11875     */
11876    final boolean hasIdentityMatrix() {
11877        return mRenderNode.hasIdentityMatrix();
11878    }
11879
11880    void ensureTransformationInfo() {
11881        if (mTransformationInfo == null) {
11882            mTransformationInfo = new TransformationInfo();
11883        }
11884    }
11885
11886    /**
11887     * Utility method to retrieve the inverse of the current mMatrix property.
11888     * We cache the matrix to avoid recalculating it when transform properties
11889     * have not changed.
11890     *
11891     * @return The inverse of the current matrix of this view.
11892     * @hide
11893     */
11894    public final Matrix getInverseMatrix() {
11895        ensureTransformationInfo();
11896        if (mTransformationInfo.mInverseMatrix == null) {
11897            mTransformationInfo.mInverseMatrix = new Matrix();
11898        }
11899        final Matrix matrix = mTransformationInfo.mInverseMatrix;
11900        mRenderNode.getInverseMatrix(matrix);
11901        return matrix;
11902    }
11903
11904    /**
11905     * Gets the distance along the Z axis from the camera to this view.
11906     *
11907     * @see #setCameraDistance(float)
11908     *
11909     * @return The distance along the Z axis.
11910     */
11911    public float getCameraDistance() {
11912        final float dpi = mResources.getDisplayMetrics().densityDpi;
11913        return -(mRenderNode.getCameraDistance() * dpi);
11914    }
11915
11916    /**
11917     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11918     * views are drawn) from the camera to this view. The camera's distance
11919     * affects 3D transformations, for instance rotations around the X and Y
11920     * axis. If the rotationX or rotationY properties are changed and this view is
11921     * large (more than half the size of the screen), it is recommended to always
11922     * use a camera distance that's greater than the height (X axis rotation) or
11923     * the width (Y axis rotation) of this view.</p>
11924     *
11925     * <p>The distance of the camera from the view plane can have an affect on the
11926     * perspective distortion of the view when it is rotated around the x or y axis.
11927     * For example, a large distance will result in a large viewing angle, and there
11928     * will not be much perspective distortion of the view as it rotates. A short
11929     * distance may cause much more perspective distortion upon rotation, and can
11930     * also result in some drawing artifacts if the rotated view ends up partially
11931     * behind the camera (which is why the recommendation is to use a distance at
11932     * least as far as the size of the view, if the view is to be rotated.)</p>
11933     *
11934     * <p>The distance is expressed in "depth pixels." The default distance depends
11935     * on the screen density. For instance, on a medium density display, the
11936     * default distance is 1280. On a high density display, the default distance
11937     * is 1920.</p>
11938     *
11939     * <p>If you want to specify a distance that leads to visually consistent
11940     * results across various densities, use the following formula:</p>
11941     * <pre>
11942     * float scale = context.getResources().getDisplayMetrics().density;
11943     * view.setCameraDistance(distance * scale);
11944     * </pre>
11945     *
11946     * <p>The density scale factor of a high density display is 1.5,
11947     * and 1920 = 1280 * 1.5.</p>
11948     *
11949     * @param distance The distance in "depth pixels", if negative the opposite
11950     *        value is used
11951     *
11952     * @see #setRotationX(float)
11953     * @see #setRotationY(float)
11954     */
11955    public void setCameraDistance(float distance) {
11956        final float dpi = mResources.getDisplayMetrics().densityDpi;
11957
11958        invalidateViewProperty(true, false);
11959        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11960        invalidateViewProperty(false, false);
11961
11962        invalidateParentIfNeededAndWasQuickRejected();
11963    }
11964
11965    /**
11966     * The degrees that the view is rotated around the pivot point.
11967     *
11968     * @see #setRotation(float)
11969     * @see #getPivotX()
11970     * @see #getPivotY()
11971     *
11972     * @return The degrees of rotation.
11973     */
11974    @ViewDebug.ExportedProperty(category = "drawing")
11975    public float getRotation() {
11976        return mRenderNode.getRotation();
11977    }
11978
11979    /**
11980     * Sets the degrees that the view is rotated around the pivot point. Increasing values
11981     * result in clockwise rotation.
11982     *
11983     * @param rotation The degrees of rotation.
11984     *
11985     * @see #getRotation()
11986     * @see #getPivotX()
11987     * @see #getPivotY()
11988     * @see #setRotationX(float)
11989     * @see #setRotationY(float)
11990     *
11991     * @attr ref android.R.styleable#View_rotation
11992     */
11993    public void setRotation(float rotation) {
11994        if (rotation != getRotation()) {
11995            // Double-invalidation is necessary to capture view's old and new areas
11996            invalidateViewProperty(true, false);
11997            mRenderNode.setRotation(rotation);
11998            invalidateViewProperty(false, true);
11999
12000            invalidateParentIfNeededAndWasQuickRejected();
12001            notifySubtreeAccessibilityStateChangedIfNeeded();
12002        }
12003    }
12004
12005    /**
12006     * The degrees that the view is rotated around the vertical axis through the pivot point.
12007     *
12008     * @see #getPivotX()
12009     * @see #getPivotY()
12010     * @see #setRotationY(float)
12011     *
12012     * @return The degrees of Y rotation.
12013     */
12014    @ViewDebug.ExportedProperty(category = "drawing")
12015    public float getRotationY() {
12016        return mRenderNode.getRotationY();
12017    }
12018
12019    /**
12020     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
12021     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
12022     * down the y axis.
12023     *
12024     * When rotating large views, it is recommended to adjust the camera distance
12025     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12026     *
12027     * @param rotationY The degrees of Y rotation.
12028     *
12029     * @see #getRotationY()
12030     * @see #getPivotX()
12031     * @see #getPivotY()
12032     * @see #setRotation(float)
12033     * @see #setRotationX(float)
12034     * @see #setCameraDistance(float)
12035     *
12036     * @attr ref android.R.styleable#View_rotationY
12037     */
12038    public void setRotationY(float rotationY) {
12039        if (rotationY != getRotationY()) {
12040            invalidateViewProperty(true, false);
12041            mRenderNode.setRotationY(rotationY);
12042            invalidateViewProperty(false, true);
12043
12044            invalidateParentIfNeededAndWasQuickRejected();
12045            notifySubtreeAccessibilityStateChangedIfNeeded();
12046        }
12047    }
12048
12049    /**
12050     * The degrees that the view is rotated around the horizontal axis through the pivot point.
12051     *
12052     * @see #getPivotX()
12053     * @see #getPivotY()
12054     * @see #setRotationX(float)
12055     *
12056     * @return The degrees of X rotation.
12057     */
12058    @ViewDebug.ExportedProperty(category = "drawing")
12059    public float getRotationX() {
12060        return mRenderNode.getRotationX();
12061    }
12062
12063    /**
12064     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
12065     * Increasing values result in clockwise rotation from the viewpoint of looking down the
12066     * x axis.
12067     *
12068     * When rotating large views, it is recommended to adjust the camera distance
12069     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12070     *
12071     * @param rotationX The degrees of X rotation.
12072     *
12073     * @see #getRotationX()
12074     * @see #getPivotX()
12075     * @see #getPivotY()
12076     * @see #setRotation(float)
12077     * @see #setRotationY(float)
12078     * @see #setCameraDistance(float)
12079     *
12080     * @attr ref android.R.styleable#View_rotationX
12081     */
12082    public void setRotationX(float rotationX) {
12083        if (rotationX != getRotationX()) {
12084            invalidateViewProperty(true, false);
12085            mRenderNode.setRotationX(rotationX);
12086            invalidateViewProperty(false, true);
12087
12088            invalidateParentIfNeededAndWasQuickRejected();
12089            notifySubtreeAccessibilityStateChangedIfNeeded();
12090        }
12091    }
12092
12093    /**
12094     * The amount that the view is scaled in x around the pivot point, as a proportion of
12095     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
12096     *
12097     * <p>By default, this is 1.0f.
12098     *
12099     * @see #getPivotX()
12100     * @see #getPivotY()
12101     * @return The scaling factor.
12102     */
12103    @ViewDebug.ExportedProperty(category = "drawing")
12104    public float getScaleX() {
12105        return mRenderNode.getScaleX();
12106    }
12107
12108    /**
12109     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
12110     * the view's unscaled width. A value of 1 means that no scaling is applied.
12111     *
12112     * @param scaleX The scaling factor.
12113     * @see #getPivotX()
12114     * @see #getPivotY()
12115     *
12116     * @attr ref android.R.styleable#View_scaleX
12117     */
12118    public void setScaleX(float scaleX) {
12119        if (scaleX != getScaleX()) {
12120            invalidateViewProperty(true, false);
12121            mRenderNode.setScaleX(scaleX);
12122            invalidateViewProperty(false, true);
12123
12124            invalidateParentIfNeededAndWasQuickRejected();
12125            notifySubtreeAccessibilityStateChangedIfNeeded();
12126        }
12127    }
12128
12129    /**
12130     * The amount that the view is scaled in y around the pivot point, as a proportion of
12131     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
12132     *
12133     * <p>By default, this is 1.0f.
12134     *
12135     * @see #getPivotX()
12136     * @see #getPivotY()
12137     * @return The scaling factor.
12138     */
12139    @ViewDebug.ExportedProperty(category = "drawing")
12140    public float getScaleY() {
12141        return mRenderNode.getScaleY();
12142    }
12143
12144    /**
12145     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
12146     * the view's unscaled width. A value of 1 means that no scaling is applied.
12147     *
12148     * @param scaleY The scaling factor.
12149     * @see #getPivotX()
12150     * @see #getPivotY()
12151     *
12152     * @attr ref android.R.styleable#View_scaleY
12153     */
12154    public void setScaleY(float scaleY) {
12155        if (scaleY != getScaleY()) {
12156            invalidateViewProperty(true, false);
12157            mRenderNode.setScaleY(scaleY);
12158            invalidateViewProperty(false, true);
12159
12160            invalidateParentIfNeededAndWasQuickRejected();
12161            notifySubtreeAccessibilityStateChangedIfNeeded();
12162        }
12163    }
12164
12165    /**
12166     * The x location of the point around which the view is {@link #setRotation(float) rotated}
12167     * and {@link #setScaleX(float) scaled}.
12168     *
12169     * @see #getRotation()
12170     * @see #getScaleX()
12171     * @see #getScaleY()
12172     * @see #getPivotY()
12173     * @return The x location of the pivot point.
12174     *
12175     * @attr ref android.R.styleable#View_transformPivotX
12176     */
12177    @ViewDebug.ExportedProperty(category = "drawing")
12178    public float getPivotX() {
12179        return mRenderNode.getPivotX();
12180    }
12181
12182    /**
12183     * Sets the x location of the point around which the view is
12184     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
12185     * By default, the pivot point is centered on the object.
12186     * Setting this property disables this behavior and causes the view to use only the
12187     * explicitly set pivotX and pivotY values.
12188     *
12189     * @param pivotX The x location of the pivot point.
12190     * @see #getRotation()
12191     * @see #getScaleX()
12192     * @see #getScaleY()
12193     * @see #getPivotY()
12194     *
12195     * @attr ref android.R.styleable#View_transformPivotX
12196     */
12197    public void setPivotX(float pivotX) {
12198        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
12199            invalidateViewProperty(true, false);
12200            mRenderNode.setPivotX(pivotX);
12201            invalidateViewProperty(false, true);
12202
12203            invalidateParentIfNeededAndWasQuickRejected();
12204        }
12205    }
12206
12207    /**
12208     * The y location of the point around which the view is {@link #setRotation(float) rotated}
12209     * and {@link #setScaleY(float) scaled}.
12210     *
12211     * @see #getRotation()
12212     * @see #getScaleX()
12213     * @see #getScaleY()
12214     * @see #getPivotY()
12215     * @return The y location of the pivot point.
12216     *
12217     * @attr ref android.R.styleable#View_transformPivotY
12218     */
12219    @ViewDebug.ExportedProperty(category = "drawing")
12220    public float getPivotY() {
12221        return mRenderNode.getPivotY();
12222    }
12223
12224    /**
12225     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
12226     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
12227     * Setting this property disables this behavior and causes the view to use only the
12228     * explicitly set pivotX and pivotY values.
12229     *
12230     * @param pivotY The y location of the pivot point.
12231     * @see #getRotation()
12232     * @see #getScaleX()
12233     * @see #getScaleY()
12234     * @see #getPivotY()
12235     *
12236     * @attr ref android.R.styleable#View_transformPivotY
12237     */
12238    public void setPivotY(float pivotY) {
12239        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
12240            invalidateViewProperty(true, false);
12241            mRenderNode.setPivotY(pivotY);
12242            invalidateViewProperty(false, true);
12243
12244            invalidateParentIfNeededAndWasQuickRejected();
12245        }
12246    }
12247
12248    /**
12249     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
12250     * completely transparent and 1 means the view is completely opaque.
12251     *
12252     * <p>By default this is 1.0f.
12253     * @return The opacity of the view.
12254     */
12255    @ViewDebug.ExportedProperty(category = "drawing")
12256    public float getAlpha() {
12257        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
12258    }
12259
12260    /**
12261     * Sets the behavior for overlapping rendering for this view (see {@link
12262     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
12263     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
12264     * providing the value which is then used internally. That is, when {@link
12265     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
12266     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
12267     * instead.
12268     *
12269     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
12270     * instead of that returned by {@link #hasOverlappingRendering()}.
12271     *
12272     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
12273     */
12274    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
12275        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
12276        if (hasOverlappingRendering) {
12277            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12278        } else {
12279            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12280        }
12281    }
12282
12283    /**
12284     * Returns the value for overlapping rendering that is used internally. This is either
12285     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
12286     * the return value of {@link #hasOverlappingRendering()}, otherwise.
12287     *
12288     * @return The value for overlapping rendering being used internally.
12289     */
12290    public final boolean getHasOverlappingRendering() {
12291        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
12292                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
12293                hasOverlappingRendering();
12294    }
12295
12296    /**
12297     * Returns whether this View has content which overlaps.
12298     *
12299     * <p>This function, intended to be overridden by specific View types, is an optimization when
12300     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
12301     * an offscreen buffer and then composited into place, which can be expensive. If the view has
12302     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
12303     * directly. An example of overlapping rendering is a TextView with a background image, such as
12304     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
12305     * ImageView with only the foreground image. The default implementation returns true; subclasses
12306     * should override if they have cases which can be optimized.</p>
12307     *
12308     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
12309     * necessitates that a View return true if it uses the methods internally without passing the
12310     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
12311     *
12312     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
12313     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
12314     *
12315     * @return true if the content in this view might overlap, false otherwise.
12316     */
12317    @ViewDebug.ExportedProperty(category = "drawing")
12318    public boolean hasOverlappingRendering() {
12319        return true;
12320    }
12321
12322    /**
12323     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
12324     * completely transparent and 1 means the view is completely opaque.
12325     *
12326     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
12327     * can have significant performance implications, especially for large views. It is best to use
12328     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
12329     *
12330     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
12331     * strongly recommended for performance reasons to either override
12332     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
12333     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
12334     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
12335     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
12336     * of rendering cost, even for simple or small views. Starting with
12337     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
12338     * applied to the view at the rendering level.</p>
12339     *
12340     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
12341     * responsible for applying the opacity itself.</p>
12342     *
12343     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
12344     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
12345     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
12346     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
12347     *
12348     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
12349     * value will clip a View to its bounds, unless the View returns <code>false</code> from
12350     * {@link #hasOverlappingRendering}.</p>
12351     *
12352     * @param alpha The opacity of the view.
12353     *
12354     * @see #hasOverlappingRendering()
12355     * @see #setLayerType(int, android.graphics.Paint)
12356     *
12357     * @attr ref android.R.styleable#View_alpha
12358     */
12359    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
12360        ensureTransformationInfo();
12361        if (mTransformationInfo.mAlpha != alpha) {
12362            mTransformationInfo.mAlpha = alpha;
12363            if (onSetAlpha((int) (alpha * 255))) {
12364                mPrivateFlags |= PFLAG_ALPHA_SET;
12365                // subclass is handling alpha - don't optimize rendering cache invalidation
12366                invalidateParentCaches();
12367                invalidate(true);
12368            } else {
12369                mPrivateFlags &= ~PFLAG_ALPHA_SET;
12370                invalidateViewProperty(true, false);
12371                mRenderNode.setAlpha(getFinalAlpha());
12372                notifyViewAccessibilityStateChangedIfNeeded(
12373                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12374            }
12375        }
12376    }
12377
12378    /**
12379     * Faster version of setAlpha() which performs the same steps except there are
12380     * no calls to invalidate(). The caller of this function should perform proper invalidation
12381     * on the parent and this object. The return value indicates whether the subclass handles
12382     * alpha (the return value for onSetAlpha()).
12383     *
12384     * @param alpha The new value for the alpha property
12385     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
12386     *         the new value for the alpha property is different from the old value
12387     */
12388    boolean setAlphaNoInvalidation(float alpha) {
12389        ensureTransformationInfo();
12390        if (mTransformationInfo.mAlpha != alpha) {
12391            mTransformationInfo.mAlpha = alpha;
12392            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
12393            if (subclassHandlesAlpha) {
12394                mPrivateFlags |= PFLAG_ALPHA_SET;
12395                return true;
12396            } else {
12397                mPrivateFlags &= ~PFLAG_ALPHA_SET;
12398                mRenderNode.setAlpha(getFinalAlpha());
12399            }
12400        }
12401        return false;
12402    }
12403
12404    /**
12405     * This property is hidden and intended only for use by the Fade transition, which
12406     * animates it to produce a visual translucency that does not side-effect (or get
12407     * affected by) the real alpha property. This value is composited with the other
12408     * alpha value (and the AlphaAnimation value, when that is present) to produce
12409     * a final visual translucency result, which is what is passed into the DisplayList.
12410     *
12411     * @hide
12412     */
12413    public void setTransitionAlpha(float alpha) {
12414        ensureTransformationInfo();
12415        if (mTransformationInfo.mTransitionAlpha != alpha) {
12416            mTransformationInfo.mTransitionAlpha = alpha;
12417            mPrivateFlags &= ~PFLAG_ALPHA_SET;
12418            invalidateViewProperty(true, false);
12419            mRenderNode.setAlpha(getFinalAlpha());
12420        }
12421    }
12422
12423    /**
12424     * Calculates the visual alpha of this view, which is a combination of the actual
12425     * alpha value and the transitionAlpha value (if set).
12426     */
12427    private float getFinalAlpha() {
12428        if (mTransformationInfo != null) {
12429            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
12430        }
12431        return 1;
12432    }
12433
12434    /**
12435     * This property is hidden and intended only for use by the Fade transition, which
12436     * animates it to produce a visual translucency that does not side-effect (or get
12437     * affected by) the real alpha property. This value is composited with the other
12438     * alpha value (and the AlphaAnimation value, when that is present) to produce
12439     * a final visual translucency result, which is what is passed into the DisplayList.
12440     *
12441     * @hide
12442     */
12443    @ViewDebug.ExportedProperty(category = "drawing")
12444    public float getTransitionAlpha() {
12445        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
12446    }
12447
12448    /**
12449     * Top position of this view relative to its parent.
12450     *
12451     * @return The top of this view, in pixels.
12452     */
12453    @ViewDebug.CapturedViewProperty
12454    public final int getTop() {
12455        return mTop;
12456    }
12457
12458    /**
12459     * Sets the top position of this view relative to its parent. This method is meant to be called
12460     * by the layout system and should not generally be called otherwise, because the property
12461     * may be changed at any time by the layout.
12462     *
12463     * @param top The top of this view, in pixels.
12464     */
12465    public final void setTop(int top) {
12466        if (top != mTop) {
12467            final boolean matrixIsIdentity = hasIdentityMatrix();
12468            if (matrixIsIdentity) {
12469                if (mAttachInfo != null) {
12470                    int minTop;
12471                    int yLoc;
12472                    if (top < mTop) {
12473                        minTop = top;
12474                        yLoc = top - mTop;
12475                    } else {
12476                        minTop = mTop;
12477                        yLoc = 0;
12478                    }
12479                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
12480                }
12481            } else {
12482                // Double-invalidation is necessary to capture view's old and new areas
12483                invalidate(true);
12484            }
12485
12486            int width = mRight - mLeft;
12487            int oldHeight = mBottom - mTop;
12488
12489            mTop = top;
12490            mRenderNode.setTop(mTop);
12491
12492            sizeChange(width, mBottom - mTop, width, oldHeight);
12493
12494            if (!matrixIsIdentity) {
12495                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12496                invalidate(true);
12497            }
12498            mBackgroundSizeChanged = true;
12499            if (mForegroundInfo != null) {
12500                mForegroundInfo.mBoundsChanged = true;
12501            }
12502            invalidateParentIfNeeded();
12503            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12504                // View was rejected last time it was drawn by its parent; this may have changed
12505                invalidateParentIfNeeded();
12506            }
12507        }
12508    }
12509
12510    /**
12511     * Bottom position of this view relative to its parent.
12512     *
12513     * @return The bottom of this view, in pixels.
12514     */
12515    @ViewDebug.CapturedViewProperty
12516    public final int getBottom() {
12517        return mBottom;
12518    }
12519
12520    /**
12521     * True if this view has changed since the last time being drawn.
12522     *
12523     * @return The dirty state of this view.
12524     */
12525    public boolean isDirty() {
12526        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
12527    }
12528
12529    /**
12530     * Sets the bottom position of this view relative to its parent. This method is meant to be
12531     * called by the layout system and should not generally be called otherwise, because the
12532     * property may be changed at any time by the layout.
12533     *
12534     * @param bottom The bottom of this view, in pixels.
12535     */
12536    public final void setBottom(int bottom) {
12537        if (bottom != mBottom) {
12538            final boolean matrixIsIdentity = hasIdentityMatrix();
12539            if (matrixIsIdentity) {
12540                if (mAttachInfo != null) {
12541                    int maxBottom;
12542                    if (bottom < mBottom) {
12543                        maxBottom = mBottom;
12544                    } else {
12545                        maxBottom = bottom;
12546                    }
12547                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
12548                }
12549            } else {
12550                // Double-invalidation is necessary to capture view's old and new areas
12551                invalidate(true);
12552            }
12553
12554            int width = mRight - mLeft;
12555            int oldHeight = mBottom - mTop;
12556
12557            mBottom = bottom;
12558            mRenderNode.setBottom(mBottom);
12559
12560            sizeChange(width, mBottom - mTop, width, oldHeight);
12561
12562            if (!matrixIsIdentity) {
12563                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12564                invalidate(true);
12565            }
12566            mBackgroundSizeChanged = true;
12567            if (mForegroundInfo != null) {
12568                mForegroundInfo.mBoundsChanged = true;
12569            }
12570            invalidateParentIfNeeded();
12571            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12572                // View was rejected last time it was drawn by its parent; this may have changed
12573                invalidateParentIfNeeded();
12574            }
12575        }
12576    }
12577
12578    /**
12579     * Left position of this view relative to its parent.
12580     *
12581     * @return The left edge of this view, in pixels.
12582     */
12583    @ViewDebug.CapturedViewProperty
12584    public final int getLeft() {
12585        return mLeft;
12586    }
12587
12588    /**
12589     * Sets the left position of this view relative to its parent. This method is meant to be called
12590     * by the layout system and should not generally be called otherwise, because the property
12591     * may be changed at any time by the layout.
12592     *
12593     * @param left The left of this view, in pixels.
12594     */
12595    public final void setLeft(int left) {
12596        if (left != mLeft) {
12597            final boolean matrixIsIdentity = hasIdentityMatrix();
12598            if (matrixIsIdentity) {
12599                if (mAttachInfo != null) {
12600                    int minLeft;
12601                    int xLoc;
12602                    if (left < mLeft) {
12603                        minLeft = left;
12604                        xLoc = left - mLeft;
12605                    } else {
12606                        minLeft = mLeft;
12607                        xLoc = 0;
12608                    }
12609                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
12610                }
12611            } else {
12612                // Double-invalidation is necessary to capture view's old and new areas
12613                invalidate(true);
12614            }
12615
12616            int oldWidth = mRight - mLeft;
12617            int height = mBottom - mTop;
12618
12619            mLeft = left;
12620            mRenderNode.setLeft(left);
12621
12622            sizeChange(mRight - mLeft, height, oldWidth, height);
12623
12624            if (!matrixIsIdentity) {
12625                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12626                invalidate(true);
12627            }
12628            mBackgroundSizeChanged = true;
12629            if (mForegroundInfo != null) {
12630                mForegroundInfo.mBoundsChanged = true;
12631            }
12632            invalidateParentIfNeeded();
12633            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12634                // View was rejected last time it was drawn by its parent; this may have changed
12635                invalidateParentIfNeeded();
12636            }
12637        }
12638    }
12639
12640    /**
12641     * Right position of this view relative to its parent.
12642     *
12643     * @return The right edge of this view, in pixels.
12644     */
12645    @ViewDebug.CapturedViewProperty
12646    public final int getRight() {
12647        return mRight;
12648    }
12649
12650    /**
12651     * Sets the right position of this view relative to its parent. This method is meant to be called
12652     * by the layout system and should not generally be called otherwise, because the property
12653     * may be changed at any time by the layout.
12654     *
12655     * @param right The right of this view, in pixels.
12656     */
12657    public final void setRight(int right) {
12658        if (right != mRight) {
12659            final boolean matrixIsIdentity = hasIdentityMatrix();
12660            if (matrixIsIdentity) {
12661                if (mAttachInfo != null) {
12662                    int maxRight;
12663                    if (right < mRight) {
12664                        maxRight = mRight;
12665                    } else {
12666                        maxRight = right;
12667                    }
12668                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
12669                }
12670            } else {
12671                // Double-invalidation is necessary to capture view's old and new areas
12672                invalidate(true);
12673            }
12674
12675            int oldWidth = mRight - mLeft;
12676            int height = mBottom - mTop;
12677
12678            mRight = right;
12679            mRenderNode.setRight(mRight);
12680
12681            sizeChange(mRight - mLeft, height, oldWidth, height);
12682
12683            if (!matrixIsIdentity) {
12684                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12685                invalidate(true);
12686            }
12687            mBackgroundSizeChanged = true;
12688            if (mForegroundInfo != null) {
12689                mForegroundInfo.mBoundsChanged = true;
12690            }
12691            invalidateParentIfNeeded();
12692            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12693                // View was rejected last time it was drawn by its parent; this may have changed
12694                invalidateParentIfNeeded();
12695            }
12696        }
12697    }
12698
12699    /**
12700     * The visual x position of this view, in pixels. This is equivalent to the
12701     * {@link #setTranslationX(float) translationX} property plus the current
12702     * {@link #getLeft() left} property.
12703     *
12704     * @return The visual x position of this view, in pixels.
12705     */
12706    @ViewDebug.ExportedProperty(category = "drawing")
12707    public float getX() {
12708        return mLeft + getTranslationX();
12709    }
12710
12711    /**
12712     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
12713     * {@link #setTranslationX(float) translationX} property to be the difference between
12714     * the x value passed in and the current {@link #getLeft() left} property.
12715     *
12716     * @param x The visual x position of this view, in pixels.
12717     */
12718    public void setX(float x) {
12719        setTranslationX(x - mLeft);
12720    }
12721
12722    /**
12723     * The visual y position of this view, in pixels. This is equivalent to the
12724     * {@link #setTranslationY(float) translationY} property plus the current
12725     * {@link #getTop() top} property.
12726     *
12727     * @return The visual y position of this view, in pixels.
12728     */
12729    @ViewDebug.ExportedProperty(category = "drawing")
12730    public float getY() {
12731        return mTop + getTranslationY();
12732    }
12733
12734    /**
12735     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
12736     * {@link #setTranslationY(float) translationY} property to be the difference between
12737     * the y value passed in and the current {@link #getTop() top} property.
12738     *
12739     * @param y The visual y position of this view, in pixels.
12740     */
12741    public void setY(float y) {
12742        setTranslationY(y - mTop);
12743    }
12744
12745    /**
12746     * The visual z position of this view, in pixels. This is equivalent to the
12747     * {@link #setTranslationZ(float) translationZ} property plus the current
12748     * {@link #getElevation() elevation} property.
12749     *
12750     * @return The visual z position of this view, in pixels.
12751     */
12752    @ViewDebug.ExportedProperty(category = "drawing")
12753    public float getZ() {
12754        return getElevation() + getTranslationZ();
12755    }
12756
12757    /**
12758     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
12759     * {@link #setTranslationZ(float) translationZ} property to be the difference between
12760     * the x value passed in and the current {@link #getElevation() elevation} property.
12761     *
12762     * @param z The visual z position of this view, in pixels.
12763     */
12764    public void setZ(float z) {
12765        setTranslationZ(z - getElevation());
12766    }
12767
12768    /**
12769     * The base elevation of this view relative to its parent, in pixels.
12770     *
12771     * @return The base depth position of the view, in pixels.
12772     */
12773    @ViewDebug.ExportedProperty(category = "drawing")
12774    public float getElevation() {
12775        return mRenderNode.getElevation();
12776    }
12777
12778    /**
12779     * Sets the base elevation of this view, in pixels.
12780     *
12781     * @attr ref android.R.styleable#View_elevation
12782     */
12783    public void setElevation(float elevation) {
12784        if (elevation != getElevation()) {
12785            invalidateViewProperty(true, false);
12786            mRenderNode.setElevation(elevation);
12787            invalidateViewProperty(false, true);
12788
12789            invalidateParentIfNeededAndWasQuickRejected();
12790        }
12791    }
12792
12793    /**
12794     * The horizontal location of this view relative to its {@link #getLeft() left} position.
12795     * This position is post-layout, in addition to wherever the object's
12796     * layout placed it.
12797     *
12798     * @return The horizontal position of this view relative to its left position, in pixels.
12799     */
12800    @ViewDebug.ExportedProperty(category = "drawing")
12801    public float getTranslationX() {
12802        return mRenderNode.getTranslationX();
12803    }
12804
12805    /**
12806     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12807     * This effectively positions the object post-layout, in addition to wherever the object's
12808     * layout placed it.
12809     *
12810     * @param translationX The horizontal position of this view relative to its left position,
12811     * in pixels.
12812     *
12813     * @attr ref android.R.styleable#View_translationX
12814     */
12815    public void setTranslationX(float translationX) {
12816        if (translationX != getTranslationX()) {
12817            invalidateViewProperty(true, false);
12818            mRenderNode.setTranslationX(translationX);
12819            invalidateViewProperty(false, true);
12820
12821            invalidateParentIfNeededAndWasQuickRejected();
12822            notifySubtreeAccessibilityStateChangedIfNeeded();
12823        }
12824    }
12825
12826    /**
12827     * The vertical location of this view relative to its {@link #getTop() top} position.
12828     * This position is post-layout, in addition to wherever the object's
12829     * layout placed it.
12830     *
12831     * @return The vertical position of this view relative to its top position,
12832     * in pixels.
12833     */
12834    @ViewDebug.ExportedProperty(category = "drawing")
12835    public float getTranslationY() {
12836        return mRenderNode.getTranslationY();
12837    }
12838
12839    /**
12840     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12841     * This effectively positions the object post-layout, in addition to wherever the object's
12842     * layout placed it.
12843     *
12844     * @param translationY The vertical position of this view relative to its top position,
12845     * in pixels.
12846     *
12847     * @attr ref android.R.styleable#View_translationY
12848     */
12849    public void setTranslationY(float translationY) {
12850        if (translationY != getTranslationY()) {
12851            invalidateViewProperty(true, false);
12852            mRenderNode.setTranslationY(translationY);
12853            invalidateViewProperty(false, true);
12854
12855            invalidateParentIfNeededAndWasQuickRejected();
12856            notifySubtreeAccessibilityStateChangedIfNeeded();
12857        }
12858    }
12859
12860    /**
12861     * The depth location of this view relative to its {@link #getElevation() elevation}.
12862     *
12863     * @return The depth of this view relative to its elevation.
12864     */
12865    @ViewDebug.ExportedProperty(category = "drawing")
12866    public float getTranslationZ() {
12867        return mRenderNode.getTranslationZ();
12868    }
12869
12870    /**
12871     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12872     *
12873     * @attr ref android.R.styleable#View_translationZ
12874     */
12875    public void setTranslationZ(float translationZ) {
12876        if (translationZ != getTranslationZ()) {
12877            invalidateViewProperty(true, false);
12878            mRenderNode.setTranslationZ(translationZ);
12879            invalidateViewProperty(false, true);
12880
12881            invalidateParentIfNeededAndWasQuickRejected();
12882        }
12883    }
12884
12885    /** @hide */
12886    public void setAnimationMatrix(Matrix matrix) {
12887        invalidateViewProperty(true, false);
12888        mRenderNode.setAnimationMatrix(matrix);
12889        invalidateViewProperty(false, true);
12890
12891        invalidateParentIfNeededAndWasQuickRejected();
12892    }
12893
12894    /**
12895     * Returns the current StateListAnimator if exists.
12896     *
12897     * @return StateListAnimator or null if it does not exists
12898     * @see    #setStateListAnimator(android.animation.StateListAnimator)
12899     */
12900    public StateListAnimator getStateListAnimator() {
12901        return mStateListAnimator;
12902    }
12903
12904    /**
12905     * Attaches the provided StateListAnimator to this View.
12906     * <p>
12907     * Any previously attached StateListAnimator will be detached.
12908     *
12909     * @param stateListAnimator The StateListAnimator to update the view
12910     * @see {@link android.animation.StateListAnimator}
12911     */
12912    public void setStateListAnimator(StateListAnimator stateListAnimator) {
12913        if (mStateListAnimator == stateListAnimator) {
12914            return;
12915        }
12916        if (mStateListAnimator != null) {
12917            mStateListAnimator.setTarget(null);
12918        }
12919        mStateListAnimator = stateListAnimator;
12920        if (stateListAnimator != null) {
12921            stateListAnimator.setTarget(this);
12922            if (isAttachedToWindow()) {
12923                stateListAnimator.setState(getDrawableState());
12924            }
12925        }
12926    }
12927
12928    /**
12929     * Returns whether the Outline should be used to clip the contents of the View.
12930     * <p>
12931     * Note that this flag will only be respected if the View's Outline returns true from
12932     * {@link Outline#canClip()}.
12933     *
12934     * @see #setOutlineProvider(ViewOutlineProvider)
12935     * @see #setClipToOutline(boolean)
12936     */
12937    public final boolean getClipToOutline() {
12938        return mRenderNode.getClipToOutline();
12939    }
12940
12941    /**
12942     * Sets whether the View's Outline should be used to clip the contents of the View.
12943     * <p>
12944     * Only a single non-rectangular clip can be applied on a View at any time.
12945     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12946     * circular reveal} animation take priority over Outline clipping, and
12947     * child Outline clipping takes priority over Outline clipping done by a
12948     * parent.
12949     * <p>
12950     * Note that this flag will only be respected if the View's Outline returns true from
12951     * {@link Outline#canClip()}.
12952     *
12953     * @see #setOutlineProvider(ViewOutlineProvider)
12954     * @see #getClipToOutline()
12955     */
12956    public void setClipToOutline(boolean clipToOutline) {
12957        damageInParent();
12958        if (getClipToOutline() != clipToOutline) {
12959            mRenderNode.setClipToOutline(clipToOutline);
12960        }
12961    }
12962
12963    // correspond to the enum values of View_outlineProvider
12964    private static final int PROVIDER_BACKGROUND = 0;
12965    private static final int PROVIDER_NONE = 1;
12966    private static final int PROVIDER_BOUNDS = 2;
12967    private static final int PROVIDER_PADDED_BOUNDS = 3;
12968    private void setOutlineProviderFromAttribute(int providerInt) {
12969        switch (providerInt) {
12970            case PROVIDER_BACKGROUND:
12971                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12972                break;
12973            case PROVIDER_NONE:
12974                setOutlineProvider(null);
12975                break;
12976            case PROVIDER_BOUNDS:
12977                setOutlineProvider(ViewOutlineProvider.BOUNDS);
12978                break;
12979            case PROVIDER_PADDED_BOUNDS:
12980                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12981                break;
12982        }
12983    }
12984
12985    /**
12986     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12987     * the shape of the shadow it casts, and enables outline clipping.
12988     * <p>
12989     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12990     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12991     * outline provider with this method allows this behavior to be overridden.
12992     * <p>
12993     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12994     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12995     * <p>
12996     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12997     *
12998     * @see #setClipToOutline(boolean)
12999     * @see #getClipToOutline()
13000     * @see #getOutlineProvider()
13001     */
13002    public void setOutlineProvider(ViewOutlineProvider provider) {
13003        mOutlineProvider = provider;
13004        invalidateOutline();
13005    }
13006
13007    /**
13008     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
13009     * that defines the shape of the shadow it casts, and enables outline clipping.
13010     *
13011     * @see #setOutlineProvider(ViewOutlineProvider)
13012     */
13013    public ViewOutlineProvider getOutlineProvider() {
13014        return mOutlineProvider;
13015    }
13016
13017    /**
13018     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
13019     *
13020     * @see #setOutlineProvider(ViewOutlineProvider)
13021     */
13022    public void invalidateOutline() {
13023        rebuildOutline();
13024
13025        notifySubtreeAccessibilityStateChangedIfNeeded();
13026        invalidateViewProperty(false, false);
13027    }
13028
13029    /**
13030     * Internal version of {@link #invalidateOutline()} which invalidates the
13031     * outline without invalidating the view itself. This is intended to be called from
13032     * within methods in the View class itself which are the result of the view being
13033     * invalidated already. For example, when we are drawing the background of a View,
13034     * we invalidate the outline in case it changed in the meantime, but we do not
13035     * need to invalidate the view because we're already drawing the background as part
13036     * of drawing the view in response to an earlier invalidation of the view.
13037     */
13038    private void rebuildOutline() {
13039        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
13040        if (mAttachInfo == null) return;
13041
13042        if (mOutlineProvider == null) {
13043            // no provider, remove outline
13044            mRenderNode.setOutline(null);
13045        } else {
13046            final Outline outline = mAttachInfo.mTmpOutline;
13047            outline.setEmpty();
13048            outline.setAlpha(1.0f);
13049
13050            mOutlineProvider.getOutline(this, outline);
13051            mRenderNode.setOutline(outline);
13052        }
13053    }
13054
13055    /**
13056     * HierarchyViewer only
13057     *
13058     * @hide
13059     */
13060    @ViewDebug.ExportedProperty(category = "drawing")
13061    public boolean hasShadow() {
13062        return mRenderNode.hasShadow();
13063    }
13064
13065
13066    /** @hide */
13067    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
13068        mRenderNode.setRevealClip(shouldClip, x, y, radius);
13069        invalidateViewProperty(false, false);
13070    }
13071
13072    /**
13073     * Hit rectangle in parent's coordinates
13074     *
13075     * @param outRect The hit rectangle of the view.
13076     */
13077    public void getHitRect(Rect outRect) {
13078        if (hasIdentityMatrix() || mAttachInfo == null) {
13079            outRect.set(mLeft, mTop, mRight, mBottom);
13080        } else {
13081            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
13082            tmpRect.set(0, 0, getWidth(), getHeight());
13083            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
13084            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
13085                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
13086        }
13087    }
13088
13089    /**
13090     * Determines whether the given point, in local coordinates is inside the view.
13091     */
13092    /*package*/ final boolean pointInView(float localX, float localY) {
13093        return pointInView(localX, localY, 0);
13094    }
13095
13096    /**
13097     * Utility method to determine whether the given point, in local coordinates,
13098     * is inside the view, where the area of the view is expanded by the slop factor.
13099     * This method is called while processing touch-move events to determine if the event
13100     * is still within the view.
13101     *
13102     * @hide
13103     */
13104    public boolean pointInView(float localX, float localY, float slop) {
13105        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
13106                localY < ((mBottom - mTop) + slop);
13107    }
13108
13109    /**
13110     * When a view has focus and the user navigates away from it, the next view is searched for
13111     * starting from the rectangle filled in by this method.
13112     *
13113     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
13114     * of the view.  However, if your view maintains some idea of internal selection,
13115     * such as a cursor, or a selected row or column, you should override this method and
13116     * fill in a more specific rectangle.
13117     *
13118     * @param r The rectangle to fill in, in this view's coordinates.
13119     */
13120    public void getFocusedRect(Rect r) {
13121        getDrawingRect(r);
13122    }
13123
13124    /**
13125     * If some part of this view is not clipped by any of its parents, then
13126     * return that area in r in global (root) coordinates. To convert r to local
13127     * coordinates (without taking possible View rotations into account), offset
13128     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
13129     * If the view is completely clipped or translated out, return false.
13130     *
13131     * @param r If true is returned, r holds the global coordinates of the
13132     *        visible portion of this view.
13133     * @param globalOffset If true is returned, globalOffset holds the dx,dy
13134     *        between this view and its root. globalOffet may be null.
13135     * @return true if r is non-empty (i.e. part of the view is visible at the
13136     *         root level.
13137     */
13138    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
13139        int width = mRight - mLeft;
13140        int height = mBottom - mTop;
13141        if (width > 0 && height > 0) {
13142            r.set(0, 0, width, height);
13143            if (globalOffset != null) {
13144                globalOffset.set(-mScrollX, -mScrollY);
13145            }
13146            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
13147        }
13148        return false;
13149    }
13150
13151    public final boolean getGlobalVisibleRect(Rect r) {
13152        return getGlobalVisibleRect(r, null);
13153    }
13154
13155    public final boolean getLocalVisibleRect(Rect r) {
13156        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
13157        if (getGlobalVisibleRect(r, offset)) {
13158            r.offset(-offset.x, -offset.y); // make r local
13159            return true;
13160        }
13161        return false;
13162    }
13163
13164    /**
13165     * Offset this view's vertical location by the specified number of pixels.
13166     *
13167     * @param offset the number of pixels to offset the view by
13168     */
13169    public void offsetTopAndBottom(int offset) {
13170        if (offset != 0) {
13171            final boolean matrixIsIdentity = hasIdentityMatrix();
13172            if (matrixIsIdentity) {
13173                if (isHardwareAccelerated()) {
13174                    invalidateViewProperty(false, false);
13175                } else {
13176                    final ViewParent p = mParent;
13177                    if (p != null && mAttachInfo != null) {
13178                        final Rect r = mAttachInfo.mTmpInvalRect;
13179                        int minTop;
13180                        int maxBottom;
13181                        int yLoc;
13182                        if (offset < 0) {
13183                            minTop = mTop + offset;
13184                            maxBottom = mBottom;
13185                            yLoc = offset;
13186                        } else {
13187                            minTop = mTop;
13188                            maxBottom = mBottom + offset;
13189                            yLoc = 0;
13190                        }
13191                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
13192                        p.invalidateChild(this, r);
13193                    }
13194                }
13195            } else {
13196                invalidateViewProperty(false, false);
13197            }
13198
13199            mTop += offset;
13200            mBottom += offset;
13201            mRenderNode.offsetTopAndBottom(offset);
13202            if (isHardwareAccelerated()) {
13203                invalidateViewProperty(false, false);
13204                invalidateParentIfNeededAndWasQuickRejected();
13205            } else {
13206                if (!matrixIsIdentity) {
13207                    invalidateViewProperty(false, true);
13208                }
13209                invalidateParentIfNeeded();
13210            }
13211            notifySubtreeAccessibilityStateChangedIfNeeded();
13212        }
13213    }
13214
13215    /**
13216     * Offset this view's horizontal location by the specified amount of pixels.
13217     *
13218     * @param offset the number of pixels to offset the view by
13219     */
13220    public void offsetLeftAndRight(int offset) {
13221        if (offset != 0) {
13222            final boolean matrixIsIdentity = hasIdentityMatrix();
13223            if (matrixIsIdentity) {
13224                if (isHardwareAccelerated()) {
13225                    invalidateViewProperty(false, false);
13226                } else {
13227                    final ViewParent p = mParent;
13228                    if (p != null && mAttachInfo != null) {
13229                        final Rect r = mAttachInfo.mTmpInvalRect;
13230                        int minLeft;
13231                        int maxRight;
13232                        if (offset < 0) {
13233                            minLeft = mLeft + offset;
13234                            maxRight = mRight;
13235                        } else {
13236                            minLeft = mLeft;
13237                            maxRight = mRight + offset;
13238                        }
13239                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
13240                        p.invalidateChild(this, r);
13241                    }
13242                }
13243            } else {
13244                invalidateViewProperty(false, false);
13245            }
13246
13247            mLeft += offset;
13248            mRight += offset;
13249            mRenderNode.offsetLeftAndRight(offset);
13250            if (isHardwareAccelerated()) {
13251                invalidateViewProperty(false, false);
13252                invalidateParentIfNeededAndWasQuickRejected();
13253            } else {
13254                if (!matrixIsIdentity) {
13255                    invalidateViewProperty(false, true);
13256                }
13257                invalidateParentIfNeeded();
13258            }
13259            notifySubtreeAccessibilityStateChangedIfNeeded();
13260        }
13261    }
13262
13263    /**
13264     * Get the LayoutParams associated with this view. All views should have
13265     * layout parameters. These supply parameters to the <i>parent</i> of this
13266     * view specifying how it should be arranged. There are many subclasses of
13267     * ViewGroup.LayoutParams, and these correspond to the different subclasses
13268     * of ViewGroup that are responsible for arranging their children.
13269     *
13270     * This method may return null if this View is not attached to a parent
13271     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
13272     * was not invoked successfully. When a View is attached to a parent
13273     * ViewGroup, this method must not return null.
13274     *
13275     * @return The LayoutParams associated with this view, or null if no
13276     *         parameters have been set yet
13277     */
13278    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
13279    public ViewGroup.LayoutParams getLayoutParams() {
13280        return mLayoutParams;
13281    }
13282
13283    /**
13284     * Set the layout parameters associated with this view. These supply
13285     * parameters to the <i>parent</i> of this view specifying how it should be
13286     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
13287     * correspond to the different subclasses of ViewGroup that are responsible
13288     * for arranging their children.
13289     *
13290     * @param params The layout parameters for this view, cannot be null
13291     */
13292    public void setLayoutParams(ViewGroup.LayoutParams params) {
13293        if (params == null) {
13294            throw new NullPointerException("Layout parameters cannot be null");
13295        }
13296        mLayoutParams = params;
13297        resolveLayoutParams();
13298        if (mParent instanceof ViewGroup) {
13299            ((ViewGroup) mParent).onSetLayoutParams(this, params);
13300        }
13301        requestLayout();
13302    }
13303
13304    /**
13305     * Resolve the layout parameters depending on the resolved layout direction
13306     *
13307     * @hide
13308     */
13309    public void resolveLayoutParams() {
13310        if (mLayoutParams != null) {
13311            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
13312        }
13313    }
13314
13315    /**
13316     * Set the scrolled position of your view. This will cause a call to
13317     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13318     * invalidated.
13319     * @param x the x position to scroll to
13320     * @param y the y position to scroll to
13321     */
13322    public void scrollTo(int x, int y) {
13323        if (mScrollX != x || mScrollY != y) {
13324            int oldX = mScrollX;
13325            int oldY = mScrollY;
13326            mScrollX = x;
13327            mScrollY = y;
13328            invalidateParentCaches();
13329            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
13330            if (!awakenScrollBars()) {
13331                postInvalidateOnAnimation();
13332            }
13333        }
13334    }
13335
13336    /**
13337     * Move the scrolled position of your view. This will cause a call to
13338     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13339     * invalidated.
13340     * @param x the amount of pixels to scroll by horizontally
13341     * @param y the amount of pixels to scroll by vertically
13342     */
13343    public void scrollBy(int x, int y) {
13344        scrollTo(mScrollX + x, mScrollY + y);
13345    }
13346
13347    /**
13348     * <p>Trigger the scrollbars to draw. When invoked this method starts an
13349     * animation to fade the scrollbars out after a default delay. If a subclass
13350     * provides animated scrolling, the start delay should equal the duration
13351     * of the scrolling animation.</p>
13352     *
13353     * <p>The animation starts only if at least one of the scrollbars is
13354     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
13355     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13356     * this method returns true, and false otherwise. If the animation is
13357     * started, this method calls {@link #invalidate()}; in that case the
13358     * caller should not call {@link #invalidate()}.</p>
13359     *
13360     * <p>This method should be invoked every time a subclass directly updates
13361     * the scroll parameters.</p>
13362     *
13363     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
13364     * and {@link #scrollTo(int, int)}.</p>
13365     *
13366     * @return true if the animation is played, false otherwise
13367     *
13368     * @see #awakenScrollBars(int)
13369     * @see #scrollBy(int, int)
13370     * @see #scrollTo(int, int)
13371     * @see #isHorizontalScrollBarEnabled()
13372     * @see #isVerticalScrollBarEnabled()
13373     * @see #setHorizontalScrollBarEnabled(boolean)
13374     * @see #setVerticalScrollBarEnabled(boolean)
13375     */
13376    protected boolean awakenScrollBars() {
13377        return mScrollCache != null &&
13378                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
13379    }
13380
13381    /**
13382     * Trigger the scrollbars to draw.
13383     * This method differs from awakenScrollBars() only in its default duration.
13384     * initialAwakenScrollBars() will show the scroll bars for longer than
13385     * usual to give the user more of a chance to notice them.
13386     *
13387     * @return true if the animation is played, false otherwise.
13388     */
13389    private boolean initialAwakenScrollBars() {
13390        return mScrollCache != null &&
13391                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
13392    }
13393
13394    /**
13395     * <p>
13396     * Trigger the scrollbars to draw. When invoked this method starts an
13397     * animation to fade the scrollbars out after a fixed delay. If a subclass
13398     * provides animated scrolling, the start delay should equal the duration of
13399     * the scrolling animation.
13400     * </p>
13401     *
13402     * <p>
13403     * The animation starts only if at least one of the scrollbars is enabled,
13404     * as specified by {@link #isHorizontalScrollBarEnabled()} and
13405     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13406     * this method returns true, and false otherwise. If the animation is
13407     * started, this method calls {@link #invalidate()}; in that case the caller
13408     * should not call {@link #invalidate()}.
13409     * </p>
13410     *
13411     * <p>
13412     * This method should be invoked every time a subclass directly updates the
13413     * scroll parameters.
13414     * </p>
13415     *
13416     * @param startDelay the delay, in milliseconds, after which the animation
13417     *        should start; when the delay is 0, the animation starts
13418     *        immediately
13419     * @return true if the animation is played, false otherwise
13420     *
13421     * @see #scrollBy(int, int)
13422     * @see #scrollTo(int, int)
13423     * @see #isHorizontalScrollBarEnabled()
13424     * @see #isVerticalScrollBarEnabled()
13425     * @see #setHorizontalScrollBarEnabled(boolean)
13426     * @see #setVerticalScrollBarEnabled(boolean)
13427     */
13428    protected boolean awakenScrollBars(int startDelay) {
13429        return awakenScrollBars(startDelay, true);
13430    }
13431
13432    /**
13433     * <p>
13434     * Trigger the scrollbars to draw. When invoked this method starts an
13435     * animation to fade the scrollbars out after a fixed delay. If a subclass
13436     * provides animated scrolling, the start delay should equal the duration of
13437     * the scrolling animation.
13438     * </p>
13439     *
13440     * <p>
13441     * The animation starts only if at least one of the scrollbars is enabled,
13442     * as specified by {@link #isHorizontalScrollBarEnabled()} and
13443     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13444     * this method returns true, and false otherwise. If the animation is
13445     * started, this method calls {@link #invalidate()} if the invalidate parameter
13446     * is set to true; in that case the caller
13447     * should not call {@link #invalidate()}.
13448     * </p>
13449     *
13450     * <p>
13451     * This method should be invoked every time a subclass directly updates the
13452     * scroll parameters.
13453     * </p>
13454     *
13455     * @param startDelay the delay, in milliseconds, after which the animation
13456     *        should start; when the delay is 0, the animation starts
13457     *        immediately
13458     *
13459     * @param invalidate Whether this method should call invalidate
13460     *
13461     * @return true if the animation is played, false otherwise
13462     *
13463     * @see #scrollBy(int, int)
13464     * @see #scrollTo(int, int)
13465     * @see #isHorizontalScrollBarEnabled()
13466     * @see #isVerticalScrollBarEnabled()
13467     * @see #setHorizontalScrollBarEnabled(boolean)
13468     * @see #setVerticalScrollBarEnabled(boolean)
13469     */
13470    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
13471        final ScrollabilityCache scrollCache = mScrollCache;
13472
13473        if (scrollCache == null || !scrollCache.fadeScrollBars) {
13474            return false;
13475        }
13476
13477        if (scrollCache.scrollBar == null) {
13478            scrollCache.scrollBar = new ScrollBarDrawable();
13479            scrollCache.scrollBar.setState(getDrawableState());
13480            scrollCache.scrollBar.setCallback(this);
13481        }
13482
13483        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
13484
13485            if (invalidate) {
13486                // Invalidate to show the scrollbars
13487                postInvalidateOnAnimation();
13488            }
13489
13490            if (scrollCache.state == ScrollabilityCache.OFF) {
13491                // FIXME: this is copied from WindowManagerService.
13492                // We should get this value from the system when it
13493                // is possible to do so.
13494                final int KEY_REPEAT_FIRST_DELAY = 750;
13495                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
13496            }
13497
13498            // Tell mScrollCache when we should start fading. This may
13499            // extend the fade start time if one was already scheduled
13500            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
13501            scrollCache.fadeStartTime = fadeStartTime;
13502            scrollCache.state = ScrollabilityCache.ON;
13503
13504            // Schedule our fader to run, unscheduling any old ones first
13505            if (mAttachInfo != null) {
13506                mAttachInfo.mHandler.removeCallbacks(scrollCache);
13507                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
13508            }
13509
13510            return true;
13511        }
13512
13513        return false;
13514    }
13515
13516    /**
13517     * Do not invalidate views which are not visible and which are not running an animation. They
13518     * will not get drawn and they should not set dirty flags as if they will be drawn
13519     */
13520    private boolean skipInvalidate() {
13521        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
13522                (!(mParent instanceof ViewGroup) ||
13523                        !((ViewGroup) mParent).isViewTransitioning(this));
13524    }
13525
13526    /**
13527     * Mark the area defined by dirty as needing to be drawn. If the view is
13528     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13529     * point in the future.
13530     * <p>
13531     * This must be called from a UI thread. To call from a non-UI thread, call
13532     * {@link #postInvalidate()}.
13533     * <p>
13534     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
13535     * {@code dirty}.
13536     *
13537     * @param dirty the rectangle representing the bounds of the dirty region
13538     */
13539    public void invalidate(Rect dirty) {
13540        final int scrollX = mScrollX;
13541        final int scrollY = mScrollY;
13542        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
13543                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
13544    }
13545
13546    /**
13547     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
13548     * coordinates of the dirty rect are relative to the view. If the view is
13549     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13550     * point in the future.
13551     * <p>
13552     * This must be called from a UI thread. To call from a non-UI thread, call
13553     * {@link #postInvalidate()}.
13554     *
13555     * @param l the left position of the dirty region
13556     * @param t the top position of the dirty region
13557     * @param r the right position of the dirty region
13558     * @param b the bottom position of the dirty region
13559     */
13560    public void invalidate(int l, int t, int r, int b) {
13561        final int scrollX = mScrollX;
13562        final int scrollY = mScrollY;
13563        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
13564    }
13565
13566    /**
13567     * Invalidate the whole view. If the view is visible,
13568     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
13569     * the future.
13570     * <p>
13571     * This must be called from a UI thread. To call from a non-UI thread, call
13572     * {@link #postInvalidate()}.
13573     */
13574    public void invalidate() {
13575        invalidate(true);
13576    }
13577
13578    /**
13579     * This is where the invalidate() work actually happens. A full invalidate()
13580     * causes the drawing cache to be invalidated, but this function can be
13581     * called with invalidateCache set to false to skip that invalidation step
13582     * for cases that do not need it (for example, a component that remains at
13583     * the same dimensions with the same content).
13584     *
13585     * @param invalidateCache Whether the drawing cache for this view should be
13586     *            invalidated as well. This is usually true for a full
13587     *            invalidate, but may be set to false if the View's contents or
13588     *            dimensions have not changed.
13589     */
13590    void invalidate(boolean invalidateCache) {
13591        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
13592    }
13593
13594    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
13595            boolean fullInvalidate) {
13596        if (mGhostView != null) {
13597            mGhostView.invalidate(true);
13598            return;
13599        }
13600
13601        if (skipInvalidate()) {
13602            return;
13603        }
13604
13605        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
13606                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
13607                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
13608                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
13609            if (fullInvalidate) {
13610                mLastIsOpaque = isOpaque();
13611                mPrivateFlags &= ~PFLAG_DRAWN;
13612            }
13613
13614            mPrivateFlags |= PFLAG_DIRTY;
13615
13616            if (invalidateCache) {
13617                mPrivateFlags |= PFLAG_INVALIDATED;
13618                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13619            }
13620
13621            // Propagate the damage rectangle to the parent view.
13622            final AttachInfo ai = mAttachInfo;
13623            final ViewParent p = mParent;
13624            if (p != null && ai != null && l < r && t < b) {
13625                final Rect damage = ai.mTmpInvalRect;
13626                damage.set(l, t, r, b);
13627                p.invalidateChild(this, damage);
13628            }
13629
13630            // Damage the entire projection receiver, if necessary.
13631            if (mBackground != null && mBackground.isProjected()) {
13632                final View receiver = getProjectionReceiver();
13633                if (receiver != null) {
13634                    receiver.damageInParent();
13635                }
13636            }
13637
13638            // Damage the entire IsolatedZVolume receiving this view's shadow.
13639            if (isHardwareAccelerated() && getZ() != 0) {
13640                damageShadowReceiver();
13641            }
13642        }
13643    }
13644
13645    /**
13646     * @return this view's projection receiver, or {@code null} if none exists
13647     */
13648    private View getProjectionReceiver() {
13649        ViewParent p = getParent();
13650        while (p != null && p instanceof View) {
13651            final View v = (View) p;
13652            if (v.isProjectionReceiver()) {
13653                return v;
13654            }
13655            p = p.getParent();
13656        }
13657
13658        return null;
13659    }
13660
13661    /**
13662     * @return whether the view is a projection receiver
13663     */
13664    private boolean isProjectionReceiver() {
13665        return mBackground != null;
13666    }
13667
13668    /**
13669     * Damage area of the screen that can be covered by this View's shadow.
13670     *
13671     * This method will guarantee that any changes to shadows cast by a View
13672     * are damaged on the screen for future redraw.
13673     */
13674    private void damageShadowReceiver() {
13675        final AttachInfo ai = mAttachInfo;
13676        if (ai != null) {
13677            ViewParent p = getParent();
13678            if (p != null && p instanceof ViewGroup) {
13679                final ViewGroup vg = (ViewGroup) p;
13680                vg.damageInParent();
13681            }
13682        }
13683    }
13684
13685    /**
13686     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
13687     * set any flags or handle all of the cases handled by the default invalidation methods.
13688     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
13689     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
13690     * walk up the hierarchy, transforming the dirty rect as necessary.
13691     *
13692     * The method also handles normal invalidation logic if display list properties are not
13693     * being used in this view. The invalidateParent and forceRedraw flags are used by that
13694     * backup approach, to handle these cases used in the various property-setting methods.
13695     *
13696     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
13697     * are not being used in this view
13698     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
13699     * list properties are not being used in this view
13700     */
13701    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
13702        if (!isHardwareAccelerated()
13703                || !mRenderNode.isValid()
13704                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
13705            if (invalidateParent) {
13706                invalidateParentCaches();
13707            }
13708            if (forceRedraw) {
13709                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13710            }
13711            invalidate(false);
13712        } else {
13713            damageInParent();
13714        }
13715        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
13716            damageShadowReceiver();
13717        }
13718    }
13719
13720    /**
13721     * Tells the parent view to damage this view's bounds.
13722     *
13723     * @hide
13724     */
13725    protected void damageInParent() {
13726        final AttachInfo ai = mAttachInfo;
13727        final ViewParent p = mParent;
13728        if (p != null && ai != null) {
13729            final Rect r = ai.mTmpInvalRect;
13730            r.set(0, 0, mRight - mLeft, mBottom - mTop);
13731            if (mParent instanceof ViewGroup) {
13732                ((ViewGroup) mParent).damageChild(this, r);
13733            } else {
13734                mParent.invalidateChild(this, r);
13735            }
13736        }
13737    }
13738
13739    /**
13740     * Utility method to transform a given Rect by the current matrix of this view.
13741     */
13742    void transformRect(final Rect rect) {
13743        if (!getMatrix().isIdentity()) {
13744            RectF boundingRect = mAttachInfo.mTmpTransformRect;
13745            boundingRect.set(rect);
13746            getMatrix().mapRect(boundingRect);
13747            rect.set((int) Math.floor(boundingRect.left),
13748                    (int) Math.floor(boundingRect.top),
13749                    (int) Math.ceil(boundingRect.right),
13750                    (int) Math.ceil(boundingRect.bottom));
13751        }
13752    }
13753
13754    /**
13755     * Used to indicate that the parent of this view should clear its caches. This functionality
13756     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13757     * which is necessary when various parent-managed properties of the view change, such as
13758     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
13759     * clears the parent caches and does not causes an invalidate event.
13760     *
13761     * @hide
13762     */
13763    protected void invalidateParentCaches() {
13764        if (mParent instanceof View) {
13765            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
13766        }
13767    }
13768
13769    /**
13770     * Used to indicate that the parent of this view should be invalidated. This functionality
13771     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13772     * which is necessary when various parent-managed properties of the view change, such as
13773     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
13774     * an invalidation event to the parent.
13775     *
13776     * @hide
13777     */
13778    protected void invalidateParentIfNeeded() {
13779        if (isHardwareAccelerated() && mParent instanceof View) {
13780            ((View) mParent).invalidate(true);
13781        }
13782    }
13783
13784    /**
13785     * @hide
13786     */
13787    protected void invalidateParentIfNeededAndWasQuickRejected() {
13788        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
13789            // View was rejected last time it was drawn by its parent; this may have changed
13790            invalidateParentIfNeeded();
13791        }
13792    }
13793
13794    /**
13795     * Indicates whether this View is opaque. An opaque View guarantees that it will
13796     * draw all the pixels overlapping its bounds using a fully opaque color.
13797     *
13798     * Subclasses of View should override this method whenever possible to indicate
13799     * whether an instance is opaque. Opaque Views are treated in a special way by
13800     * the View hierarchy, possibly allowing it to perform optimizations during
13801     * invalidate/draw passes.
13802     *
13803     * @return True if this View is guaranteed to be fully opaque, false otherwise.
13804     */
13805    @ViewDebug.ExportedProperty(category = "drawing")
13806    public boolean isOpaque() {
13807        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13808                getFinalAlpha() >= 1.0f;
13809    }
13810
13811    /**
13812     * @hide
13813     */
13814    protected void computeOpaqueFlags() {
13815        // Opaque if:
13816        //   - Has a background
13817        //   - Background is opaque
13818        //   - Doesn't have scrollbars or scrollbars overlay
13819
13820        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13821            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13822        } else {
13823            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13824        }
13825
13826        final int flags = mViewFlags;
13827        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13828                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13829                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13830            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13831        } else {
13832            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13833        }
13834    }
13835
13836    /**
13837     * @hide
13838     */
13839    protected boolean hasOpaqueScrollbars() {
13840        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13841    }
13842
13843    /**
13844     * @return A handler associated with the thread running the View. This
13845     * handler can be used to pump events in the UI events queue.
13846     */
13847    public Handler getHandler() {
13848        final AttachInfo attachInfo = mAttachInfo;
13849        if (attachInfo != null) {
13850            return attachInfo.mHandler;
13851        }
13852        return null;
13853    }
13854
13855    /**
13856     * Returns the queue of runnable for this view.
13857     *
13858     * @return the queue of runnables for this view
13859     */
13860    private HandlerActionQueue getRunQueue() {
13861        if (mRunQueue == null) {
13862            mRunQueue = new HandlerActionQueue();
13863        }
13864        return mRunQueue;
13865    }
13866
13867    /**
13868     * Gets the view root associated with the View.
13869     * @return The view root, or null if none.
13870     * @hide
13871     */
13872    public ViewRootImpl getViewRootImpl() {
13873        if (mAttachInfo != null) {
13874            return mAttachInfo.mViewRootImpl;
13875        }
13876        return null;
13877    }
13878
13879    /**
13880     * @hide
13881     */
13882    public ThreadedRenderer getHardwareRenderer() {
13883        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
13884    }
13885
13886    /**
13887     * <p>Causes the Runnable to be added to the message queue.
13888     * The runnable will be run on the user interface thread.</p>
13889     *
13890     * @param action The Runnable that will be executed.
13891     *
13892     * @return Returns true if the Runnable was successfully placed in to the
13893     *         message queue.  Returns false on failure, usually because the
13894     *         looper processing the message queue is exiting.
13895     *
13896     * @see #postDelayed
13897     * @see #removeCallbacks
13898     */
13899    public boolean post(Runnable action) {
13900        final AttachInfo attachInfo = mAttachInfo;
13901        if (attachInfo != null) {
13902            return attachInfo.mHandler.post(action);
13903        }
13904
13905        // Postpone the runnable until we know on which thread it needs to run.
13906        // Assume that the runnable will be successfully placed after attach.
13907        getRunQueue().post(action);
13908        return true;
13909    }
13910
13911    /**
13912     * <p>Causes the Runnable to be added to the message queue, to be run
13913     * after the specified amount of time elapses.
13914     * The runnable will be run on the user interface thread.</p>
13915     *
13916     * @param action The Runnable that will be executed.
13917     * @param delayMillis The delay (in milliseconds) until the Runnable
13918     *        will be executed.
13919     *
13920     * @return true if the Runnable was successfully placed in to the
13921     *         message queue.  Returns false on failure, usually because the
13922     *         looper processing the message queue is exiting.  Note that a
13923     *         result of true does not mean the Runnable will be processed --
13924     *         if the looper is quit before the delivery time of the message
13925     *         occurs then the message will be dropped.
13926     *
13927     * @see #post
13928     * @see #removeCallbacks
13929     */
13930    public boolean postDelayed(Runnable action, long delayMillis) {
13931        final AttachInfo attachInfo = mAttachInfo;
13932        if (attachInfo != null) {
13933            return attachInfo.mHandler.postDelayed(action, delayMillis);
13934        }
13935
13936        // Postpone the runnable until we know on which thread it needs to run.
13937        // Assume that the runnable will be successfully placed after attach.
13938        getRunQueue().postDelayed(action, delayMillis);
13939        return true;
13940    }
13941
13942    /**
13943     * <p>Causes the Runnable to execute on the next animation time step.
13944     * The runnable will be run on the user interface thread.</p>
13945     *
13946     * @param action The Runnable that will be executed.
13947     *
13948     * @see #postOnAnimationDelayed
13949     * @see #removeCallbacks
13950     */
13951    public void postOnAnimation(Runnable action) {
13952        final AttachInfo attachInfo = mAttachInfo;
13953        if (attachInfo != null) {
13954            attachInfo.mViewRootImpl.mChoreographer.postCallback(
13955                    Choreographer.CALLBACK_ANIMATION, action, null);
13956        } else {
13957            // Postpone the runnable until we know
13958            // on which thread it needs to run.
13959            getRunQueue().post(action);
13960        }
13961    }
13962
13963    /**
13964     * <p>Causes the Runnable to execute on the next animation time step,
13965     * after the specified amount of time elapses.
13966     * The runnable will be run on the user interface thread.</p>
13967     *
13968     * @param action The Runnable that will be executed.
13969     * @param delayMillis The delay (in milliseconds) until the Runnable
13970     *        will be executed.
13971     *
13972     * @see #postOnAnimation
13973     * @see #removeCallbacks
13974     */
13975    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13976        final AttachInfo attachInfo = mAttachInfo;
13977        if (attachInfo != null) {
13978            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13979                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13980        } else {
13981            // Postpone the runnable until we know
13982            // on which thread it needs to run.
13983            getRunQueue().postDelayed(action, delayMillis);
13984        }
13985    }
13986
13987    /**
13988     * <p>Removes the specified Runnable from the message queue.</p>
13989     *
13990     * @param action The Runnable to remove from the message handling queue
13991     *
13992     * @return true if this view could ask the Handler to remove the Runnable,
13993     *         false otherwise. When the returned value is true, the Runnable
13994     *         may or may not have been actually removed from the message queue
13995     *         (for instance, if the Runnable was not in the queue already.)
13996     *
13997     * @see #post
13998     * @see #postDelayed
13999     * @see #postOnAnimation
14000     * @see #postOnAnimationDelayed
14001     */
14002    public boolean removeCallbacks(Runnable action) {
14003        if (action != null) {
14004            final AttachInfo attachInfo = mAttachInfo;
14005            if (attachInfo != null) {
14006                attachInfo.mHandler.removeCallbacks(action);
14007                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14008                        Choreographer.CALLBACK_ANIMATION, action, null);
14009            }
14010            getRunQueue().removeCallbacks(action);
14011        }
14012        return true;
14013    }
14014
14015    /**
14016     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
14017     * Use this to invalidate the View from a non-UI thread.</p>
14018     *
14019     * <p>This method can be invoked from outside of the UI thread
14020     * only when this View is attached to a window.</p>
14021     *
14022     * @see #invalidate()
14023     * @see #postInvalidateDelayed(long)
14024     */
14025    public void postInvalidate() {
14026        postInvalidateDelayed(0);
14027    }
14028
14029    /**
14030     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14031     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
14032     *
14033     * <p>This method can be invoked from outside of the UI thread
14034     * only when this View is attached to a window.</p>
14035     *
14036     * @param left The left coordinate of the rectangle to invalidate.
14037     * @param top The top coordinate of the rectangle to invalidate.
14038     * @param right The right coordinate of the rectangle to invalidate.
14039     * @param bottom The bottom coordinate of the rectangle to invalidate.
14040     *
14041     * @see #invalidate(int, int, int, int)
14042     * @see #invalidate(Rect)
14043     * @see #postInvalidateDelayed(long, int, int, int, int)
14044     */
14045    public void postInvalidate(int left, int top, int right, int bottom) {
14046        postInvalidateDelayed(0, left, top, right, bottom);
14047    }
14048
14049    /**
14050     * <p>Cause an invalidate to happen on a subsequent cycle through the event
14051     * loop. Waits for the specified amount of time.</p>
14052     *
14053     * <p>This method can be invoked from outside of the UI thread
14054     * only when this View is attached to a window.</p>
14055     *
14056     * @param delayMilliseconds the duration in milliseconds to delay the
14057     *         invalidation by
14058     *
14059     * @see #invalidate()
14060     * @see #postInvalidate()
14061     */
14062    public void postInvalidateDelayed(long delayMilliseconds) {
14063        // We try only with the AttachInfo because there's no point in invalidating
14064        // if we are not attached to our window
14065        final AttachInfo attachInfo = mAttachInfo;
14066        if (attachInfo != null) {
14067            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
14068        }
14069    }
14070
14071    /**
14072     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14073     * through the event loop. Waits for the specified amount of time.</p>
14074     *
14075     * <p>This method can be invoked from outside of the UI thread
14076     * only when this View is attached to a window.</p>
14077     *
14078     * @param delayMilliseconds the duration in milliseconds to delay the
14079     *         invalidation by
14080     * @param left The left coordinate of the rectangle to invalidate.
14081     * @param top The top coordinate of the rectangle to invalidate.
14082     * @param right The right coordinate of the rectangle to invalidate.
14083     * @param bottom The bottom coordinate of the rectangle to invalidate.
14084     *
14085     * @see #invalidate(int, int, int, int)
14086     * @see #invalidate(Rect)
14087     * @see #postInvalidate(int, int, int, int)
14088     */
14089    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
14090            int right, int bottom) {
14091
14092        // We try only with the AttachInfo because there's no point in invalidating
14093        // if we are not attached to our window
14094        final AttachInfo attachInfo = mAttachInfo;
14095        if (attachInfo != null) {
14096            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14097            info.target = this;
14098            info.left = left;
14099            info.top = top;
14100            info.right = right;
14101            info.bottom = bottom;
14102
14103            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
14104        }
14105    }
14106
14107    /**
14108     * <p>Cause an invalidate to happen on the next animation time step, typically the
14109     * next display frame.</p>
14110     *
14111     * <p>This method can be invoked from outside of the UI thread
14112     * only when this View is attached to a window.</p>
14113     *
14114     * @see #invalidate()
14115     */
14116    public void postInvalidateOnAnimation() {
14117        // We try only with the AttachInfo because there's no point in invalidating
14118        // if we are not attached to our window
14119        final AttachInfo attachInfo = mAttachInfo;
14120        if (attachInfo != null) {
14121            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
14122        }
14123    }
14124
14125    /**
14126     * <p>Cause an invalidate of the specified area to happen on the next animation
14127     * time step, typically the next display frame.</p>
14128     *
14129     * <p>This method can be invoked from outside of the UI thread
14130     * only when this View is attached to a window.</p>
14131     *
14132     * @param left The left coordinate of the rectangle to invalidate.
14133     * @param top The top coordinate of the rectangle to invalidate.
14134     * @param right The right coordinate of the rectangle to invalidate.
14135     * @param bottom The bottom coordinate of the rectangle to invalidate.
14136     *
14137     * @see #invalidate(int, int, int, int)
14138     * @see #invalidate(Rect)
14139     */
14140    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
14141        // We try only with the AttachInfo because there's no point in invalidating
14142        // if we are not attached to our window
14143        final AttachInfo attachInfo = mAttachInfo;
14144        if (attachInfo != null) {
14145            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14146            info.target = this;
14147            info.left = left;
14148            info.top = top;
14149            info.right = right;
14150            info.bottom = bottom;
14151
14152            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
14153        }
14154    }
14155
14156    /**
14157     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
14158     * This event is sent at most once every
14159     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
14160     */
14161    private void postSendViewScrolledAccessibilityEventCallback() {
14162        if (mSendViewScrolledAccessibilityEvent == null) {
14163            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
14164        }
14165        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
14166            mSendViewScrolledAccessibilityEvent.mIsPending = true;
14167            postDelayed(mSendViewScrolledAccessibilityEvent,
14168                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
14169        }
14170    }
14171
14172    /**
14173     * Called by a parent to request that a child update its values for mScrollX
14174     * and mScrollY if necessary. This will typically be done if the child is
14175     * animating a scroll using a {@link android.widget.Scroller Scroller}
14176     * object.
14177     */
14178    public void computeScroll() {
14179    }
14180
14181    /**
14182     * <p>Indicate whether the horizontal edges are faded when the view is
14183     * scrolled horizontally.</p>
14184     *
14185     * @return true if the horizontal edges should are faded on scroll, false
14186     *         otherwise
14187     *
14188     * @see #setHorizontalFadingEdgeEnabled(boolean)
14189     *
14190     * @attr ref android.R.styleable#View_requiresFadingEdge
14191     */
14192    public boolean isHorizontalFadingEdgeEnabled() {
14193        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
14194    }
14195
14196    /**
14197     * <p>Define whether the horizontal edges should be faded when this view
14198     * is scrolled horizontally.</p>
14199     *
14200     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
14201     *                                    be faded when the view is scrolled
14202     *                                    horizontally
14203     *
14204     * @see #isHorizontalFadingEdgeEnabled()
14205     *
14206     * @attr ref android.R.styleable#View_requiresFadingEdge
14207     */
14208    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
14209        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
14210            if (horizontalFadingEdgeEnabled) {
14211                initScrollCache();
14212            }
14213
14214            mViewFlags ^= FADING_EDGE_HORIZONTAL;
14215        }
14216    }
14217
14218    /**
14219     * <p>Indicate whether the vertical edges are faded when the view is
14220     * scrolled horizontally.</p>
14221     *
14222     * @return true if the vertical edges should are faded on scroll, false
14223     *         otherwise
14224     *
14225     * @see #setVerticalFadingEdgeEnabled(boolean)
14226     *
14227     * @attr ref android.R.styleable#View_requiresFadingEdge
14228     */
14229    public boolean isVerticalFadingEdgeEnabled() {
14230        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
14231    }
14232
14233    /**
14234     * <p>Define whether the vertical edges should be faded when this view
14235     * is scrolled vertically.</p>
14236     *
14237     * @param verticalFadingEdgeEnabled true if the vertical edges should
14238     *                                  be faded when the view is scrolled
14239     *                                  vertically
14240     *
14241     * @see #isVerticalFadingEdgeEnabled()
14242     *
14243     * @attr ref android.R.styleable#View_requiresFadingEdge
14244     */
14245    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
14246        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
14247            if (verticalFadingEdgeEnabled) {
14248                initScrollCache();
14249            }
14250
14251            mViewFlags ^= FADING_EDGE_VERTICAL;
14252        }
14253    }
14254
14255    /**
14256     * Returns the strength, or intensity, of the top faded edge. The strength is
14257     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14258     * returns 0.0 or 1.0 but no value in between.
14259     *
14260     * Subclasses should override this method to provide a smoother fade transition
14261     * when scrolling occurs.
14262     *
14263     * @return the intensity of the top fade as a float between 0.0f and 1.0f
14264     */
14265    protected float getTopFadingEdgeStrength() {
14266        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
14267    }
14268
14269    /**
14270     * Returns the strength, or intensity, of the bottom faded edge. The strength is
14271     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14272     * returns 0.0 or 1.0 but no value in between.
14273     *
14274     * Subclasses should override this method to provide a smoother fade transition
14275     * when scrolling occurs.
14276     *
14277     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
14278     */
14279    protected float getBottomFadingEdgeStrength() {
14280        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
14281                computeVerticalScrollRange() ? 1.0f : 0.0f;
14282    }
14283
14284    /**
14285     * Returns the strength, or intensity, of the left faded edge. The strength is
14286     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14287     * returns 0.0 or 1.0 but no value in between.
14288     *
14289     * Subclasses should override this method to provide a smoother fade transition
14290     * when scrolling occurs.
14291     *
14292     * @return the intensity of the left fade as a float between 0.0f and 1.0f
14293     */
14294    protected float getLeftFadingEdgeStrength() {
14295        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
14296    }
14297
14298    /**
14299     * Returns the strength, or intensity, of the right faded edge. The strength is
14300     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14301     * returns 0.0 or 1.0 but no value in between.
14302     *
14303     * Subclasses should override this method to provide a smoother fade transition
14304     * when scrolling occurs.
14305     *
14306     * @return the intensity of the right fade as a float between 0.0f and 1.0f
14307     */
14308    protected float getRightFadingEdgeStrength() {
14309        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
14310                computeHorizontalScrollRange() ? 1.0f : 0.0f;
14311    }
14312
14313    /**
14314     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
14315     * scrollbar is not drawn by default.</p>
14316     *
14317     * @return true if the horizontal scrollbar should be painted, false
14318     *         otherwise
14319     *
14320     * @see #setHorizontalScrollBarEnabled(boolean)
14321     */
14322    public boolean isHorizontalScrollBarEnabled() {
14323        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14324    }
14325
14326    /**
14327     * <p>Define whether the horizontal scrollbar should be drawn or not. The
14328     * scrollbar is not drawn by default.</p>
14329     *
14330     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
14331     *                                   be painted
14332     *
14333     * @see #isHorizontalScrollBarEnabled()
14334     */
14335    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
14336        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
14337            mViewFlags ^= SCROLLBARS_HORIZONTAL;
14338            computeOpaqueFlags();
14339            resolvePadding();
14340        }
14341    }
14342
14343    /**
14344     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
14345     * scrollbar is not drawn by default.</p>
14346     *
14347     * @return true if the vertical scrollbar should be painted, false
14348     *         otherwise
14349     *
14350     * @see #setVerticalScrollBarEnabled(boolean)
14351     */
14352    public boolean isVerticalScrollBarEnabled() {
14353        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
14354    }
14355
14356    /**
14357     * <p>Define whether the vertical scrollbar should be drawn or not. The
14358     * scrollbar is not drawn by default.</p>
14359     *
14360     * @param verticalScrollBarEnabled true if the vertical scrollbar should
14361     *                                 be painted
14362     *
14363     * @see #isVerticalScrollBarEnabled()
14364     */
14365    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
14366        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
14367            mViewFlags ^= SCROLLBARS_VERTICAL;
14368            computeOpaqueFlags();
14369            resolvePadding();
14370        }
14371    }
14372
14373    /**
14374     * @hide
14375     */
14376    protected void recomputePadding() {
14377        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14378    }
14379
14380    /**
14381     * Define whether scrollbars will fade when the view is not scrolling.
14382     *
14383     * @param fadeScrollbars whether to enable fading
14384     *
14385     * @attr ref android.R.styleable#View_fadeScrollbars
14386     */
14387    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
14388        initScrollCache();
14389        final ScrollabilityCache scrollabilityCache = mScrollCache;
14390        scrollabilityCache.fadeScrollBars = fadeScrollbars;
14391        if (fadeScrollbars) {
14392            scrollabilityCache.state = ScrollabilityCache.OFF;
14393        } else {
14394            scrollabilityCache.state = ScrollabilityCache.ON;
14395        }
14396    }
14397
14398    /**
14399     *
14400     * Returns true if scrollbars will fade when this view is not scrolling
14401     *
14402     * @return true if scrollbar fading is enabled
14403     *
14404     * @attr ref android.R.styleable#View_fadeScrollbars
14405     */
14406    public boolean isScrollbarFadingEnabled() {
14407        return mScrollCache != null && mScrollCache.fadeScrollBars;
14408    }
14409
14410    /**
14411     *
14412     * Returns the delay before scrollbars fade.
14413     *
14414     * @return the delay before scrollbars fade
14415     *
14416     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14417     */
14418    public int getScrollBarDefaultDelayBeforeFade() {
14419        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
14420                mScrollCache.scrollBarDefaultDelayBeforeFade;
14421    }
14422
14423    /**
14424     * Define the delay before scrollbars fade.
14425     *
14426     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
14427     *
14428     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14429     */
14430    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
14431        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
14432    }
14433
14434    /**
14435     *
14436     * Returns the scrollbar fade duration.
14437     *
14438     * @return the scrollbar fade duration
14439     *
14440     * @attr ref android.R.styleable#View_scrollbarFadeDuration
14441     */
14442    public int getScrollBarFadeDuration() {
14443        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
14444                mScrollCache.scrollBarFadeDuration;
14445    }
14446
14447    /**
14448     * Define the scrollbar fade duration.
14449     *
14450     * @param scrollBarFadeDuration - the scrollbar fade duration
14451     *
14452     * @attr ref android.R.styleable#View_scrollbarFadeDuration
14453     */
14454    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
14455        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
14456    }
14457
14458    /**
14459     *
14460     * Returns the scrollbar size.
14461     *
14462     * @return the scrollbar size
14463     *
14464     * @attr ref android.R.styleable#View_scrollbarSize
14465     */
14466    public int getScrollBarSize() {
14467        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
14468                mScrollCache.scrollBarSize;
14469    }
14470
14471    /**
14472     * Define the scrollbar size.
14473     *
14474     * @param scrollBarSize - the scrollbar size
14475     *
14476     * @attr ref android.R.styleable#View_scrollbarSize
14477     */
14478    public void setScrollBarSize(int scrollBarSize) {
14479        getScrollCache().scrollBarSize = scrollBarSize;
14480    }
14481
14482    /**
14483     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
14484     * inset. When inset, they add to the padding of the view. And the scrollbars
14485     * can be drawn inside the padding area or on the edge of the view. For example,
14486     * if a view has a background drawable and you want to draw the scrollbars
14487     * inside the padding specified by the drawable, you can use
14488     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
14489     * appear at the edge of the view, ignoring the padding, then you can use
14490     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
14491     * @param style the style of the scrollbars. Should be one of
14492     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
14493     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
14494     * @see #SCROLLBARS_INSIDE_OVERLAY
14495     * @see #SCROLLBARS_INSIDE_INSET
14496     * @see #SCROLLBARS_OUTSIDE_OVERLAY
14497     * @see #SCROLLBARS_OUTSIDE_INSET
14498     *
14499     * @attr ref android.R.styleable#View_scrollbarStyle
14500     */
14501    public void setScrollBarStyle(@ScrollBarStyle int style) {
14502        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
14503            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
14504            computeOpaqueFlags();
14505            resolvePadding();
14506        }
14507    }
14508
14509    /**
14510     * <p>Returns the current scrollbar style.</p>
14511     * @return the current scrollbar style
14512     * @see #SCROLLBARS_INSIDE_OVERLAY
14513     * @see #SCROLLBARS_INSIDE_INSET
14514     * @see #SCROLLBARS_OUTSIDE_OVERLAY
14515     * @see #SCROLLBARS_OUTSIDE_INSET
14516     *
14517     * @attr ref android.R.styleable#View_scrollbarStyle
14518     */
14519    @ViewDebug.ExportedProperty(mapping = {
14520            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
14521            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
14522            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
14523            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
14524    })
14525    @ScrollBarStyle
14526    public int getScrollBarStyle() {
14527        return mViewFlags & SCROLLBARS_STYLE_MASK;
14528    }
14529
14530    /**
14531     * <p>Compute the horizontal range that the horizontal scrollbar
14532     * represents.</p>
14533     *
14534     * <p>The range is expressed in arbitrary units that must be the same as the
14535     * units used by {@link #computeHorizontalScrollExtent()} and
14536     * {@link #computeHorizontalScrollOffset()}.</p>
14537     *
14538     * <p>The default range is the drawing width of this view.</p>
14539     *
14540     * @return the total horizontal range represented by the horizontal
14541     *         scrollbar
14542     *
14543     * @see #computeHorizontalScrollExtent()
14544     * @see #computeHorizontalScrollOffset()
14545     * @see android.widget.ScrollBarDrawable
14546     */
14547    protected int computeHorizontalScrollRange() {
14548        return getWidth();
14549    }
14550
14551    /**
14552     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
14553     * within the horizontal range. This value is used to compute the position
14554     * of the thumb within the scrollbar's track.</p>
14555     *
14556     * <p>The range is expressed in arbitrary units that must be the same as the
14557     * units used by {@link #computeHorizontalScrollRange()} and
14558     * {@link #computeHorizontalScrollExtent()}.</p>
14559     *
14560     * <p>The default offset is the scroll offset of this view.</p>
14561     *
14562     * @return the horizontal offset of the scrollbar's thumb
14563     *
14564     * @see #computeHorizontalScrollRange()
14565     * @see #computeHorizontalScrollExtent()
14566     * @see android.widget.ScrollBarDrawable
14567     */
14568    protected int computeHorizontalScrollOffset() {
14569        return mScrollX;
14570    }
14571
14572    /**
14573     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
14574     * within the horizontal range. This value is used to compute the length
14575     * of the thumb within the scrollbar's track.</p>
14576     *
14577     * <p>The range is expressed in arbitrary units that must be the same as the
14578     * units used by {@link #computeHorizontalScrollRange()} and
14579     * {@link #computeHorizontalScrollOffset()}.</p>
14580     *
14581     * <p>The default extent is the drawing width of this view.</p>
14582     *
14583     * @return the horizontal extent of the scrollbar's thumb
14584     *
14585     * @see #computeHorizontalScrollRange()
14586     * @see #computeHorizontalScrollOffset()
14587     * @see android.widget.ScrollBarDrawable
14588     */
14589    protected int computeHorizontalScrollExtent() {
14590        return getWidth();
14591    }
14592
14593    /**
14594     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
14595     *
14596     * <p>The range is expressed in arbitrary units that must be the same as the
14597     * units used by {@link #computeVerticalScrollExtent()} and
14598     * {@link #computeVerticalScrollOffset()}.</p>
14599     *
14600     * @return the total vertical range represented by the vertical scrollbar
14601     *
14602     * <p>The default range is the drawing height of this view.</p>
14603     *
14604     * @see #computeVerticalScrollExtent()
14605     * @see #computeVerticalScrollOffset()
14606     * @see android.widget.ScrollBarDrawable
14607     */
14608    protected int computeVerticalScrollRange() {
14609        return getHeight();
14610    }
14611
14612    /**
14613     * <p>Compute the vertical offset of the vertical scrollbar's thumb
14614     * within the horizontal range. This value is used to compute the position
14615     * of the thumb within the scrollbar's track.</p>
14616     *
14617     * <p>The range is expressed in arbitrary units that must be the same as the
14618     * units used by {@link #computeVerticalScrollRange()} and
14619     * {@link #computeVerticalScrollExtent()}.</p>
14620     *
14621     * <p>The default offset is the scroll offset of this view.</p>
14622     *
14623     * @return the vertical offset of the scrollbar's thumb
14624     *
14625     * @see #computeVerticalScrollRange()
14626     * @see #computeVerticalScrollExtent()
14627     * @see android.widget.ScrollBarDrawable
14628     */
14629    protected int computeVerticalScrollOffset() {
14630        return mScrollY;
14631    }
14632
14633    /**
14634     * <p>Compute the vertical extent of the vertical scrollbar's thumb
14635     * within the vertical range. This value is used to compute the length
14636     * of the thumb within the scrollbar's track.</p>
14637     *
14638     * <p>The range is expressed in arbitrary units that must be the same as the
14639     * units used by {@link #computeVerticalScrollRange()} and
14640     * {@link #computeVerticalScrollOffset()}.</p>
14641     *
14642     * <p>The default extent is the drawing height of this view.</p>
14643     *
14644     * @return the vertical extent of the scrollbar's thumb
14645     *
14646     * @see #computeVerticalScrollRange()
14647     * @see #computeVerticalScrollOffset()
14648     * @see android.widget.ScrollBarDrawable
14649     */
14650    protected int computeVerticalScrollExtent() {
14651        return getHeight();
14652    }
14653
14654    /**
14655     * Check if this view can be scrolled horizontally in a certain direction.
14656     *
14657     * @param direction Negative to check scrolling left, positive to check scrolling right.
14658     * @return true if this view can be scrolled in the specified direction, false otherwise.
14659     */
14660    public boolean canScrollHorizontally(int direction) {
14661        final int offset = computeHorizontalScrollOffset();
14662        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
14663        if (range == 0) return false;
14664        if (direction < 0) {
14665            return offset > 0;
14666        } else {
14667            return offset < range - 1;
14668        }
14669    }
14670
14671    /**
14672     * Check if this view can be scrolled vertically in a certain direction.
14673     *
14674     * @param direction Negative to check scrolling up, positive to check scrolling down.
14675     * @return true if this view can be scrolled in the specified direction, false otherwise.
14676     */
14677    public boolean canScrollVertically(int direction) {
14678        final int offset = computeVerticalScrollOffset();
14679        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
14680        if (range == 0) return false;
14681        if (direction < 0) {
14682            return offset > 0;
14683        } else {
14684            return offset < range - 1;
14685        }
14686    }
14687
14688    void getScrollIndicatorBounds(@NonNull Rect out) {
14689        out.left = mScrollX;
14690        out.right = mScrollX + mRight - mLeft;
14691        out.top = mScrollY;
14692        out.bottom = mScrollY + mBottom - mTop;
14693    }
14694
14695    private void onDrawScrollIndicators(Canvas c) {
14696        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
14697            // No scroll indicators enabled.
14698            return;
14699        }
14700
14701        final Drawable dr = mScrollIndicatorDrawable;
14702        if (dr == null) {
14703            // Scroll indicators aren't supported here.
14704            return;
14705        }
14706
14707        final int h = dr.getIntrinsicHeight();
14708        final int w = dr.getIntrinsicWidth();
14709        final Rect rect = mAttachInfo.mTmpInvalRect;
14710        getScrollIndicatorBounds(rect);
14711
14712        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
14713            final boolean canScrollUp = canScrollVertically(-1);
14714            if (canScrollUp) {
14715                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
14716                dr.draw(c);
14717            }
14718        }
14719
14720        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
14721            final boolean canScrollDown = canScrollVertically(1);
14722            if (canScrollDown) {
14723                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
14724                dr.draw(c);
14725            }
14726        }
14727
14728        final int leftRtl;
14729        final int rightRtl;
14730        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14731            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
14732            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
14733        } else {
14734            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
14735            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
14736        }
14737
14738        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
14739        if ((mPrivateFlags3 & leftMask) != 0) {
14740            final boolean canScrollLeft = canScrollHorizontally(-1);
14741            if (canScrollLeft) {
14742                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
14743                dr.draw(c);
14744            }
14745        }
14746
14747        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
14748        if ((mPrivateFlags3 & rightMask) != 0) {
14749            final boolean canScrollRight = canScrollHorizontally(1);
14750            if (canScrollRight) {
14751                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
14752                dr.draw(c);
14753            }
14754        }
14755    }
14756
14757    private void getHorizontalScrollBarBounds(Rect bounds) {
14758        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14759        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14760                && !isVerticalScrollBarHidden();
14761        final int size = getHorizontalScrollbarHeight();
14762        final int verticalScrollBarGap = drawVerticalScrollBar ?
14763                getVerticalScrollbarWidth() : 0;
14764        final int width = mRight - mLeft;
14765        final int height = mBottom - mTop;
14766        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
14767        bounds.left = mScrollX + (mPaddingLeft & inside);
14768        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14769        bounds.bottom = bounds.top + size;
14770    }
14771
14772    private void getVerticalScrollBarBounds(Rect bounds) {
14773        if (mRoundScrollbarRenderer == null) {
14774            getStraightVerticalScrollBarBounds(bounds);
14775        } else {
14776            getRoundVerticalScrollBarBounds(bounds);
14777        }
14778    }
14779
14780    private void getRoundVerticalScrollBarBounds(Rect bounds) {
14781        final int width = mRight - mLeft;
14782        final int height = mBottom - mTop;
14783        // Do not take padding into account as we always want the scrollbars
14784        // to hug the screen for round wearable devices.
14785        bounds.left = mScrollX;
14786        bounds.top = mScrollY;
14787        bounds.right = bounds.left + width;
14788        bounds.bottom = mScrollY + height;
14789    }
14790
14791    private void getStraightVerticalScrollBarBounds(Rect bounds) {
14792        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14793        final int size = getVerticalScrollbarWidth();
14794        int verticalScrollbarPosition = mVerticalScrollbarPosition;
14795        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14796            verticalScrollbarPosition = isLayoutRtl() ?
14797                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14798        }
14799        final int width = mRight - mLeft;
14800        final int height = mBottom - mTop;
14801        switch (verticalScrollbarPosition) {
14802            default:
14803            case SCROLLBAR_POSITION_RIGHT:
14804                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
14805                break;
14806            case SCROLLBAR_POSITION_LEFT:
14807                bounds.left = mScrollX + (mUserPaddingLeft & inside);
14808                break;
14809        }
14810        bounds.top = mScrollY + (mPaddingTop & inside);
14811        bounds.right = bounds.left + size;
14812        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
14813    }
14814
14815    /**
14816     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
14817     * scrollbars are painted only if they have been awakened first.</p>
14818     *
14819     * @param canvas the canvas on which to draw the scrollbars
14820     *
14821     * @see #awakenScrollBars(int)
14822     */
14823    protected final void onDrawScrollBars(Canvas canvas) {
14824        // scrollbars are drawn only when the animation is running
14825        final ScrollabilityCache cache = mScrollCache;
14826
14827        if (cache != null) {
14828
14829            int state = cache.state;
14830
14831            if (state == ScrollabilityCache.OFF) {
14832                return;
14833            }
14834
14835            boolean invalidate = false;
14836
14837            if (state == ScrollabilityCache.FADING) {
14838                // We're fading -- get our fade interpolation
14839                if (cache.interpolatorValues == null) {
14840                    cache.interpolatorValues = new float[1];
14841                }
14842
14843                float[] values = cache.interpolatorValues;
14844
14845                // Stops the animation if we're done
14846                if (cache.scrollBarInterpolator.timeToValues(values) ==
14847                        Interpolator.Result.FREEZE_END) {
14848                    cache.state = ScrollabilityCache.OFF;
14849                } else {
14850                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14851                }
14852
14853                // This will make the scroll bars inval themselves after
14854                // drawing. We only want this when we're fading so that
14855                // we prevent excessive redraws
14856                invalidate = true;
14857            } else {
14858                // We're just on -- but we may have been fading before so
14859                // reset alpha
14860                cache.scrollBar.mutate().setAlpha(255);
14861            }
14862
14863            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
14864            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14865                    && !isVerticalScrollBarHidden();
14866
14867            // Fork out the scroll bar drawing for round wearable devices.
14868            if (mRoundScrollbarRenderer != null) {
14869                if (drawVerticalScrollBar) {
14870                    final Rect bounds = cache.mScrollBarBounds;
14871                    getVerticalScrollBarBounds(bounds);
14872                    mRoundScrollbarRenderer.drawRoundScrollbars(
14873                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
14874                    if (invalidate) {
14875                        invalidate();
14876                    }
14877                }
14878                // Do not draw horizontal scroll bars for round wearable devices.
14879            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14880                final ScrollBarDrawable scrollBar = cache.scrollBar;
14881
14882                if (drawHorizontalScrollBar) {
14883                    scrollBar.setParameters(computeHorizontalScrollRange(),
14884                            computeHorizontalScrollOffset(),
14885                            computeHorizontalScrollExtent(), false);
14886                    final Rect bounds = cache.mScrollBarBounds;
14887                    getHorizontalScrollBarBounds(bounds);
14888                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14889                            bounds.right, bounds.bottom);
14890                    if (invalidate) {
14891                        invalidate(bounds);
14892                    }
14893                }
14894
14895                if (drawVerticalScrollBar) {
14896                    scrollBar.setParameters(computeVerticalScrollRange(),
14897                            computeVerticalScrollOffset(),
14898                            computeVerticalScrollExtent(), true);
14899                    final Rect bounds = cache.mScrollBarBounds;
14900                    getVerticalScrollBarBounds(bounds);
14901                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14902                            bounds.right, bounds.bottom);
14903                    if (invalidate) {
14904                        invalidate(bounds);
14905                    }
14906                }
14907            }
14908        }
14909    }
14910
14911    /**
14912     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14913     * FastScroller is visible.
14914     * @return whether to temporarily hide the vertical scrollbar
14915     * @hide
14916     */
14917    protected boolean isVerticalScrollBarHidden() {
14918        return false;
14919    }
14920
14921    /**
14922     * <p>Draw the horizontal scrollbar if
14923     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14924     *
14925     * @param canvas the canvas on which to draw the scrollbar
14926     * @param scrollBar the scrollbar's drawable
14927     *
14928     * @see #isHorizontalScrollBarEnabled()
14929     * @see #computeHorizontalScrollRange()
14930     * @see #computeHorizontalScrollExtent()
14931     * @see #computeHorizontalScrollOffset()
14932     * @see android.widget.ScrollBarDrawable
14933     * @hide
14934     */
14935    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14936            int l, int t, int r, int b) {
14937        scrollBar.setBounds(l, t, r, b);
14938        scrollBar.draw(canvas);
14939    }
14940
14941    /**
14942     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14943     * returns true.</p>
14944     *
14945     * @param canvas the canvas on which to draw the scrollbar
14946     * @param scrollBar the scrollbar's drawable
14947     *
14948     * @see #isVerticalScrollBarEnabled()
14949     * @see #computeVerticalScrollRange()
14950     * @see #computeVerticalScrollExtent()
14951     * @see #computeVerticalScrollOffset()
14952     * @see android.widget.ScrollBarDrawable
14953     * @hide
14954     */
14955    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14956            int l, int t, int r, int b) {
14957        scrollBar.setBounds(l, t, r, b);
14958        scrollBar.draw(canvas);
14959    }
14960
14961    /**
14962     * Implement this to do your drawing.
14963     *
14964     * @param canvas the canvas on which the background will be drawn
14965     */
14966    protected void onDraw(Canvas canvas) {
14967    }
14968
14969    /*
14970     * Caller is responsible for calling requestLayout if necessary.
14971     * (This allows addViewInLayout to not request a new layout.)
14972     */
14973    void assignParent(ViewParent parent) {
14974        if (mParent == null) {
14975            mParent = parent;
14976        } else if (parent == null) {
14977            mParent = null;
14978        } else {
14979            throw new RuntimeException("view " + this + " being added, but"
14980                    + " it already has a parent");
14981        }
14982    }
14983
14984    /**
14985     * This is called when the view is attached to a window.  At this point it
14986     * has a Surface and will start drawing.  Note that this function is
14987     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14988     * however it may be called any time before the first onDraw -- including
14989     * before or after {@link #onMeasure(int, int)}.
14990     *
14991     * @see #onDetachedFromWindow()
14992     */
14993    @CallSuper
14994    protected void onAttachedToWindow() {
14995        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
14996            mParent.requestTransparentRegion(this);
14997        }
14998
14999        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15000
15001        jumpDrawablesToCurrentState();
15002
15003        resetSubtreeAccessibilityStateChanged();
15004
15005        // rebuild, since Outline not maintained while View is detached
15006        rebuildOutline();
15007
15008        if (isFocused()) {
15009            InputMethodManager imm = InputMethodManager.peekInstance();
15010            if (imm != null) {
15011                imm.focusIn(this);
15012            }
15013        }
15014    }
15015
15016    /**
15017     * Resolve all RTL related properties.
15018     *
15019     * @return true if resolution of RTL properties has been done
15020     *
15021     * @hide
15022     */
15023    public boolean resolveRtlPropertiesIfNeeded() {
15024        if (!needRtlPropertiesResolution()) return false;
15025
15026        // Order is important here: LayoutDirection MUST be resolved first
15027        if (!isLayoutDirectionResolved()) {
15028            resolveLayoutDirection();
15029            resolveLayoutParams();
15030        }
15031        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
15032        if (!isTextDirectionResolved()) {
15033            resolveTextDirection();
15034        }
15035        if (!isTextAlignmentResolved()) {
15036            resolveTextAlignment();
15037        }
15038        // Should resolve Drawables before Padding because we need the layout direction of the
15039        // Drawable to correctly resolve Padding.
15040        if (!areDrawablesResolved()) {
15041            resolveDrawables();
15042        }
15043        if (!isPaddingResolved()) {
15044            resolvePadding();
15045        }
15046        onRtlPropertiesChanged(getLayoutDirection());
15047        return true;
15048    }
15049
15050    /**
15051     * Reset resolution of all RTL related properties.
15052     *
15053     * @hide
15054     */
15055    public void resetRtlProperties() {
15056        resetResolvedLayoutDirection();
15057        resetResolvedTextDirection();
15058        resetResolvedTextAlignment();
15059        resetResolvedPadding();
15060        resetResolvedDrawables();
15061    }
15062
15063    /**
15064     * @see #onScreenStateChanged(int)
15065     */
15066    void dispatchScreenStateChanged(int screenState) {
15067        onScreenStateChanged(screenState);
15068    }
15069
15070    /**
15071     * This method is called whenever the state of the screen this view is
15072     * attached to changes. A state change will usually occurs when the screen
15073     * turns on or off (whether it happens automatically or the user does it
15074     * manually.)
15075     *
15076     * @param screenState The new state of the screen. Can be either
15077     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
15078     */
15079    public void onScreenStateChanged(int screenState) {
15080    }
15081
15082    /**
15083     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
15084     */
15085    private boolean hasRtlSupport() {
15086        return mContext.getApplicationInfo().hasRtlSupport();
15087    }
15088
15089    /**
15090     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
15091     * RTL not supported)
15092     */
15093    private boolean isRtlCompatibilityMode() {
15094        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
15095        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
15096    }
15097
15098    /**
15099     * @return true if RTL properties need resolution.
15100     *
15101     */
15102    private boolean needRtlPropertiesResolution() {
15103        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
15104    }
15105
15106    /**
15107     * Called when any RTL property (layout direction or text direction or text alignment) has
15108     * been changed.
15109     *
15110     * Subclasses need to override this method to take care of cached information that depends on the
15111     * resolved layout direction, or to inform child views that inherit their layout direction.
15112     *
15113     * The default implementation does nothing.
15114     *
15115     * @param layoutDirection the direction of the layout
15116     *
15117     * @see #LAYOUT_DIRECTION_LTR
15118     * @see #LAYOUT_DIRECTION_RTL
15119     */
15120    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
15121    }
15122
15123    /**
15124     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
15125     * that the parent directionality can and will be resolved before its children.
15126     *
15127     * @return true if resolution has been done, false otherwise.
15128     *
15129     * @hide
15130     */
15131    public boolean resolveLayoutDirection() {
15132        // Clear any previous layout direction resolution
15133        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15134
15135        if (hasRtlSupport()) {
15136            // Set resolved depending on layout direction
15137            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
15138                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
15139                case LAYOUT_DIRECTION_INHERIT:
15140                    // We cannot resolve yet. LTR is by default and let the resolution happen again
15141                    // later to get the correct resolved value
15142                    if (!canResolveLayoutDirection()) return false;
15143
15144                    // Parent has not yet resolved, LTR is still the default
15145                    try {
15146                        if (!mParent.isLayoutDirectionResolved()) return false;
15147
15148                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15149                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15150                        }
15151                    } catch (AbstractMethodError e) {
15152                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15153                                " does not fully implement ViewParent", e);
15154                    }
15155                    break;
15156                case LAYOUT_DIRECTION_RTL:
15157                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15158                    break;
15159                case LAYOUT_DIRECTION_LOCALE:
15160                    if((LAYOUT_DIRECTION_RTL ==
15161                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
15162                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15163                    }
15164                    break;
15165                default:
15166                    // Nothing to do, LTR by default
15167            }
15168        }
15169
15170        // Set to resolved
15171        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15172        return true;
15173    }
15174
15175    /**
15176     * Check if layout direction resolution can be done.
15177     *
15178     * @return true if layout direction resolution can be done otherwise return false.
15179     */
15180    public boolean canResolveLayoutDirection() {
15181        switch (getRawLayoutDirection()) {
15182            case LAYOUT_DIRECTION_INHERIT:
15183                if (mParent != null) {
15184                    try {
15185                        return mParent.canResolveLayoutDirection();
15186                    } catch (AbstractMethodError e) {
15187                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15188                                " does not fully implement ViewParent", e);
15189                    }
15190                }
15191                return false;
15192
15193            default:
15194                return true;
15195        }
15196    }
15197
15198    /**
15199     * Reset the resolved layout direction. Layout direction will be resolved during a call to
15200     * {@link #onMeasure(int, int)}.
15201     *
15202     * @hide
15203     */
15204    public void resetResolvedLayoutDirection() {
15205        // Reset the current resolved bits
15206        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15207    }
15208
15209    /**
15210     * @return true if the layout direction is inherited.
15211     *
15212     * @hide
15213     */
15214    public boolean isLayoutDirectionInherited() {
15215        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
15216    }
15217
15218    /**
15219     * @return true if layout direction has been resolved.
15220     */
15221    public boolean isLayoutDirectionResolved() {
15222        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15223    }
15224
15225    /**
15226     * Return if padding has been resolved
15227     *
15228     * @hide
15229     */
15230    boolean isPaddingResolved() {
15231        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
15232    }
15233
15234    /**
15235     * Resolves padding depending on layout direction, if applicable, and
15236     * recomputes internal padding values to adjust for scroll bars.
15237     *
15238     * @hide
15239     */
15240    public void resolvePadding() {
15241        final int resolvedLayoutDirection = getLayoutDirection();
15242
15243        if (!isRtlCompatibilityMode()) {
15244            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
15245            // If start / end padding are defined, they will be resolved (hence overriding) to
15246            // left / right or right / left depending on the resolved layout direction.
15247            // If start / end padding are not defined, use the left / right ones.
15248            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
15249                Rect padding = sThreadLocal.get();
15250                if (padding == null) {
15251                    padding = new Rect();
15252                    sThreadLocal.set(padding);
15253                }
15254                mBackground.getPadding(padding);
15255                if (!mLeftPaddingDefined) {
15256                    mUserPaddingLeftInitial = padding.left;
15257                }
15258                if (!mRightPaddingDefined) {
15259                    mUserPaddingRightInitial = padding.right;
15260                }
15261            }
15262            switch (resolvedLayoutDirection) {
15263                case LAYOUT_DIRECTION_RTL:
15264                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15265                        mUserPaddingRight = mUserPaddingStart;
15266                    } else {
15267                        mUserPaddingRight = mUserPaddingRightInitial;
15268                    }
15269                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15270                        mUserPaddingLeft = mUserPaddingEnd;
15271                    } else {
15272                        mUserPaddingLeft = mUserPaddingLeftInitial;
15273                    }
15274                    break;
15275                case LAYOUT_DIRECTION_LTR:
15276                default:
15277                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15278                        mUserPaddingLeft = mUserPaddingStart;
15279                    } else {
15280                        mUserPaddingLeft = mUserPaddingLeftInitial;
15281                    }
15282                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15283                        mUserPaddingRight = mUserPaddingEnd;
15284                    } else {
15285                        mUserPaddingRight = mUserPaddingRightInitial;
15286                    }
15287            }
15288
15289            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
15290        }
15291
15292        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15293        onRtlPropertiesChanged(resolvedLayoutDirection);
15294
15295        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
15296    }
15297
15298    /**
15299     * Reset the resolved layout direction.
15300     *
15301     * @hide
15302     */
15303    public void resetResolvedPadding() {
15304        resetResolvedPaddingInternal();
15305    }
15306
15307    /**
15308     * Used when we only want to reset *this* view's padding and not trigger overrides
15309     * in ViewGroup that reset children too.
15310     */
15311    void resetResolvedPaddingInternal() {
15312        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
15313    }
15314
15315    /**
15316     * This is called when the view is detached from a window.  At this point it
15317     * no longer has a surface for drawing.
15318     *
15319     * @see #onAttachedToWindow()
15320     */
15321    @CallSuper
15322    protected void onDetachedFromWindow() {
15323    }
15324
15325    /**
15326     * This is a framework-internal mirror of onDetachedFromWindow() that's called
15327     * after onDetachedFromWindow().
15328     *
15329     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
15330     * The super method should be called at the end of the overridden method to ensure
15331     * subclasses are destroyed first
15332     *
15333     * @hide
15334     */
15335    @CallSuper
15336    protected void onDetachedFromWindowInternal() {
15337        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
15338        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15339        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
15340
15341        removeUnsetPressCallback();
15342        removeLongPressCallback();
15343        removePerformClickCallback();
15344        removeSendViewScrolledAccessibilityEventCallback();
15345        stopNestedScroll();
15346
15347        // Anything that started animating right before detach should already
15348        // be in its final state when re-attached.
15349        jumpDrawablesToCurrentState();
15350
15351        destroyDrawingCache();
15352
15353        cleanupDraw();
15354        mCurrentAnimation = null;
15355    }
15356
15357    private void cleanupDraw() {
15358        resetDisplayList();
15359        if (mAttachInfo != null) {
15360            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
15361        }
15362    }
15363
15364    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
15365    }
15366
15367    /**
15368     * @return The number of times this view has been attached to a window
15369     */
15370    protected int getWindowAttachCount() {
15371        return mWindowAttachCount;
15372    }
15373
15374    /**
15375     * Retrieve a unique token identifying the window this view is attached to.
15376     * @return Return the window's token for use in
15377     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
15378     */
15379    public IBinder getWindowToken() {
15380        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
15381    }
15382
15383    /**
15384     * Retrieve the {@link WindowId} for the window this view is
15385     * currently attached to.
15386     */
15387    public WindowId getWindowId() {
15388        if (mAttachInfo == null) {
15389            return null;
15390        }
15391        if (mAttachInfo.mWindowId == null) {
15392            try {
15393                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
15394                        mAttachInfo.mWindowToken);
15395                mAttachInfo.mWindowId = new WindowId(
15396                        mAttachInfo.mIWindowId);
15397            } catch (RemoteException e) {
15398            }
15399        }
15400        return mAttachInfo.mWindowId;
15401    }
15402
15403    /**
15404     * Retrieve a unique token identifying the top-level "real" window of
15405     * the window that this view is attached to.  That is, this is like
15406     * {@link #getWindowToken}, except if the window this view in is a panel
15407     * window (attached to another containing window), then the token of
15408     * the containing window is returned instead.
15409     *
15410     * @return Returns the associated window token, either
15411     * {@link #getWindowToken()} or the containing window's token.
15412     */
15413    public IBinder getApplicationWindowToken() {
15414        AttachInfo ai = mAttachInfo;
15415        if (ai != null) {
15416            IBinder appWindowToken = ai.mPanelParentWindowToken;
15417            if (appWindowToken == null) {
15418                appWindowToken = ai.mWindowToken;
15419            }
15420            return appWindowToken;
15421        }
15422        return null;
15423    }
15424
15425    /**
15426     * Gets the logical display to which the view's window has been attached.
15427     *
15428     * @return The logical display, or null if the view is not currently attached to a window.
15429     */
15430    public Display getDisplay() {
15431        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
15432    }
15433
15434    /**
15435     * Retrieve private session object this view hierarchy is using to
15436     * communicate with the window manager.
15437     * @return the session object to communicate with the window manager
15438     */
15439    /*package*/ IWindowSession getWindowSession() {
15440        return mAttachInfo != null ? mAttachInfo.mSession : null;
15441    }
15442
15443    /**
15444     * Return the visibility value of the least visible component passed.
15445     */
15446    int combineVisibility(int vis1, int vis2) {
15447        // This works because VISIBLE < INVISIBLE < GONE.
15448        return Math.max(vis1, vis2);
15449    }
15450
15451    /**
15452     * @param info the {@link android.view.View.AttachInfo} to associated with
15453     *        this view
15454     */
15455    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
15456        mAttachInfo = info;
15457        if (mOverlay != null) {
15458            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
15459        }
15460        mWindowAttachCount++;
15461        // We will need to evaluate the drawable state at least once.
15462        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15463        if (mFloatingTreeObserver != null) {
15464            info.mTreeObserver.merge(mFloatingTreeObserver);
15465            mFloatingTreeObserver = null;
15466        }
15467
15468        registerPendingFrameMetricsObservers();
15469
15470        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
15471            mAttachInfo.mScrollContainers.add(this);
15472            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
15473        }
15474        // Transfer all pending runnables.
15475        if (mRunQueue != null) {
15476            mRunQueue.executeActions(info.mHandler);
15477            mRunQueue = null;
15478        }
15479        performCollectViewAttributes(mAttachInfo, visibility);
15480        onAttachedToWindow();
15481
15482        ListenerInfo li = mListenerInfo;
15483        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15484                li != null ? li.mOnAttachStateChangeListeners : null;
15485        if (listeners != null && listeners.size() > 0) {
15486            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15487            // perform the dispatching. The iterator is a safe guard against listeners that
15488            // could mutate the list by calling the various add/remove methods. This prevents
15489            // the array from being modified while we iterate it.
15490            for (OnAttachStateChangeListener listener : listeners) {
15491                listener.onViewAttachedToWindow(this);
15492            }
15493        }
15494
15495        int vis = info.mWindowVisibility;
15496        if (vis != GONE) {
15497            onWindowVisibilityChanged(vis);
15498            if (isShown()) {
15499                // Calling onVisibilityChanged directly here since the subtree will also
15500                // receive dispatchAttachedToWindow and this same call
15501                onVisibilityAggregated(vis == VISIBLE);
15502            }
15503        }
15504
15505        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
15506        // As all views in the subtree will already receive dispatchAttachedToWindow
15507        // traversing the subtree again here is not desired.
15508        onVisibilityChanged(this, visibility);
15509
15510        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
15511            // If nobody has evaluated the drawable state yet, then do it now.
15512            refreshDrawableState();
15513        }
15514        needGlobalAttributesUpdate(false);
15515    }
15516
15517    void dispatchDetachedFromWindow() {
15518        AttachInfo info = mAttachInfo;
15519        if (info != null) {
15520            int vis = info.mWindowVisibility;
15521            if (vis != GONE) {
15522                onWindowVisibilityChanged(GONE);
15523                if (isShown()) {
15524                    // Invoking onVisibilityAggregated directly here since the subtree
15525                    // will also receive detached from window
15526                    onVisibilityAggregated(false);
15527                }
15528            }
15529        }
15530
15531        onDetachedFromWindow();
15532        onDetachedFromWindowInternal();
15533
15534        InputMethodManager imm = InputMethodManager.peekInstance();
15535        if (imm != null) {
15536            imm.onViewDetachedFromWindow(this);
15537        }
15538
15539        ListenerInfo li = mListenerInfo;
15540        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15541                li != null ? li.mOnAttachStateChangeListeners : null;
15542        if (listeners != null && listeners.size() > 0) {
15543            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15544            // perform the dispatching. The iterator is a safe guard against listeners that
15545            // could mutate the list by calling the various add/remove methods. This prevents
15546            // the array from being modified while we iterate it.
15547            for (OnAttachStateChangeListener listener : listeners) {
15548                listener.onViewDetachedFromWindow(this);
15549            }
15550        }
15551
15552        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
15553            mAttachInfo.mScrollContainers.remove(this);
15554            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
15555        }
15556
15557        mAttachInfo = null;
15558        if (mOverlay != null) {
15559            mOverlay.getOverlayView().dispatchDetachedFromWindow();
15560        }
15561    }
15562
15563    /**
15564     * Cancel any deferred high-level input events that were previously posted to the event queue.
15565     *
15566     * <p>Many views post high-level events such as click handlers to the event queue
15567     * to run deferred in order to preserve a desired user experience - clearing visible
15568     * pressed states before executing, etc. This method will abort any events of this nature
15569     * that are currently in flight.</p>
15570     *
15571     * <p>Custom views that generate their own high-level deferred input events should override
15572     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
15573     *
15574     * <p>This will also cancel pending input events for any child views.</p>
15575     *
15576     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
15577     * This will not impact newer events posted after this call that may occur as a result of
15578     * lower-level input events still waiting in the queue. If you are trying to prevent
15579     * double-submitted  events for the duration of some sort of asynchronous transaction
15580     * you should also take other steps to protect against unexpected double inputs e.g. calling
15581     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
15582     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
15583     */
15584    public final void cancelPendingInputEvents() {
15585        dispatchCancelPendingInputEvents();
15586    }
15587
15588    /**
15589     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
15590     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
15591     */
15592    void dispatchCancelPendingInputEvents() {
15593        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
15594        onCancelPendingInputEvents();
15595        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
15596            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
15597                    " did not call through to super.onCancelPendingInputEvents()");
15598        }
15599    }
15600
15601    /**
15602     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
15603     * a parent view.
15604     *
15605     * <p>This method is responsible for removing any pending high-level input events that were
15606     * posted to the event queue to run later. Custom view classes that post their own deferred
15607     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
15608     * {@link android.os.Handler} should override this method, call
15609     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
15610     * </p>
15611     */
15612    public void onCancelPendingInputEvents() {
15613        removePerformClickCallback();
15614        cancelLongPress();
15615        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
15616    }
15617
15618    /**
15619     * Store this view hierarchy's frozen state into the given container.
15620     *
15621     * @param container The SparseArray in which to save the view's state.
15622     *
15623     * @see #restoreHierarchyState(android.util.SparseArray)
15624     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15625     * @see #onSaveInstanceState()
15626     */
15627    public void saveHierarchyState(SparseArray<Parcelable> container) {
15628        dispatchSaveInstanceState(container);
15629    }
15630
15631    /**
15632     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
15633     * this view and its children. May be overridden to modify how freezing happens to a
15634     * view's children; for example, some views may want to not store state for their children.
15635     *
15636     * @param container The SparseArray in which to save the view's state.
15637     *
15638     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15639     * @see #saveHierarchyState(android.util.SparseArray)
15640     * @see #onSaveInstanceState()
15641     */
15642    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
15643        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
15644            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15645            Parcelable state = onSaveInstanceState();
15646            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15647                throw new IllegalStateException(
15648                        "Derived class did not call super.onSaveInstanceState()");
15649            }
15650            if (state != null) {
15651                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
15652                // + ": " + state);
15653                container.put(mID, state);
15654            }
15655        }
15656    }
15657
15658    /**
15659     * Hook allowing a view to generate a representation of its internal state
15660     * that can later be used to create a new instance with that same state.
15661     * This state should only contain information that is not persistent or can
15662     * not be reconstructed later. For example, you will never store your
15663     * current position on screen because that will be computed again when a
15664     * new instance of the view is placed in its view hierarchy.
15665     * <p>
15666     * Some examples of things you may store here: the current cursor position
15667     * in a text view (but usually not the text itself since that is stored in a
15668     * content provider or other persistent storage), the currently selected
15669     * item in a list view.
15670     *
15671     * @return Returns a Parcelable object containing the view's current dynamic
15672     *         state, or null if there is nothing interesting to save. The
15673     *         default implementation returns null.
15674     * @see #onRestoreInstanceState(android.os.Parcelable)
15675     * @see #saveHierarchyState(android.util.SparseArray)
15676     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15677     * @see #setSaveEnabled(boolean)
15678     */
15679    @CallSuper
15680    protected Parcelable onSaveInstanceState() {
15681        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15682        if (mStartActivityRequestWho != null) {
15683            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
15684            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
15685            return state;
15686        }
15687        return BaseSavedState.EMPTY_STATE;
15688    }
15689
15690    /**
15691     * Restore this view hierarchy's frozen state from the given container.
15692     *
15693     * @param container The SparseArray which holds previously frozen states.
15694     *
15695     * @see #saveHierarchyState(android.util.SparseArray)
15696     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15697     * @see #onRestoreInstanceState(android.os.Parcelable)
15698     */
15699    public void restoreHierarchyState(SparseArray<Parcelable> container) {
15700        dispatchRestoreInstanceState(container);
15701    }
15702
15703    /**
15704     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
15705     * state for this view and its children. May be overridden to modify how restoring
15706     * happens to a view's children; for example, some views may want to not store state
15707     * for their children.
15708     *
15709     * @param container The SparseArray which holds previously saved state.
15710     *
15711     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15712     * @see #restoreHierarchyState(android.util.SparseArray)
15713     * @see #onRestoreInstanceState(android.os.Parcelable)
15714     */
15715    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
15716        if (mID != NO_ID) {
15717            Parcelable state = container.get(mID);
15718            if (state != null) {
15719                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
15720                // + ": " + state);
15721                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15722                onRestoreInstanceState(state);
15723                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15724                    throw new IllegalStateException(
15725                            "Derived class did not call super.onRestoreInstanceState()");
15726                }
15727            }
15728        }
15729    }
15730
15731    /**
15732     * Hook allowing a view to re-apply a representation of its internal state that had previously
15733     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
15734     * null state.
15735     *
15736     * @param state The frozen state that had previously been returned by
15737     *        {@link #onSaveInstanceState}.
15738     *
15739     * @see #onSaveInstanceState()
15740     * @see #restoreHierarchyState(android.util.SparseArray)
15741     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15742     */
15743    @CallSuper
15744    protected void onRestoreInstanceState(Parcelable state) {
15745        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15746        if (state != null && !(state instanceof AbsSavedState)) {
15747            throw new IllegalArgumentException("Wrong state class, expecting View State but "
15748                    + "received " + state.getClass().toString() + " instead. This usually happens "
15749                    + "when two views of different type have the same id in the same hierarchy. "
15750                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
15751                    + "other views do not use the same id.");
15752        }
15753        if (state != null && state instanceof BaseSavedState) {
15754            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
15755        }
15756    }
15757
15758    /**
15759     * <p>Return the time at which the drawing of the view hierarchy started.</p>
15760     *
15761     * @return the drawing start time in milliseconds
15762     */
15763    public long getDrawingTime() {
15764        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
15765    }
15766
15767    /**
15768     * <p>Enables or disables the duplication of the parent's state into this view. When
15769     * duplication is enabled, this view gets its drawable state from its parent rather
15770     * than from its own internal properties.</p>
15771     *
15772     * <p>Note: in the current implementation, setting this property to true after the
15773     * view was added to a ViewGroup might have no effect at all. This property should
15774     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
15775     *
15776     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
15777     * property is enabled, an exception will be thrown.</p>
15778     *
15779     * <p>Note: if the child view uses and updates additional states which are unknown to the
15780     * parent, these states should not be affected by this method.</p>
15781     *
15782     * @param enabled True to enable duplication of the parent's drawable state, false
15783     *                to disable it.
15784     *
15785     * @see #getDrawableState()
15786     * @see #isDuplicateParentStateEnabled()
15787     */
15788    public void setDuplicateParentStateEnabled(boolean enabled) {
15789        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
15790    }
15791
15792    /**
15793     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
15794     *
15795     * @return True if this view's drawable state is duplicated from the parent,
15796     *         false otherwise
15797     *
15798     * @see #getDrawableState()
15799     * @see #setDuplicateParentStateEnabled(boolean)
15800     */
15801    public boolean isDuplicateParentStateEnabled() {
15802        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
15803    }
15804
15805    /**
15806     * <p>Specifies the type of layer backing this view. The layer can be
15807     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15808     * {@link #LAYER_TYPE_HARDWARE}.</p>
15809     *
15810     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15811     * instance that controls how the layer is composed on screen. The following
15812     * properties of the paint are taken into account when composing the layer:</p>
15813     * <ul>
15814     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15815     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15816     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15817     * </ul>
15818     *
15819     * <p>If this view has an alpha value set to < 1.0 by calling
15820     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
15821     * by this view's alpha value.</p>
15822     *
15823     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
15824     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
15825     * for more information on when and how to use layers.</p>
15826     *
15827     * @param layerType The type of layer to use with this view, must be one of
15828     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15829     *        {@link #LAYER_TYPE_HARDWARE}
15830     * @param paint The paint used to compose the layer. This argument is optional
15831     *        and can be null. It is ignored when the layer type is
15832     *        {@link #LAYER_TYPE_NONE}
15833     *
15834     * @see #getLayerType()
15835     * @see #LAYER_TYPE_NONE
15836     * @see #LAYER_TYPE_SOFTWARE
15837     * @see #LAYER_TYPE_HARDWARE
15838     * @see #setAlpha(float)
15839     *
15840     * @attr ref android.R.styleable#View_layerType
15841     */
15842    public void setLayerType(int layerType, @Nullable Paint paint) {
15843        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15844            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15845                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15846        }
15847
15848        boolean typeChanged = mRenderNode.setLayerType(layerType);
15849
15850        if (!typeChanged) {
15851            setLayerPaint(paint);
15852            return;
15853        }
15854
15855        if (layerType != LAYER_TYPE_SOFTWARE) {
15856            // Destroy any previous software drawing cache if present
15857            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
15858            // drawing cache created in View#draw when drawing to a SW canvas.
15859            destroyDrawingCache();
15860        }
15861
15862        mLayerType = layerType;
15863        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
15864        mRenderNode.setLayerPaint(mLayerPaint);
15865
15866        // draw() behaves differently if we are on a layer, so we need to
15867        // invalidate() here
15868        invalidateParentCaches();
15869        invalidate(true);
15870    }
15871
15872    /**
15873     * Updates the {@link Paint} object used with the current layer (used only if the current
15874     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15875     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15876     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15877     * ensure that the view gets redrawn immediately.
15878     *
15879     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15880     * instance that controls how the layer is composed on screen. The following
15881     * properties of the paint are taken into account when composing the layer:</p>
15882     * <ul>
15883     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15884     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15885     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15886     * </ul>
15887     *
15888     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15889     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15890     *
15891     * @param paint The paint used to compose the layer. This argument is optional
15892     *        and can be null. It is ignored when the layer type is
15893     *        {@link #LAYER_TYPE_NONE}
15894     *
15895     * @see #setLayerType(int, android.graphics.Paint)
15896     */
15897    public void setLayerPaint(@Nullable Paint paint) {
15898        int layerType = getLayerType();
15899        if (layerType != LAYER_TYPE_NONE) {
15900            mLayerPaint = paint;
15901            if (layerType == LAYER_TYPE_HARDWARE) {
15902                if (mRenderNode.setLayerPaint(paint)) {
15903                    invalidateViewProperty(false, false);
15904                }
15905            } else {
15906                invalidate();
15907            }
15908        }
15909    }
15910
15911    /**
15912     * Indicates what type of layer is currently associated with this view. By default
15913     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15914     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15915     * for more information on the different types of layers.
15916     *
15917     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15918     *         {@link #LAYER_TYPE_HARDWARE}
15919     *
15920     * @see #setLayerType(int, android.graphics.Paint)
15921     * @see #buildLayer()
15922     * @see #LAYER_TYPE_NONE
15923     * @see #LAYER_TYPE_SOFTWARE
15924     * @see #LAYER_TYPE_HARDWARE
15925     */
15926    public int getLayerType() {
15927        return mLayerType;
15928    }
15929
15930    /**
15931     * Forces this view's layer to be created and this view to be rendered
15932     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15933     * invoking this method will have no effect.
15934     *
15935     * This method can for instance be used to render a view into its layer before
15936     * starting an animation. If this view is complex, rendering into the layer
15937     * before starting the animation will avoid skipping frames.
15938     *
15939     * @throws IllegalStateException If this view is not attached to a window
15940     *
15941     * @see #setLayerType(int, android.graphics.Paint)
15942     */
15943    public void buildLayer() {
15944        if (mLayerType == LAYER_TYPE_NONE) return;
15945
15946        final AttachInfo attachInfo = mAttachInfo;
15947        if (attachInfo == null) {
15948            throw new IllegalStateException("This view must be attached to a window first");
15949        }
15950
15951        if (getWidth() == 0 || getHeight() == 0) {
15952            return;
15953        }
15954
15955        switch (mLayerType) {
15956            case LAYER_TYPE_HARDWARE:
15957                updateDisplayListIfDirty();
15958                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
15959                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
15960                }
15961                break;
15962            case LAYER_TYPE_SOFTWARE:
15963                buildDrawingCache(true);
15964                break;
15965        }
15966    }
15967
15968    /**
15969     * Destroys all hardware rendering resources. This method is invoked
15970     * when the system needs to reclaim resources. Upon execution of this
15971     * method, you should free any OpenGL resources created by the view.
15972     *
15973     * Note: you <strong>must</strong> call
15974     * <code>super.destroyHardwareResources()</code> when overriding
15975     * this method.
15976     *
15977     * @hide
15978     */
15979    @CallSuper
15980    protected void destroyHardwareResources() {
15981        // Although the Layer will be destroyed by RenderNode, we want to release
15982        // the staging display list, which is also a signal to RenderNode that it's
15983        // safe to free its copy of the display list as it knows that we will
15984        // push an updated DisplayList if we try to draw again
15985        resetDisplayList();
15986    }
15987
15988    /**
15989     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
15990     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
15991     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
15992     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
15993     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
15994     * null.</p>
15995     *
15996     * <p>Enabling the drawing cache is similar to
15997     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
15998     * acceleration is turned off. When hardware acceleration is turned on, enabling the
15999     * drawing cache has no effect on rendering because the system uses a different mechanism
16000     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
16001     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
16002     * for information on how to enable software and hardware layers.</p>
16003     *
16004     * <p>This API can be used to manually generate
16005     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
16006     * {@link #getDrawingCache()}.</p>
16007     *
16008     * @param enabled true to enable the drawing cache, false otherwise
16009     *
16010     * @see #isDrawingCacheEnabled()
16011     * @see #getDrawingCache()
16012     * @see #buildDrawingCache()
16013     * @see #setLayerType(int, android.graphics.Paint)
16014     */
16015    public void setDrawingCacheEnabled(boolean enabled) {
16016        mCachingFailed = false;
16017        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
16018    }
16019
16020    /**
16021     * <p>Indicates whether the drawing cache is enabled for this view.</p>
16022     *
16023     * @return true if the drawing cache is enabled
16024     *
16025     * @see #setDrawingCacheEnabled(boolean)
16026     * @see #getDrawingCache()
16027     */
16028    @ViewDebug.ExportedProperty(category = "drawing")
16029    public boolean isDrawingCacheEnabled() {
16030        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
16031    }
16032
16033    /**
16034     * Debugging utility which recursively outputs the dirty state of a view and its
16035     * descendants.
16036     *
16037     * @hide
16038     */
16039    @SuppressWarnings({"UnusedDeclaration"})
16040    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
16041        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
16042                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
16043                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
16044                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
16045        if (clear) {
16046            mPrivateFlags &= clearMask;
16047        }
16048        if (this instanceof ViewGroup) {
16049            ViewGroup parent = (ViewGroup) this;
16050            final int count = parent.getChildCount();
16051            for (int i = 0; i < count; i++) {
16052                final View child = parent.getChildAt(i);
16053                child.outputDirtyFlags(indent + "  ", clear, clearMask);
16054            }
16055        }
16056    }
16057
16058    /**
16059     * This method is used by ViewGroup to cause its children to restore or recreate their
16060     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
16061     * to recreate its own display list, which would happen if it went through the normal
16062     * draw/dispatchDraw mechanisms.
16063     *
16064     * @hide
16065     */
16066    protected void dispatchGetDisplayList() {}
16067
16068    /**
16069     * A view that is not attached or hardware accelerated cannot create a display list.
16070     * This method checks these conditions and returns the appropriate result.
16071     *
16072     * @return true if view has the ability to create a display list, false otherwise.
16073     *
16074     * @hide
16075     */
16076    public boolean canHaveDisplayList() {
16077        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
16078    }
16079
16080    /**
16081     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
16082     * @hide
16083     */
16084    @NonNull
16085    public RenderNode updateDisplayListIfDirty() {
16086        final RenderNode renderNode = mRenderNode;
16087        if (!canHaveDisplayList()) {
16088            // can't populate RenderNode, don't try
16089            return renderNode;
16090        }
16091
16092        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
16093                || !renderNode.isValid()
16094                || (mRecreateDisplayList)) {
16095            // Don't need to recreate the display list, just need to tell our
16096            // children to restore/recreate theirs
16097            if (renderNode.isValid()
16098                    && !mRecreateDisplayList) {
16099                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16100                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16101                dispatchGetDisplayList();
16102
16103                return renderNode; // no work needed
16104            }
16105
16106            // If we got here, we're recreating it. Mark it as such to ensure that
16107            // we copy in child display lists into ours in drawChild()
16108            mRecreateDisplayList = true;
16109
16110            int width = mRight - mLeft;
16111            int height = mBottom - mTop;
16112            int layerType = getLayerType();
16113
16114            final DisplayListCanvas canvas = renderNode.start(width, height);
16115            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
16116
16117            try {
16118                if (layerType == LAYER_TYPE_SOFTWARE) {
16119                    buildDrawingCache(true);
16120                    Bitmap cache = getDrawingCache(true);
16121                    if (cache != null) {
16122                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
16123                    }
16124                } else {
16125                    computeScroll();
16126
16127                    canvas.translate(-mScrollX, -mScrollY);
16128                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16129                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16130
16131                    // Fast path for layouts with no backgrounds
16132                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16133                        dispatchDraw(canvas);
16134                        if (mOverlay != null && !mOverlay.isEmpty()) {
16135                            mOverlay.getOverlayView().draw(canvas);
16136                        }
16137                    } else {
16138                        draw(canvas);
16139                    }
16140                }
16141            } finally {
16142                renderNode.end(canvas);
16143                setDisplayListProperties(renderNode);
16144            }
16145        } else {
16146            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16147            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16148        }
16149        return renderNode;
16150    }
16151
16152    private void resetDisplayList() {
16153        if (mRenderNode.isValid()) {
16154            mRenderNode.discardDisplayList();
16155        }
16156
16157        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
16158            mBackgroundRenderNode.discardDisplayList();
16159        }
16160    }
16161
16162    /**
16163     * Called when the passed RenderNode is removed from the draw tree
16164     * @hide
16165     */
16166    public void onRenderNodeDetached(RenderNode renderNode) {
16167    }
16168
16169    /**
16170     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
16171     *
16172     * @return A non-scaled bitmap representing this view or null if cache is disabled.
16173     *
16174     * @see #getDrawingCache(boolean)
16175     */
16176    public Bitmap getDrawingCache() {
16177        return getDrawingCache(false);
16178    }
16179
16180    /**
16181     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
16182     * is null when caching is disabled. If caching is enabled and the cache is not ready,
16183     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
16184     * draw from the cache when the cache is enabled. To benefit from the cache, you must
16185     * request the drawing cache by calling this method and draw it on screen if the
16186     * returned bitmap is not null.</p>
16187     *
16188     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16189     * this method will create a bitmap of the same size as this view. Because this bitmap
16190     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16191     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16192     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16193     * size than the view. This implies that your application must be able to handle this
16194     * size.</p>
16195     *
16196     * @param autoScale Indicates whether the generated bitmap should be scaled based on
16197     *        the current density of the screen when the application is in compatibility
16198     *        mode.
16199     *
16200     * @return A bitmap representing this view or null if cache is disabled.
16201     *
16202     * @see #setDrawingCacheEnabled(boolean)
16203     * @see #isDrawingCacheEnabled()
16204     * @see #buildDrawingCache(boolean)
16205     * @see #destroyDrawingCache()
16206     */
16207    public Bitmap getDrawingCache(boolean autoScale) {
16208        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
16209            return null;
16210        }
16211        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
16212            buildDrawingCache(autoScale);
16213        }
16214        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
16215    }
16216
16217    /**
16218     * <p>Frees the resources used by the drawing cache. If you call
16219     * {@link #buildDrawingCache()} manually without calling
16220     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16221     * should cleanup the cache with this method afterwards.</p>
16222     *
16223     * @see #setDrawingCacheEnabled(boolean)
16224     * @see #buildDrawingCache()
16225     * @see #getDrawingCache()
16226     */
16227    public void destroyDrawingCache() {
16228        if (mDrawingCache != null) {
16229            mDrawingCache.recycle();
16230            mDrawingCache = null;
16231        }
16232        if (mUnscaledDrawingCache != null) {
16233            mUnscaledDrawingCache.recycle();
16234            mUnscaledDrawingCache = null;
16235        }
16236    }
16237
16238    /**
16239     * Setting a solid background color for the drawing cache's bitmaps will improve
16240     * performance and memory usage. Note, though that this should only be used if this
16241     * view will always be drawn on top of a solid color.
16242     *
16243     * @param color The background color to use for the drawing cache's bitmap
16244     *
16245     * @see #setDrawingCacheEnabled(boolean)
16246     * @see #buildDrawingCache()
16247     * @see #getDrawingCache()
16248     */
16249    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
16250        if (color != mDrawingCacheBackgroundColor) {
16251            mDrawingCacheBackgroundColor = color;
16252            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16253        }
16254    }
16255
16256    /**
16257     * @see #setDrawingCacheBackgroundColor(int)
16258     *
16259     * @return The background color to used for the drawing cache's bitmap
16260     */
16261    @ColorInt
16262    public int getDrawingCacheBackgroundColor() {
16263        return mDrawingCacheBackgroundColor;
16264    }
16265
16266    /**
16267     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
16268     *
16269     * @see #buildDrawingCache(boolean)
16270     */
16271    public void buildDrawingCache() {
16272        buildDrawingCache(false);
16273    }
16274
16275    /**
16276     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
16277     *
16278     * <p>If you call {@link #buildDrawingCache()} manually without calling
16279     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16280     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
16281     *
16282     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16283     * this method will create a bitmap of the same size as this view. Because this bitmap
16284     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16285     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16286     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16287     * size than the view. This implies that your application must be able to handle this
16288     * size.</p>
16289     *
16290     * <p>You should avoid calling this method when hardware acceleration is enabled. If
16291     * you do not need the drawing cache bitmap, calling this method will increase memory
16292     * usage and cause the view to be rendered in software once, thus negatively impacting
16293     * performance.</p>
16294     *
16295     * @see #getDrawingCache()
16296     * @see #destroyDrawingCache()
16297     */
16298    public void buildDrawingCache(boolean autoScale) {
16299        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
16300                mDrawingCache == null : mUnscaledDrawingCache == null)) {
16301            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
16302                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
16303                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
16304            }
16305            try {
16306                buildDrawingCacheImpl(autoScale);
16307            } finally {
16308                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
16309            }
16310        }
16311    }
16312
16313    /**
16314     * private, internal implementation of buildDrawingCache, used to enable tracing
16315     */
16316    private void buildDrawingCacheImpl(boolean autoScale) {
16317        mCachingFailed = false;
16318
16319        int width = mRight - mLeft;
16320        int height = mBottom - mTop;
16321
16322        final AttachInfo attachInfo = mAttachInfo;
16323        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
16324
16325        if (autoScale && scalingRequired) {
16326            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
16327            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
16328        }
16329
16330        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
16331        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
16332        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
16333
16334        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
16335        final long drawingCacheSize =
16336                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
16337        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
16338            if (width > 0 && height > 0) {
16339                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
16340                        + " too large to fit into a software layer (or drawing cache), needs "
16341                        + projectedBitmapSize + " bytes, only "
16342                        + drawingCacheSize + " available");
16343            }
16344            destroyDrawingCache();
16345            mCachingFailed = true;
16346            return;
16347        }
16348
16349        boolean clear = true;
16350        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
16351
16352        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
16353            Bitmap.Config quality;
16354            if (!opaque) {
16355                // Never pick ARGB_4444 because it looks awful
16356                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
16357                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
16358                    case DRAWING_CACHE_QUALITY_AUTO:
16359                    case DRAWING_CACHE_QUALITY_LOW:
16360                    case DRAWING_CACHE_QUALITY_HIGH:
16361                    default:
16362                        quality = Bitmap.Config.ARGB_8888;
16363                        break;
16364                }
16365            } else {
16366                // Optimization for translucent windows
16367                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
16368                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
16369            }
16370
16371            // Try to cleanup memory
16372            if (bitmap != null) bitmap.recycle();
16373
16374            try {
16375                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16376                        width, height, quality);
16377                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
16378                if (autoScale) {
16379                    mDrawingCache = bitmap;
16380                } else {
16381                    mUnscaledDrawingCache = bitmap;
16382                }
16383                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
16384            } catch (OutOfMemoryError e) {
16385                // If there is not enough memory to create the bitmap cache, just
16386                // ignore the issue as bitmap caches are not required to draw the
16387                // view hierarchy
16388                if (autoScale) {
16389                    mDrawingCache = null;
16390                } else {
16391                    mUnscaledDrawingCache = null;
16392                }
16393                mCachingFailed = true;
16394                return;
16395            }
16396
16397            clear = drawingCacheBackgroundColor != 0;
16398        }
16399
16400        Canvas canvas;
16401        if (attachInfo != null) {
16402            canvas = attachInfo.mCanvas;
16403            if (canvas == null) {
16404                canvas = new Canvas();
16405            }
16406            canvas.setBitmap(bitmap);
16407            // Temporarily clobber the cached Canvas in case one of our children
16408            // is also using a drawing cache. Without this, the children would
16409            // steal the canvas by attaching their own bitmap to it and bad, bad
16410            // thing would happen (invisible views, corrupted drawings, etc.)
16411            attachInfo.mCanvas = null;
16412        } else {
16413            // This case should hopefully never or seldom happen
16414            canvas = new Canvas(bitmap);
16415        }
16416
16417        if (clear) {
16418            bitmap.eraseColor(drawingCacheBackgroundColor);
16419        }
16420
16421        computeScroll();
16422        final int restoreCount = canvas.save();
16423
16424        if (autoScale && scalingRequired) {
16425            final float scale = attachInfo.mApplicationScale;
16426            canvas.scale(scale, scale);
16427        }
16428
16429        canvas.translate(-mScrollX, -mScrollY);
16430
16431        mPrivateFlags |= PFLAG_DRAWN;
16432        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
16433                mLayerType != LAYER_TYPE_NONE) {
16434            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
16435        }
16436
16437        // Fast path for layouts with no backgrounds
16438        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16439            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16440            dispatchDraw(canvas);
16441            if (mOverlay != null && !mOverlay.isEmpty()) {
16442                mOverlay.getOverlayView().draw(canvas);
16443            }
16444        } else {
16445            draw(canvas);
16446        }
16447
16448        canvas.restoreToCount(restoreCount);
16449        canvas.setBitmap(null);
16450
16451        if (attachInfo != null) {
16452            // Restore the cached Canvas for our siblings
16453            attachInfo.mCanvas = canvas;
16454        }
16455    }
16456
16457    /**
16458     * Create a snapshot of the view into a bitmap.  We should probably make
16459     * some form of this public, but should think about the API.
16460     *
16461     * @hide
16462     */
16463    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
16464        int width = mRight - mLeft;
16465        int height = mBottom - mTop;
16466
16467        final AttachInfo attachInfo = mAttachInfo;
16468        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
16469        width = (int) ((width * scale) + 0.5f);
16470        height = (int) ((height * scale) + 0.5f);
16471
16472        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16473                width > 0 ? width : 1, height > 0 ? height : 1, quality);
16474        if (bitmap == null) {
16475            throw new OutOfMemoryError();
16476        }
16477
16478        Resources resources = getResources();
16479        if (resources != null) {
16480            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
16481        }
16482
16483        Canvas canvas;
16484        if (attachInfo != null) {
16485            canvas = attachInfo.mCanvas;
16486            if (canvas == null) {
16487                canvas = new Canvas();
16488            }
16489            canvas.setBitmap(bitmap);
16490            // Temporarily clobber the cached Canvas in case one of our children
16491            // is also using a drawing cache. Without this, the children would
16492            // steal the canvas by attaching their own bitmap to it and bad, bad
16493            // things would happen (invisible views, corrupted drawings, etc.)
16494            attachInfo.mCanvas = null;
16495        } else {
16496            // This case should hopefully never or seldom happen
16497            canvas = new Canvas(bitmap);
16498        }
16499
16500        if ((backgroundColor & 0xff000000) != 0) {
16501            bitmap.eraseColor(backgroundColor);
16502        }
16503
16504        computeScroll();
16505        final int restoreCount = canvas.save();
16506        canvas.scale(scale, scale);
16507        canvas.translate(-mScrollX, -mScrollY);
16508
16509        // Temporarily remove the dirty mask
16510        int flags = mPrivateFlags;
16511        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16512
16513        // Fast path for layouts with no backgrounds
16514        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16515            dispatchDraw(canvas);
16516            if (mOverlay != null && !mOverlay.isEmpty()) {
16517                mOverlay.getOverlayView().draw(canvas);
16518            }
16519        } else {
16520            draw(canvas);
16521        }
16522
16523        mPrivateFlags = flags;
16524
16525        canvas.restoreToCount(restoreCount);
16526        canvas.setBitmap(null);
16527
16528        if (attachInfo != null) {
16529            // Restore the cached Canvas for our siblings
16530            attachInfo.mCanvas = canvas;
16531        }
16532
16533        return bitmap;
16534    }
16535
16536    /**
16537     * Indicates whether this View is currently in edit mode. A View is usually
16538     * in edit mode when displayed within a developer tool. For instance, if
16539     * this View is being drawn by a visual user interface builder, this method
16540     * should return true.
16541     *
16542     * Subclasses should check the return value of this method to provide
16543     * different behaviors if their normal behavior might interfere with the
16544     * host environment. For instance: the class spawns a thread in its
16545     * constructor, the drawing code relies on device-specific features, etc.
16546     *
16547     * This method is usually checked in the drawing code of custom widgets.
16548     *
16549     * @return True if this View is in edit mode, false otherwise.
16550     */
16551    public boolean isInEditMode() {
16552        return false;
16553    }
16554
16555    /**
16556     * If the View draws content inside its padding and enables fading edges,
16557     * it needs to support padding offsets. Padding offsets are added to the
16558     * fading edges to extend the length of the fade so that it covers pixels
16559     * drawn inside the padding.
16560     *
16561     * Subclasses of this class should override this method if they need
16562     * to draw content inside the padding.
16563     *
16564     * @return True if padding offset must be applied, false otherwise.
16565     *
16566     * @see #getLeftPaddingOffset()
16567     * @see #getRightPaddingOffset()
16568     * @see #getTopPaddingOffset()
16569     * @see #getBottomPaddingOffset()
16570     *
16571     * @since CURRENT
16572     */
16573    protected boolean isPaddingOffsetRequired() {
16574        return false;
16575    }
16576
16577    /**
16578     * Amount by which to extend the left fading region. Called only when
16579     * {@link #isPaddingOffsetRequired()} returns true.
16580     *
16581     * @return The left padding offset in pixels.
16582     *
16583     * @see #isPaddingOffsetRequired()
16584     *
16585     * @since CURRENT
16586     */
16587    protected int getLeftPaddingOffset() {
16588        return 0;
16589    }
16590
16591    /**
16592     * Amount by which to extend the right fading region. Called only when
16593     * {@link #isPaddingOffsetRequired()} returns true.
16594     *
16595     * @return The right padding offset in pixels.
16596     *
16597     * @see #isPaddingOffsetRequired()
16598     *
16599     * @since CURRENT
16600     */
16601    protected int getRightPaddingOffset() {
16602        return 0;
16603    }
16604
16605    /**
16606     * Amount by which to extend the top fading region. Called only when
16607     * {@link #isPaddingOffsetRequired()} returns true.
16608     *
16609     * @return The top padding offset in pixels.
16610     *
16611     * @see #isPaddingOffsetRequired()
16612     *
16613     * @since CURRENT
16614     */
16615    protected int getTopPaddingOffset() {
16616        return 0;
16617    }
16618
16619    /**
16620     * Amount by which to extend the bottom fading region. Called only when
16621     * {@link #isPaddingOffsetRequired()} returns true.
16622     *
16623     * @return The bottom padding offset in pixels.
16624     *
16625     * @see #isPaddingOffsetRequired()
16626     *
16627     * @since CURRENT
16628     */
16629    protected int getBottomPaddingOffset() {
16630        return 0;
16631    }
16632
16633    /**
16634     * @hide
16635     * @param offsetRequired
16636     */
16637    protected int getFadeTop(boolean offsetRequired) {
16638        int top = mPaddingTop;
16639        if (offsetRequired) top += getTopPaddingOffset();
16640        return top;
16641    }
16642
16643    /**
16644     * @hide
16645     * @param offsetRequired
16646     */
16647    protected int getFadeHeight(boolean offsetRequired) {
16648        int padding = mPaddingTop;
16649        if (offsetRequired) padding += getTopPaddingOffset();
16650        return mBottom - mTop - mPaddingBottom - padding;
16651    }
16652
16653    /**
16654     * <p>Indicates whether this view is attached to a hardware accelerated
16655     * window or not.</p>
16656     *
16657     * <p>Even if this method returns true, it does not mean that every call
16658     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
16659     * accelerated {@link android.graphics.Canvas}. For instance, if this view
16660     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
16661     * window is hardware accelerated,
16662     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
16663     * return false, and this method will return true.</p>
16664     *
16665     * @return True if the view is attached to a window and the window is
16666     *         hardware accelerated; false in any other case.
16667     */
16668    @ViewDebug.ExportedProperty(category = "drawing")
16669    public boolean isHardwareAccelerated() {
16670        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
16671    }
16672
16673    /**
16674     * Sets a rectangular area on this view to which the view will be clipped
16675     * when it is drawn. Setting the value to null will remove the clip bounds
16676     * and the view will draw normally, using its full bounds.
16677     *
16678     * @param clipBounds The rectangular area, in the local coordinates of
16679     * this view, to which future drawing operations will be clipped.
16680     */
16681    public void setClipBounds(Rect clipBounds) {
16682        if (clipBounds == mClipBounds
16683                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
16684            return;
16685        }
16686        if (clipBounds != null) {
16687            if (mClipBounds == null) {
16688                mClipBounds = new Rect(clipBounds);
16689            } else {
16690                mClipBounds.set(clipBounds);
16691            }
16692        } else {
16693            mClipBounds = null;
16694        }
16695        mRenderNode.setClipBounds(mClipBounds);
16696        invalidateViewProperty(false, false);
16697    }
16698
16699    /**
16700     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
16701     *
16702     * @return A copy of the current clip bounds if clip bounds are set,
16703     * otherwise null.
16704     */
16705    public Rect getClipBounds() {
16706        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
16707    }
16708
16709
16710    /**
16711     * Populates an output rectangle with the clip bounds of the view,
16712     * returning {@code true} if successful or {@code false} if the view's
16713     * clip bounds are {@code null}.
16714     *
16715     * @param outRect rectangle in which to place the clip bounds of the view
16716     * @return {@code true} if successful or {@code false} if the view's
16717     *         clip bounds are {@code null}
16718     */
16719    public boolean getClipBounds(Rect outRect) {
16720        if (mClipBounds != null) {
16721            outRect.set(mClipBounds);
16722            return true;
16723        }
16724        return false;
16725    }
16726
16727    /**
16728     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
16729     * case of an active Animation being run on the view.
16730     */
16731    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
16732            Animation a, boolean scalingRequired) {
16733        Transformation invalidationTransform;
16734        final int flags = parent.mGroupFlags;
16735        final boolean initialized = a.isInitialized();
16736        if (!initialized) {
16737            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
16738            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
16739            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
16740            onAnimationStart();
16741        }
16742
16743        final Transformation t = parent.getChildTransformation();
16744        boolean more = a.getTransformation(drawingTime, t, 1f);
16745        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
16746            if (parent.mInvalidationTransformation == null) {
16747                parent.mInvalidationTransformation = new Transformation();
16748            }
16749            invalidationTransform = parent.mInvalidationTransformation;
16750            a.getTransformation(drawingTime, invalidationTransform, 1f);
16751        } else {
16752            invalidationTransform = t;
16753        }
16754
16755        if (more) {
16756            if (!a.willChangeBounds()) {
16757                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
16758                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
16759                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
16760                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
16761                    // The child need to draw an animation, potentially offscreen, so
16762                    // make sure we do not cancel invalidate requests
16763                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16764                    parent.invalidate(mLeft, mTop, mRight, mBottom);
16765                }
16766            } else {
16767                if (parent.mInvalidateRegion == null) {
16768                    parent.mInvalidateRegion = new RectF();
16769                }
16770                final RectF region = parent.mInvalidateRegion;
16771                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
16772                        invalidationTransform);
16773
16774                // The child need to draw an animation, potentially offscreen, so
16775                // make sure we do not cancel invalidate requests
16776                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16777
16778                final int left = mLeft + (int) region.left;
16779                final int top = mTop + (int) region.top;
16780                parent.invalidate(left, top, left + (int) (region.width() + .5f),
16781                        top + (int) (region.height() + .5f));
16782            }
16783        }
16784        return more;
16785    }
16786
16787    /**
16788     * This method is called by getDisplayList() when a display list is recorded for a View.
16789     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
16790     */
16791    void setDisplayListProperties(RenderNode renderNode) {
16792        if (renderNode != null) {
16793            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
16794            renderNode.setClipToBounds(mParent instanceof ViewGroup
16795                    && ((ViewGroup) mParent).getClipChildren());
16796
16797            float alpha = 1;
16798            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
16799                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16800                ViewGroup parentVG = (ViewGroup) mParent;
16801                final Transformation t = parentVG.getChildTransformation();
16802                if (parentVG.getChildStaticTransformation(this, t)) {
16803                    final int transformType = t.getTransformationType();
16804                    if (transformType != Transformation.TYPE_IDENTITY) {
16805                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
16806                            alpha = t.getAlpha();
16807                        }
16808                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
16809                            renderNode.setStaticMatrix(t.getMatrix());
16810                        }
16811                    }
16812                }
16813            }
16814            if (mTransformationInfo != null) {
16815                alpha *= getFinalAlpha();
16816                if (alpha < 1) {
16817                    final int multipliedAlpha = (int) (255 * alpha);
16818                    if (onSetAlpha(multipliedAlpha)) {
16819                        alpha = 1;
16820                    }
16821                }
16822                renderNode.setAlpha(alpha);
16823            } else if (alpha < 1) {
16824                renderNode.setAlpha(alpha);
16825            }
16826        }
16827    }
16828
16829    /**
16830     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
16831     *
16832     * This is where the View specializes rendering behavior based on layer type,
16833     * and hardware acceleration.
16834     */
16835    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
16836        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
16837        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
16838         *
16839         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
16840         * HW accelerated, it can't handle drawing RenderNodes.
16841         */
16842        boolean drawingWithRenderNode = mAttachInfo != null
16843                && mAttachInfo.mHardwareAccelerated
16844                && hardwareAcceleratedCanvas;
16845
16846        boolean more = false;
16847        final boolean childHasIdentityMatrix = hasIdentityMatrix();
16848        final int parentFlags = parent.mGroupFlags;
16849
16850        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16851            parent.getChildTransformation().clear();
16852            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16853        }
16854
16855        Transformation transformToApply = null;
16856        boolean concatMatrix = false;
16857        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16858        final Animation a = getAnimation();
16859        if (a != null) {
16860            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16861            concatMatrix = a.willChangeTransformationMatrix();
16862            if (concatMatrix) {
16863                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16864            }
16865            transformToApply = parent.getChildTransformation();
16866        } else {
16867            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16868                // No longer animating: clear out old animation matrix
16869                mRenderNode.setAnimationMatrix(null);
16870                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16871            }
16872            if (!drawingWithRenderNode
16873                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16874                final Transformation t = parent.getChildTransformation();
16875                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16876                if (hasTransform) {
16877                    final int transformType = t.getTransformationType();
16878                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16879                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16880                }
16881            }
16882        }
16883
16884        concatMatrix |= !childHasIdentityMatrix;
16885
16886        // Sets the flag as early as possible to allow draw() implementations
16887        // to call invalidate() successfully when doing animations
16888        mPrivateFlags |= PFLAG_DRAWN;
16889
16890        if (!concatMatrix &&
16891                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16892                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16893                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16894                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16895            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16896            return more;
16897        }
16898        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16899
16900        if (hardwareAcceleratedCanvas) {
16901            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16902            // retain the flag's value temporarily in the mRecreateDisplayList flag
16903            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16904            mPrivateFlags &= ~PFLAG_INVALIDATED;
16905        }
16906
16907        RenderNode renderNode = null;
16908        Bitmap cache = null;
16909        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16910        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
16911             if (layerType != LAYER_TYPE_NONE) {
16912                 // If not drawing with RenderNode, treat HW layers as SW
16913                 layerType = LAYER_TYPE_SOFTWARE;
16914                 buildDrawingCache(true);
16915            }
16916            cache = getDrawingCache(true);
16917        }
16918
16919        if (drawingWithRenderNode) {
16920            // Delay getting the display list until animation-driven alpha values are
16921            // set up and possibly passed on to the view
16922            renderNode = updateDisplayListIfDirty();
16923            if (!renderNode.isValid()) {
16924                // Uncommon, but possible. If a view is removed from the hierarchy during the call
16925                // to getDisplayList(), the display list will be marked invalid and we should not
16926                // try to use it again.
16927                renderNode = null;
16928                drawingWithRenderNode = false;
16929            }
16930        }
16931
16932        int sx = 0;
16933        int sy = 0;
16934        if (!drawingWithRenderNode) {
16935            computeScroll();
16936            sx = mScrollX;
16937            sy = mScrollY;
16938        }
16939
16940        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16941        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16942
16943        int restoreTo = -1;
16944        if (!drawingWithRenderNode || transformToApply != null) {
16945            restoreTo = canvas.save();
16946        }
16947        if (offsetForScroll) {
16948            canvas.translate(mLeft - sx, mTop - sy);
16949        } else {
16950            if (!drawingWithRenderNode) {
16951                canvas.translate(mLeft, mTop);
16952            }
16953            if (scalingRequired) {
16954                if (drawingWithRenderNode) {
16955                    // TODO: Might not need this if we put everything inside the DL
16956                    restoreTo = canvas.save();
16957                }
16958                // mAttachInfo cannot be null, otherwise scalingRequired == false
16959                final float scale = 1.0f / mAttachInfo.mApplicationScale;
16960                canvas.scale(scale, scale);
16961            }
16962        }
16963
16964        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16965        if (transformToApply != null
16966                || alpha < 1
16967                || !hasIdentityMatrix()
16968                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16969            if (transformToApply != null || !childHasIdentityMatrix) {
16970                int transX = 0;
16971                int transY = 0;
16972
16973                if (offsetForScroll) {
16974                    transX = -sx;
16975                    transY = -sy;
16976                }
16977
16978                if (transformToApply != null) {
16979                    if (concatMatrix) {
16980                        if (drawingWithRenderNode) {
16981                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
16982                        } else {
16983                            // Undo the scroll translation, apply the transformation matrix,
16984                            // then redo the scroll translate to get the correct result.
16985                            canvas.translate(-transX, -transY);
16986                            canvas.concat(transformToApply.getMatrix());
16987                            canvas.translate(transX, transY);
16988                        }
16989                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16990                    }
16991
16992                    float transformAlpha = transformToApply.getAlpha();
16993                    if (transformAlpha < 1) {
16994                        alpha *= transformAlpha;
16995                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16996                    }
16997                }
16998
16999                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
17000                    canvas.translate(-transX, -transY);
17001                    canvas.concat(getMatrix());
17002                    canvas.translate(transX, transY);
17003                }
17004            }
17005
17006            // Deal with alpha if it is or used to be <1
17007            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17008                if (alpha < 1) {
17009                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17010                } else {
17011                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17012                }
17013                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17014                if (!drawingWithDrawingCache) {
17015                    final int multipliedAlpha = (int) (255 * alpha);
17016                    if (!onSetAlpha(multipliedAlpha)) {
17017                        if (drawingWithRenderNode) {
17018                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
17019                        } else if (layerType == LAYER_TYPE_NONE) {
17020                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
17021                                    multipliedAlpha);
17022                        }
17023                    } else {
17024                        // Alpha is handled by the child directly, clobber the layer's alpha
17025                        mPrivateFlags |= PFLAG_ALPHA_SET;
17026                    }
17027                }
17028            }
17029        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17030            onSetAlpha(255);
17031            mPrivateFlags &= ~PFLAG_ALPHA_SET;
17032        }
17033
17034        if (!drawingWithRenderNode) {
17035            // apply clips directly, since RenderNode won't do it for this draw
17036            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
17037                if (offsetForScroll) {
17038                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
17039                } else {
17040                    if (!scalingRequired || cache == null) {
17041                        canvas.clipRect(0, 0, getWidth(), getHeight());
17042                    } else {
17043                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
17044                    }
17045                }
17046            }
17047
17048            if (mClipBounds != null) {
17049                // clip bounds ignore scroll
17050                canvas.clipRect(mClipBounds);
17051            }
17052        }
17053
17054        if (!drawingWithDrawingCache) {
17055            if (drawingWithRenderNode) {
17056                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17057                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17058            } else {
17059                // Fast path for layouts with no backgrounds
17060                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17061                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17062                    dispatchDraw(canvas);
17063                } else {
17064                    draw(canvas);
17065                }
17066            }
17067        } else if (cache != null) {
17068            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17069            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
17070                // no layer paint, use temporary paint to draw bitmap
17071                Paint cachePaint = parent.mCachePaint;
17072                if (cachePaint == null) {
17073                    cachePaint = new Paint();
17074                    cachePaint.setDither(false);
17075                    parent.mCachePaint = cachePaint;
17076                }
17077                cachePaint.setAlpha((int) (alpha * 255));
17078                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
17079            } else {
17080                // use layer paint to draw the bitmap, merging the two alphas, but also restore
17081                int layerPaintAlpha = mLayerPaint.getAlpha();
17082                if (alpha < 1) {
17083                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
17084                }
17085                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
17086                if (alpha < 1) {
17087                    mLayerPaint.setAlpha(layerPaintAlpha);
17088                }
17089            }
17090        }
17091
17092        if (restoreTo >= 0) {
17093            canvas.restoreToCount(restoreTo);
17094        }
17095
17096        if (a != null && !more) {
17097            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
17098                onSetAlpha(255);
17099            }
17100            parent.finishAnimatingView(this, a);
17101        }
17102
17103        if (more && hardwareAcceleratedCanvas) {
17104            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17105                // alpha animations should cause the child to recreate its display list
17106                invalidate(true);
17107            }
17108        }
17109
17110        mRecreateDisplayList = false;
17111
17112        return more;
17113    }
17114
17115    /**
17116     * Manually render this view (and all of its children) to the given Canvas.
17117     * The view must have already done a full layout before this function is
17118     * called.  When implementing a view, implement
17119     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
17120     * If you do need to override this method, call the superclass version.
17121     *
17122     * @param canvas The Canvas to which the View is rendered.
17123     */
17124    @CallSuper
17125    public void draw(Canvas canvas) {
17126        final int privateFlags = mPrivateFlags;
17127        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
17128                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
17129        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
17130
17131        /*
17132         * Draw traversal performs several drawing steps which must be executed
17133         * in the appropriate order:
17134         *
17135         *      1. Draw the background
17136         *      2. If necessary, save the canvas' layers to prepare for fading
17137         *      3. Draw view's content
17138         *      4. Draw children
17139         *      5. If necessary, draw the fading edges and restore layers
17140         *      6. Draw decorations (scrollbars for instance)
17141         */
17142
17143        // Step 1, draw the background, if needed
17144        int saveCount;
17145
17146        if (!dirtyOpaque) {
17147            drawBackground(canvas);
17148        }
17149
17150        // skip step 2 & 5 if possible (common case)
17151        final int viewFlags = mViewFlags;
17152        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
17153        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
17154        if (!verticalEdges && !horizontalEdges) {
17155            // Step 3, draw the content
17156            if (!dirtyOpaque) onDraw(canvas);
17157
17158            // Step 4, draw the children
17159            dispatchDraw(canvas);
17160
17161            // Overlay is part of the content and draws beneath Foreground
17162            if (mOverlay != null && !mOverlay.isEmpty()) {
17163                mOverlay.getOverlayView().dispatchDraw(canvas);
17164            }
17165
17166            // Step 6, draw decorations (foreground, scrollbars)
17167            onDrawForeground(canvas);
17168
17169            // we're done...
17170            return;
17171        }
17172
17173        /*
17174         * Here we do the full fledged routine...
17175         * (this is an uncommon case where speed matters less,
17176         * this is why we repeat some of the tests that have been
17177         * done above)
17178         */
17179
17180        boolean drawTop = false;
17181        boolean drawBottom = false;
17182        boolean drawLeft = false;
17183        boolean drawRight = false;
17184
17185        float topFadeStrength = 0.0f;
17186        float bottomFadeStrength = 0.0f;
17187        float leftFadeStrength = 0.0f;
17188        float rightFadeStrength = 0.0f;
17189
17190        // Step 2, save the canvas' layers
17191        int paddingLeft = mPaddingLeft;
17192
17193        final boolean offsetRequired = isPaddingOffsetRequired();
17194        if (offsetRequired) {
17195            paddingLeft += getLeftPaddingOffset();
17196        }
17197
17198        int left = mScrollX + paddingLeft;
17199        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
17200        int top = mScrollY + getFadeTop(offsetRequired);
17201        int bottom = top + getFadeHeight(offsetRequired);
17202
17203        if (offsetRequired) {
17204            right += getRightPaddingOffset();
17205            bottom += getBottomPaddingOffset();
17206        }
17207
17208        final ScrollabilityCache scrollabilityCache = mScrollCache;
17209        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
17210        int length = (int) fadeHeight;
17211
17212        // clip the fade length if top and bottom fades overlap
17213        // overlapping fades produce odd-looking artifacts
17214        if (verticalEdges && (top + length > bottom - length)) {
17215            length = (bottom - top) / 2;
17216        }
17217
17218        // also clip horizontal fades if necessary
17219        if (horizontalEdges && (left + length > right - length)) {
17220            length = (right - left) / 2;
17221        }
17222
17223        if (verticalEdges) {
17224            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
17225            drawTop = topFadeStrength * fadeHeight > 1.0f;
17226            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
17227            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
17228        }
17229
17230        if (horizontalEdges) {
17231            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
17232            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
17233            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
17234            drawRight = rightFadeStrength * fadeHeight > 1.0f;
17235        }
17236
17237        saveCount = canvas.getSaveCount();
17238
17239        int solidColor = getSolidColor();
17240        if (solidColor == 0) {
17241            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
17242
17243            if (drawTop) {
17244                canvas.saveLayer(left, top, right, top + length, null, flags);
17245            }
17246
17247            if (drawBottom) {
17248                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
17249            }
17250
17251            if (drawLeft) {
17252                canvas.saveLayer(left, top, left + length, bottom, null, flags);
17253            }
17254
17255            if (drawRight) {
17256                canvas.saveLayer(right - length, top, right, bottom, null, flags);
17257            }
17258        } else {
17259            scrollabilityCache.setFadeColor(solidColor);
17260        }
17261
17262        // Step 3, draw the content
17263        if (!dirtyOpaque) onDraw(canvas);
17264
17265        // Step 4, draw the children
17266        dispatchDraw(canvas);
17267
17268        // Step 5, draw the fade effect and restore layers
17269        final Paint p = scrollabilityCache.paint;
17270        final Matrix matrix = scrollabilityCache.matrix;
17271        final Shader fade = scrollabilityCache.shader;
17272
17273        if (drawTop) {
17274            matrix.setScale(1, fadeHeight * topFadeStrength);
17275            matrix.postTranslate(left, top);
17276            fade.setLocalMatrix(matrix);
17277            p.setShader(fade);
17278            canvas.drawRect(left, top, right, top + length, p);
17279        }
17280
17281        if (drawBottom) {
17282            matrix.setScale(1, fadeHeight * bottomFadeStrength);
17283            matrix.postRotate(180);
17284            matrix.postTranslate(left, bottom);
17285            fade.setLocalMatrix(matrix);
17286            p.setShader(fade);
17287            canvas.drawRect(left, bottom - length, right, bottom, p);
17288        }
17289
17290        if (drawLeft) {
17291            matrix.setScale(1, fadeHeight * leftFadeStrength);
17292            matrix.postRotate(-90);
17293            matrix.postTranslate(left, top);
17294            fade.setLocalMatrix(matrix);
17295            p.setShader(fade);
17296            canvas.drawRect(left, top, left + length, bottom, p);
17297        }
17298
17299        if (drawRight) {
17300            matrix.setScale(1, fadeHeight * rightFadeStrength);
17301            matrix.postRotate(90);
17302            matrix.postTranslate(right, top);
17303            fade.setLocalMatrix(matrix);
17304            p.setShader(fade);
17305            canvas.drawRect(right - length, top, right, bottom, p);
17306        }
17307
17308        canvas.restoreToCount(saveCount);
17309
17310        // Overlay is part of the content and draws beneath Foreground
17311        if (mOverlay != null && !mOverlay.isEmpty()) {
17312            mOverlay.getOverlayView().dispatchDraw(canvas);
17313        }
17314
17315        // Step 6, draw decorations (foreground, scrollbars)
17316        onDrawForeground(canvas);
17317    }
17318
17319    /**
17320     * Draws the background onto the specified canvas.
17321     *
17322     * @param canvas Canvas on which to draw the background
17323     */
17324    private void drawBackground(Canvas canvas) {
17325        final Drawable background = mBackground;
17326        if (background == null) {
17327            return;
17328        }
17329
17330        setBackgroundBounds();
17331
17332        // Attempt to use a display list if requested.
17333        if (canvas.isHardwareAccelerated() && mAttachInfo != null
17334                && mAttachInfo.mHardwareRenderer != null) {
17335            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
17336
17337            final RenderNode renderNode = mBackgroundRenderNode;
17338            if (renderNode != null && renderNode.isValid()) {
17339                setBackgroundRenderNodeProperties(renderNode);
17340                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17341                return;
17342            }
17343        }
17344
17345        final int scrollX = mScrollX;
17346        final int scrollY = mScrollY;
17347        if ((scrollX | scrollY) == 0) {
17348            background.draw(canvas);
17349        } else {
17350            canvas.translate(scrollX, scrollY);
17351            background.draw(canvas);
17352            canvas.translate(-scrollX, -scrollY);
17353        }
17354    }
17355
17356    /**
17357     * Sets the correct background bounds and rebuilds the outline, if needed.
17358     * <p/>
17359     * This is called by LayoutLib.
17360     */
17361    void setBackgroundBounds() {
17362        if (mBackgroundSizeChanged && mBackground != null) {
17363            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
17364            mBackgroundSizeChanged = false;
17365            rebuildOutline();
17366        }
17367    }
17368
17369    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
17370        renderNode.setTranslationX(mScrollX);
17371        renderNode.setTranslationY(mScrollY);
17372    }
17373
17374    /**
17375     * Creates a new display list or updates the existing display list for the
17376     * specified Drawable.
17377     *
17378     * @param drawable Drawable for which to create a display list
17379     * @param renderNode Existing RenderNode, or {@code null}
17380     * @return A valid display list for the specified drawable
17381     */
17382    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
17383        if (renderNode == null) {
17384            renderNode = RenderNode.create(drawable.getClass().getName(), this);
17385        }
17386
17387        final Rect bounds = drawable.getBounds();
17388        final int width = bounds.width();
17389        final int height = bounds.height();
17390        final DisplayListCanvas canvas = renderNode.start(width, height);
17391
17392        // Reverse left/top translation done by drawable canvas, which will
17393        // instead be applied by rendernode's LTRB bounds below. This way, the
17394        // drawable's bounds match with its rendernode bounds and its content
17395        // will lie within those bounds in the rendernode tree.
17396        canvas.translate(-bounds.left, -bounds.top);
17397
17398        try {
17399            drawable.draw(canvas);
17400        } finally {
17401            renderNode.end(canvas);
17402        }
17403
17404        // Set up drawable properties that are view-independent.
17405        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
17406        renderNode.setProjectBackwards(drawable.isProjected());
17407        renderNode.setProjectionReceiver(true);
17408        renderNode.setClipToBounds(false);
17409        return renderNode;
17410    }
17411
17412    /**
17413     * Returns the overlay for this view, creating it if it does not yet exist.
17414     * Adding drawables to the overlay will cause them to be displayed whenever
17415     * the view itself is redrawn. Objects in the overlay should be actively
17416     * managed: remove them when they should not be displayed anymore. The
17417     * overlay will always have the same size as its host view.
17418     *
17419     * <p>Note: Overlays do not currently work correctly with {@link
17420     * SurfaceView} or {@link TextureView}; contents in overlays for these
17421     * types of views may not display correctly.</p>
17422     *
17423     * @return The ViewOverlay object for this view.
17424     * @see ViewOverlay
17425     */
17426    public ViewOverlay getOverlay() {
17427        if (mOverlay == null) {
17428            mOverlay = new ViewOverlay(mContext, this);
17429        }
17430        return mOverlay;
17431    }
17432
17433    /**
17434     * Override this if your view is known to always be drawn on top of a solid color background,
17435     * and needs to draw fading edges. Returning a non-zero color enables the view system to
17436     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
17437     * should be set to 0xFF.
17438     *
17439     * @see #setVerticalFadingEdgeEnabled(boolean)
17440     * @see #setHorizontalFadingEdgeEnabled(boolean)
17441     *
17442     * @return The known solid color background for this view, or 0 if the color may vary
17443     */
17444    @ViewDebug.ExportedProperty(category = "drawing")
17445    @ColorInt
17446    public int getSolidColor() {
17447        return 0;
17448    }
17449
17450    /**
17451     * Build a human readable string representation of the specified view flags.
17452     *
17453     * @param flags the view flags to convert to a string
17454     * @return a String representing the supplied flags
17455     */
17456    private static String printFlags(int flags) {
17457        String output = "";
17458        int numFlags = 0;
17459        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
17460            output += "TAKES_FOCUS";
17461            numFlags++;
17462        }
17463
17464        switch (flags & VISIBILITY_MASK) {
17465        case INVISIBLE:
17466            if (numFlags > 0) {
17467                output += " ";
17468            }
17469            output += "INVISIBLE";
17470            // USELESS HERE numFlags++;
17471            break;
17472        case GONE:
17473            if (numFlags > 0) {
17474                output += " ";
17475            }
17476            output += "GONE";
17477            // USELESS HERE numFlags++;
17478            break;
17479        default:
17480            break;
17481        }
17482        return output;
17483    }
17484
17485    /**
17486     * Build a human readable string representation of the specified private
17487     * view flags.
17488     *
17489     * @param privateFlags the private view flags to convert to a string
17490     * @return a String representing the supplied flags
17491     */
17492    private static String printPrivateFlags(int privateFlags) {
17493        String output = "";
17494        int numFlags = 0;
17495
17496        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
17497            output += "WANTS_FOCUS";
17498            numFlags++;
17499        }
17500
17501        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
17502            if (numFlags > 0) {
17503                output += " ";
17504            }
17505            output += "FOCUSED";
17506            numFlags++;
17507        }
17508
17509        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
17510            if (numFlags > 0) {
17511                output += " ";
17512            }
17513            output += "SELECTED";
17514            numFlags++;
17515        }
17516
17517        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
17518            if (numFlags > 0) {
17519                output += " ";
17520            }
17521            output += "IS_ROOT_NAMESPACE";
17522            numFlags++;
17523        }
17524
17525        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
17526            if (numFlags > 0) {
17527                output += " ";
17528            }
17529            output += "HAS_BOUNDS";
17530            numFlags++;
17531        }
17532
17533        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
17534            if (numFlags > 0) {
17535                output += " ";
17536            }
17537            output += "DRAWN";
17538            // USELESS HERE numFlags++;
17539        }
17540        return output;
17541    }
17542
17543    /**
17544     * <p>Indicates whether or not this view's layout will be requested during
17545     * the next hierarchy layout pass.</p>
17546     *
17547     * @return true if the layout will be forced during next layout pass
17548     */
17549    public boolean isLayoutRequested() {
17550        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
17551    }
17552
17553    /**
17554     * Return true if o is a ViewGroup that is laying out using optical bounds.
17555     * @hide
17556     */
17557    public static boolean isLayoutModeOptical(Object o) {
17558        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
17559    }
17560
17561    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
17562        Insets parentInsets = mParent instanceof View ?
17563                ((View) mParent).getOpticalInsets() : Insets.NONE;
17564        Insets childInsets = getOpticalInsets();
17565        return setFrame(
17566                left   + parentInsets.left - childInsets.left,
17567                top    + parentInsets.top  - childInsets.top,
17568                right  + parentInsets.left + childInsets.right,
17569                bottom + parentInsets.top  + childInsets.bottom);
17570    }
17571
17572    /**
17573     * Assign a size and position to a view and all of its
17574     * descendants
17575     *
17576     * <p>This is the second phase of the layout mechanism.
17577     * (The first is measuring). In this phase, each parent calls
17578     * layout on all of its children to position them.
17579     * This is typically done using the child measurements
17580     * that were stored in the measure pass().</p>
17581     *
17582     * <p>Derived classes should not override this method.
17583     * Derived classes with children should override
17584     * onLayout. In that method, they should
17585     * call layout on each of their children.</p>
17586     *
17587     * @param l Left position, relative to parent
17588     * @param t Top position, relative to parent
17589     * @param r Right position, relative to parent
17590     * @param b Bottom position, relative to parent
17591     */
17592    @SuppressWarnings({"unchecked"})
17593    public void layout(int l, int t, int r, int b) {
17594        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
17595            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
17596            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17597        }
17598
17599        int oldL = mLeft;
17600        int oldT = mTop;
17601        int oldB = mBottom;
17602        int oldR = mRight;
17603
17604        boolean changed = isLayoutModeOptical(mParent) ?
17605                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
17606
17607        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
17608            onLayout(changed, l, t, r, b);
17609
17610            if (shouldDrawRoundScrollbar()) {
17611                if(mRoundScrollbarRenderer == null) {
17612                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
17613                }
17614            } else {
17615                mRoundScrollbarRenderer = null;
17616            }
17617
17618            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
17619
17620            ListenerInfo li = mListenerInfo;
17621            if (li != null && li.mOnLayoutChangeListeners != null) {
17622                ArrayList<OnLayoutChangeListener> listenersCopy =
17623                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
17624                int numListeners = listenersCopy.size();
17625                for (int i = 0; i < numListeners; ++i) {
17626                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
17627                }
17628            }
17629        }
17630
17631        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
17632        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
17633    }
17634
17635    /**
17636     * Called from layout when this view should
17637     * assign a size and position to each of its children.
17638     *
17639     * Derived classes with children should override
17640     * this method and call layout on each of
17641     * their children.
17642     * @param changed This is a new size or position for this view
17643     * @param left Left position, relative to parent
17644     * @param top Top position, relative to parent
17645     * @param right Right position, relative to parent
17646     * @param bottom Bottom position, relative to parent
17647     */
17648    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
17649    }
17650
17651    /**
17652     * Assign a size and position to this view.
17653     *
17654     * This is called from layout.
17655     *
17656     * @param left Left position, relative to parent
17657     * @param top Top position, relative to parent
17658     * @param right Right position, relative to parent
17659     * @param bottom Bottom position, relative to parent
17660     * @return true if the new size and position are different than the
17661     *         previous ones
17662     * {@hide}
17663     */
17664    protected boolean setFrame(int left, int top, int right, int bottom) {
17665        boolean changed = false;
17666
17667        if (DBG) {
17668            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
17669                    + right + "," + bottom + ")");
17670        }
17671
17672        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
17673            changed = true;
17674
17675            // Remember our drawn bit
17676            int drawn = mPrivateFlags & PFLAG_DRAWN;
17677
17678            int oldWidth = mRight - mLeft;
17679            int oldHeight = mBottom - mTop;
17680            int newWidth = right - left;
17681            int newHeight = bottom - top;
17682            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
17683
17684            // Invalidate our old position
17685            invalidate(sizeChanged);
17686
17687            mLeft = left;
17688            mTop = top;
17689            mRight = right;
17690            mBottom = bottom;
17691            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
17692
17693            mPrivateFlags |= PFLAG_HAS_BOUNDS;
17694
17695
17696            if (sizeChanged) {
17697                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
17698            }
17699
17700            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
17701                // If we are visible, force the DRAWN bit to on so that
17702                // this invalidate will go through (at least to our parent).
17703                // This is because someone may have invalidated this view
17704                // before this call to setFrame came in, thereby clearing
17705                // the DRAWN bit.
17706                mPrivateFlags |= PFLAG_DRAWN;
17707                invalidate(sizeChanged);
17708                // parent display list may need to be recreated based on a change in the bounds
17709                // of any child
17710                invalidateParentCaches();
17711            }
17712
17713            // Reset drawn bit to original value (invalidate turns it off)
17714            mPrivateFlags |= drawn;
17715
17716            mBackgroundSizeChanged = true;
17717            if (mForegroundInfo != null) {
17718                mForegroundInfo.mBoundsChanged = true;
17719            }
17720
17721            notifySubtreeAccessibilityStateChangedIfNeeded();
17722        }
17723        return changed;
17724    }
17725
17726    /**
17727     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
17728     * @hide
17729     */
17730    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
17731        setFrame(left, top, right, bottom);
17732    }
17733
17734    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
17735        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
17736        if (mOverlay != null) {
17737            mOverlay.getOverlayView().setRight(newWidth);
17738            mOverlay.getOverlayView().setBottom(newHeight);
17739        }
17740        rebuildOutline();
17741    }
17742
17743    /**
17744     * Finalize inflating a view from XML.  This is called as the last phase
17745     * of inflation, after all child views have been added.
17746     *
17747     * <p>Even if the subclass overrides onFinishInflate, they should always be
17748     * sure to call the super method, so that we get called.
17749     */
17750    @CallSuper
17751    protected void onFinishInflate() {
17752    }
17753
17754    /**
17755     * Returns the resources associated with this view.
17756     *
17757     * @return Resources object.
17758     */
17759    public Resources getResources() {
17760        return mResources;
17761    }
17762
17763    /**
17764     * Invalidates the specified Drawable.
17765     *
17766     * @param drawable the drawable to invalidate
17767     */
17768    @Override
17769    public void invalidateDrawable(@NonNull Drawable drawable) {
17770        if (verifyDrawable(drawable)) {
17771            final Rect dirty = drawable.getDirtyBounds();
17772            final int scrollX = mScrollX;
17773            final int scrollY = mScrollY;
17774
17775            invalidate(dirty.left + scrollX, dirty.top + scrollY,
17776                    dirty.right + scrollX, dirty.bottom + scrollY);
17777            rebuildOutline();
17778        }
17779    }
17780
17781    /**
17782     * Schedules an action on a drawable to occur at a specified time.
17783     *
17784     * @param who the recipient of the action
17785     * @param what the action to run on the drawable
17786     * @param when the time at which the action must occur. Uses the
17787     *        {@link SystemClock#uptimeMillis} timebase.
17788     */
17789    @Override
17790    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
17791        if (verifyDrawable(who) && what != null) {
17792            final long delay = when - SystemClock.uptimeMillis();
17793            if (mAttachInfo != null) {
17794                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17795                        Choreographer.CALLBACK_ANIMATION, what, who,
17796                        Choreographer.subtractFrameDelay(delay));
17797            } else {
17798                // Postpone the runnable until we know
17799                // on which thread it needs to run.
17800                getRunQueue().postDelayed(what, delay);
17801            }
17802        }
17803    }
17804
17805    /**
17806     * Cancels a scheduled action on a drawable.
17807     *
17808     * @param who the recipient of the action
17809     * @param what the action to cancel
17810     */
17811    @Override
17812    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
17813        if (verifyDrawable(who) && what != null) {
17814            if (mAttachInfo != null) {
17815                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17816                        Choreographer.CALLBACK_ANIMATION, what, who);
17817            }
17818            getRunQueue().removeCallbacks(what);
17819        }
17820    }
17821
17822    /**
17823     * Unschedule any events associated with the given Drawable.  This can be
17824     * used when selecting a new Drawable into a view, so that the previous
17825     * one is completely unscheduled.
17826     *
17827     * @param who The Drawable to unschedule.
17828     *
17829     * @see #drawableStateChanged
17830     */
17831    public void unscheduleDrawable(Drawable who) {
17832        if (mAttachInfo != null && who != null) {
17833            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17834                    Choreographer.CALLBACK_ANIMATION, null, who);
17835        }
17836    }
17837
17838    /**
17839     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
17840     * that the View directionality can and will be resolved before its Drawables.
17841     *
17842     * Will call {@link View#onResolveDrawables} when resolution is done.
17843     *
17844     * @hide
17845     */
17846    protected void resolveDrawables() {
17847        // Drawables resolution may need to happen before resolving the layout direction (which is
17848        // done only during the measure() call).
17849        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
17850        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
17851        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
17852        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
17853        // direction to be resolved as its resolved value will be the same as its raw value.
17854        if (!isLayoutDirectionResolved() &&
17855                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17856            return;
17857        }
17858
17859        final int layoutDirection = isLayoutDirectionResolved() ?
17860                getLayoutDirection() : getRawLayoutDirection();
17861
17862        if (mBackground != null) {
17863            mBackground.setLayoutDirection(layoutDirection);
17864        }
17865        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17866            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17867        }
17868        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17869        onResolveDrawables(layoutDirection);
17870    }
17871
17872    boolean areDrawablesResolved() {
17873        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17874    }
17875
17876    /**
17877     * Called when layout direction has been resolved.
17878     *
17879     * The default implementation does nothing.
17880     *
17881     * @param layoutDirection The resolved layout direction.
17882     *
17883     * @see #LAYOUT_DIRECTION_LTR
17884     * @see #LAYOUT_DIRECTION_RTL
17885     *
17886     * @hide
17887     */
17888    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17889    }
17890
17891    /**
17892     * @hide
17893     */
17894    protected void resetResolvedDrawables() {
17895        resetResolvedDrawablesInternal();
17896    }
17897
17898    void resetResolvedDrawablesInternal() {
17899        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17900    }
17901
17902    /**
17903     * If your view subclass is displaying its own Drawable objects, it should
17904     * override this function and return true for any Drawable it is
17905     * displaying.  This allows animations for those drawables to be
17906     * scheduled.
17907     *
17908     * <p>Be sure to call through to the super class when overriding this
17909     * function.
17910     *
17911     * @param who The Drawable to verify.  Return true if it is one you are
17912     *            displaying, else return the result of calling through to the
17913     *            super class.
17914     *
17915     * @return boolean If true than the Drawable is being displayed in the
17916     *         view; else false and it is not allowed to animate.
17917     *
17918     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17919     * @see #drawableStateChanged()
17920     */
17921    @CallSuper
17922    protected boolean verifyDrawable(@NonNull Drawable who) {
17923        // Avoid verifying the scroll bar drawable so that we don't end up in
17924        // an invalidation loop. This effectively prevents the scroll bar
17925        // drawable from triggering invalidations and scheduling runnables.
17926        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17927    }
17928
17929    /**
17930     * This function is called whenever the state of the view changes in such
17931     * a way that it impacts the state of drawables being shown.
17932     * <p>
17933     * If the View has a StateListAnimator, it will also be called to run necessary state
17934     * change animations.
17935     * <p>
17936     * Be sure to call through to the superclass when overriding this function.
17937     *
17938     * @see Drawable#setState(int[])
17939     */
17940    @CallSuper
17941    protected void drawableStateChanged() {
17942        final int[] state = getDrawableState();
17943        boolean changed = false;
17944
17945        final Drawable bg = mBackground;
17946        if (bg != null && bg.isStateful()) {
17947            changed |= bg.setState(state);
17948        }
17949
17950        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17951        if (fg != null && fg.isStateful()) {
17952            changed |= fg.setState(state);
17953        }
17954
17955        if (mScrollCache != null) {
17956            final Drawable scrollBar = mScrollCache.scrollBar;
17957            if (scrollBar != null && scrollBar.isStateful()) {
17958                changed |= scrollBar.setState(state)
17959                        && mScrollCache.state != ScrollabilityCache.OFF;
17960            }
17961        }
17962
17963        if (mStateListAnimator != null) {
17964            mStateListAnimator.setState(state);
17965        }
17966
17967        if (changed) {
17968            invalidate();
17969        }
17970    }
17971
17972    /**
17973     * This function is called whenever the view hotspot changes and needs to
17974     * be propagated to drawables or child views managed by the view.
17975     * <p>
17976     * Dispatching to child views is handled by
17977     * {@link #dispatchDrawableHotspotChanged(float, float)}.
17978     * <p>
17979     * Be sure to call through to the superclass when overriding this function.
17980     *
17981     * @param x hotspot x coordinate
17982     * @param y hotspot y coordinate
17983     */
17984    @CallSuper
17985    public void drawableHotspotChanged(float x, float y) {
17986        if (mBackground != null) {
17987            mBackground.setHotspot(x, y);
17988        }
17989        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17990            mForegroundInfo.mDrawable.setHotspot(x, y);
17991        }
17992
17993        dispatchDrawableHotspotChanged(x, y);
17994    }
17995
17996    /**
17997     * Dispatches drawableHotspotChanged to all of this View's children.
17998     *
17999     * @param x hotspot x coordinate
18000     * @param y hotspot y coordinate
18001     * @see #drawableHotspotChanged(float, float)
18002     */
18003    public void dispatchDrawableHotspotChanged(float x, float y) {
18004    }
18005
18006    /**
18007     * Call this to force a view to update its drawable state. This will cause
18008     * drawableStateChanged to be called on this view. Views that are interested
18009     * in the new state should call getDrawableState.
18010     *
18011     * @see #drawableStateChanged
18012     * @see #getDrawableState
18013     */
18014    public void refreshDrawableState() {
18015        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
18016        drawableStateChanged();
18017
18018        ViewParent parent = mParent;
18019        if (parent != null) {
18020            parent.childDrawableStateChanged(this);
18021        }
18022    }
18023
18024    /**
18025     * Return an array of resource IDs of the drawable states representing the
18026     * current state of the view.
18027     *
18028     * @return The current drawable state
18029     *
18030     * @see Drawable#setState(int[])
18031     * @see #drawableStateChanged()
18032     * @see #onCreateDrawableState(int)
18033     */
18034    public final int[] getDrawableState() {
18035        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
18036            return mDrawableState;
18037        } else {
18038            mDrawableState = onCreateDrawableState(0);
18039            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
18040            return mDrawableState;
18041        }
18042    }
18043
18044    /**
18045     * Generate the new {@link android.graphics.drawable.Drawable} state for
18046     * this view. This is called by the view
18047     * system when the cached Drawable state is determined to be invalid.  To
18048     * retrieve the current state, you should use {@link #getDrawableState}.
18049     *
18050     * @param extraSpace if non-zero, this is the number of extra entries you
18051     * would like in the returned array in which you can place your own
18052     * states.
18053     *
18054     * @return Returns an array holding the current {@link Drawable} state of
18055     * the view.
18056     *
18057     * @see #mergeDrawableStates(int[], int[])
18058     */
18059    protected int[] onCreateDrawableState(int extraSpace) {
18060        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
18061                mParent instanceof View) {
18062            return ((View) mParent).onCreateDrawableState(extraSpace);
18063        }
18064
18065        int[] drawableState;
18066
18067        int privateFlags = mPrivateFlags;
18068
18069        int viewStateIndex = 0;
18070        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
18071        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
18072        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
18073        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
18074        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
18075        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
18076        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
18077                ThreadedRenderer.isAvailable()) {
18078            // This is set if HW acceleration is requested, even if the current
18079            // process doesn't allow it.  This is just to allow app preview
18080            // windows to better match their app.
18081            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
18082        }
18083        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
18084
18085        final int privateFlags2 = mPrivateFlags2;
18086        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
18087            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
18088        }
18089        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
18090            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
18091        }
18092
18093        drawableState = StateSet.get(viewStateIndex);
18094
18095        //noinspection ConstantIfStatement
18096        if (false) {
18097            Log.i("View", "drawableStateIndex=" + viewStateIndex);
18098            Log.i("View", toString()
18099                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
18100                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
18101                    + " fo=" + hasFocus()
18102                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
18103                    + " wf=" + hasWindowFocus()
18104                    + ": " + Arrays.toString(drawableState));
18105        }
18106
18107        if (extraSpace == 0) {
18108            return drawableState;
18109        }
18110
18111        final int[] fullState;
18112        if (drawableState != null) {
18113            fullState = new int[drawableState.length + extraSpace];
18114            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
18115        } else {
18116            fullState = new int[extraSpace];
18117        }
18118
18119        return fullState;
18120    }
18121
18122    /**
18123     * Merge your own state values in <var>additionalState</var> into the base
18124     * state values <var>baseState</var> that were returned by
18125     * {@link #onCreateDrawableState(int)}.
18126     *
18127     * @param baseState The base state values returned by
18128     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
18129     * own additional state values.
18130     *
18131     * @param additionalState The additional state values you would like
18132     * added to <var>baseState</var>; this array is not modified.
18133     *
18134     * @return As a convenience, the <var>baseState</var> array you originally
18135     * passed into the function is returned.
18136     *
18137     * @see #onCreateDrawableState(int)
18138     */
18139    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
18140        final int N = baseState.length;
18141        int i = N - 1;
18142        while (i >= 0 && baseState[i] == 0) {
18143            i--;
18144        }
18145        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
18146        return baseState;
18147    }
18148
18149    /**
18150     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
18151     * on all Drawable objects associated with this view.
18152     * <p>
18153     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
18154     * attached to this view.
18155     */
18156    @CallSuper
18157    public void jumpDrawablesToCurrentState() {
18158        if (mBackground != null) {
18159            mBackground.jumpToCurrentState();
18160        }
18161        if (mStateListAnimator != null) {
18162            mStateListAnimator.jumpToCurrentState();
18163        }
18164        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18165            mForegroundInfo.mDrawable.jumpToCurrentState();
18166        }
18167    }
18168
18169    /**
18170     * Sets the background color for this view.
18171     * @param color the color of the background
18172     */
18173    @RemotableViewMethod
18174    public void setBackgroundColor(@ColorInt int color) {
18175        if (mBackground instanceof ColorDrawable) {
18176            ((ColorDrawable) mBackground.mutate()).setColor(color);
18177            computeOpaqueFlags();
18178            mBackgroundResource = 0;
18179        } else {
18180            setBackground(new ColorDrawable(color));
18181        }
18182    }
18183
18184    /**
18185     * Set the background to a given resource. The resource should refer to
18186     * a Drawable object or 0 to remove the background.
18187     * @param resid The identifier of the resource.
18188     *
18189     * @attr ref android.R.styleable#View_background
18190     */
18191    @RemotableViewMethod
18192    public void setBackgroundResource(@DrawableRes int resid) {
18193        if (resid != 0 && resid == mBackgroundResource) {
18194            return;
18195        }
18196
18197        Drawable d = null;
18198        if (resid != 0) {
18199            d = mContext.getDrawable(resid);
18200        }
18201        setBackground(d);
18202
18203        mBackgroundResource = resid;
18204    }
18205
18206    /**
18207     * Set the background to a given Drawable, or remove the background. If the
18208     * background has padding, this View's padding is set to the background's
18209     * padding. However, when a background is removed, this View's padding isn't
18210     * touched. If setting the padding is desired, please use
18211     * {@link #setPadding(int, int, int, int)}.
18212     *
18213     * @param background The Drawable to use as the background, or null to remove the
18214     *        background
18215     */
18216    public void setBackground(Drawable background) {
18217        //noinspection deprecation
18218        setBackgroundDrawable(background);
18219    }
18220
18221    /**
18222     * @deprecated use {@link #setBackground(Drawable)} instead
18223     */
18224    @Deprecated
18225    public void setBackgroundDrawable(Drawable background) {
18226        computeOpaqueFlags();
18227
18228        if (background == mBackground) {
18229            return;
18230        }
18231
18232        boolean requestLayout = false;
18233
18234        mBackgroundResource = 0;
18235
18236        /*
18237         * Regardless of whether we're setting a new background or not, we want
18238         * to clear the previous drawable. setVisible first while we still have the callback set.
18239         */
18240        if (mBackground != null) {
18241            if (isAttachedToWindow()) {
18242                mBackground.setVisible(false, false);
18243            }
18244            mBackground.setCallback(null);
18245            unscheduleDrawable(mBackground);
18246        }
18247
18248        if (background != null) {
18249            Rect padding = sThreadLocal.get();
18250            if (padding == null) {
18251                padding = new Rect();
18252                sThreadLocal.set(padding);
18253            }
18254            resetResolvedDrawablesInternal();
18255            background.setLayoutDirection(getLayoutDirection());
18256            if (background.getPadding(padding)) {
18257                resetResolvedPaddingInternal();
18258                switch (background.getLayoutDirection()) {
18259                    case LAYOUT_DIRECTION_RTL:
18260                        mUserPaddingLeftInitial = padding.right;
18261                        mUserPaddingRightInitial = padding.left;
18262                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
18263                        break;
18264                    case LAYOUT_DIRECTION_LTR:
18265                    default:
18266                        mUserPaddingLeftInitial = padding.left;
18267                        mUserPaddingRightInitial = padding.right;
18268                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
18269                }
18270                mLeftPaddingDefined = false;
18271                mRightPaddingDefined = false;
18272            }
18273
18274            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
18275            // if it has a different minimum size, we should layout again
18276            if (mBackground == null
18277                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
18278                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
18279                requestLayout = true;
18280            }
18281
18282            // Set mBackground before we set this as the callback and start making other
18283            // background drawable state change calls. In particular, the setVisible call below
18284            // can result in drawables attempting to start animations or otherwise invalidate,
18285            // which requires the view set as the callback (us) to recognize the drawable as
18286            // belonging to it as per verifyDrawable.
18287            mBackground = background;
18288            if (background.isStateful()) {
18289                background.setState(getDrawableState());
18290            }
18291            if (isAttachedToWindow()) {
18292                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18293            }
18294
18295            applyBackgroundTint();
18296
18297            // Set callback last, since the view may still be initializing.
18298            background.setCallback(this);
18299
18300            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18301                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18302                requestLayout = true;
18303            }
18304        } else {
18305            /* Remove the background */
18306            mBackground = null;
18307            if ((mViewFlags & WILL_NOT_DRAW) != 0
18308                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
18309                mPrivateFlags |= PFLAG_SKIP_DRAW;
18310            }
18311
18312            /*
18313             * When the background is set, we try to apply its padding to this
18314             * View. When the background is removed, we don't touch this View's
18315             * padding. This is noted in the Javadocs. Hence, we don't need to
18316             * requestLayout(), the invalidate() below is sufficient.
18317             */
18318
18319            // The old background's minimum size could have affected this
18320            // View's layout, so let's requestLayout
18321            requestLayout = true;
18322        }
18323
18324        computeOpaqueFlags();
18325
18326        if (requestLayout) {
18327            requestLayout();
18328        }
18329
18330        mBackgroundSizeChanged = true;
18331        invalidate(true);
18332        invalidateOutline();
18333    }
18334
18335    /**
18336     * Gets the background drawable
18337     *
18338     * @return The drawable used as the background for this view, if any.
18339     *
18340     * @see #setBackground(Drawable)
18341     *
18342     * @attr ref android.R.styleable#View_background
18343     */
18344    public Drawable getBackground() {
18345        return mBackground;
18346    }
18347
18348    /**
18349     * Applies a tint to the background drawable. Does not modify the current tint
18350     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18351     * <p>
18352     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
18353     * mutate the drawable and apply the specified tint and tint mode using
18354     * {@link Drawable#setTintList(ColorStateList)}.
18355     *
18356     * @param tint the tint to apply, may be {@code null} to clear tint
18357     *
18358     * @attr ref android.R.styleable#View_backgroundTint
18359     * @see #getBackgroundTintList()
18360     * @see Drawable#setTintList(ColorStateList)
18361     */
18362    public void setBackgroundTintList(@Nullable ColorStateList tint) {
18363        if (mBackgroundTint == null) {
18364            mBackgroundTint = new TintInfo();
18365        }
18366        mBackgroundTint.mTintList = tint;
18367        mBackgroundTint.mHasTintList = true;
18368
18369        applyBackgroundTint();
18370    }
18371
18372    /**
18373     * Return the tint applied to the background drawable, if specified.
18374     *
18375     * @return the tint applied to the background drawable
18376     * @attr ref android.R.styleable#View_backgroundTint
18377     * @see #setBackgroundTintList(ColorStateList)
18378     */
18379    @Nullable
18380    public ColorStateList getBackgroundTintList() {
18381        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
18382    }
18383
18384    /**
18385     * Specifies the blending mode used to apply the tint specified by
18386     * {@link #setBackgroundTintList(ColorStateList)}} to the background
18387     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18388     *
18389     * @param tintMode the blending mode used to apply the tint, may be
18390     *                 {@code null} to clear tint
18391     * @attr ref android.R.styleable#View_backgroundTintMode
18392     * @see #getBackgroundTintMode()
18393     * @see Drawable#setTintMode(PorterDuff.Mode)
18394     */
18395    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18396        if (mBackgroundTint == null) {
18397            mBackgroundTint = new TintInfo();
18398        }
18399        mBackgroundTint.mTintMode = tintMode;
18400        mBackgroundTint.mHasTintMode = true;
18401
18402        applyBackgroundTint();
18403    }
18404
18405    /**
18406     * Return the blending mode used to apply the tint to the background
18407     * drawable, if specified.
18408     *
18409     * @return the blending mode used to apply the tint to the background
18410     *         drawable
18411     * @attr ref android.R.styleable#View_backgroundTintMode
18412     * @see #setBackgroundTintMode(PorterDuff.Mode)
18413     */
18414    @Nullable
18415    public PorterDuff.Mode getBackgroundTintMode() {
18416        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
18417    }
18418
18419    private void applyBackgroundTint() {
18420        if (mBackground != null && mBackgroundTint != null) {
18421            final TintInfo tintInfo = mBackgroundTint;
18422            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18423                mBackground = mBackground.mutate();
18424
18425                if (tintInfo.mHasTintList) {
18426                    mBackground.setTintList(tintInfo.mTintList);
18427                }
18428
18429                if (tintInfo.mHasTintMode) {
18430                    mBackground.setTintMode(tintInfo.mTintMode);
18431                }
18432
18433                // The drawable (or one of its children) may not have been
18434                // stateful before applying the tint, so let's try again.
18435                if (mBackground.isStateful()) {
18436                    mBackground.setState(getDrawableState());
18437                }
18438            }
18439        }
18440    }
18441
18442    /**
18443     * Returns the drawable used as the foreground of this View. The
18444     * foreground drawable, if non-null, is always drawn on top of the view's content.
18445     *
18446     * @return a Drawable or null if no foreground was set
18447     *
18448     * @see #onDrawForeground(Canvas)
18449     */
18450    public Drawable getForeground() {
18451        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18452    }
18453
18454    /**
18455     * Supply a Drawable that is to be rendered on top of all of the content in the view.
18456     *
18457     * @param foreground the Drawable to be drawn on top of the children
18458     *
18459     * @attr ref android.R.styleable#View_foreground
18460     */
18461    public void setForeground(Drawable foreground) {
18462        if (mForegroundInfo == null) {
18463            if (foreground == null) {
18464                // Nothing to do.
18465                return;
18466            }
18467            mForegroundInfo = new ForegroundInfo();
18468        }
18469
18470        if (foreground == mForegroundInfo.mDrawable) {
18471            // Nothing to do
18472            return;
18473        }
18474
18475        if (mForegroundInfo.mDrawable != null) {
18476            if (isAttachedToWindow()) {
18477                mForegroundInfo.mDrawable.setVisible(false, false);
18478            }
18479            mForegroundInfo.mDrawable.setCallback(null);
18480            unscheduleDrawable(mForegroundInfo.mDrawable);
18481        }
18482
18483        mForegroundInfo.mDrawable = foreground;
18484        mForegroundInfo.mBoundsChanged = true;
18485        if (foreground != null) {
18486            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18487                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18488            }
18489            foreground.setLayoutDirection(getLayoutDirection());
18490            if (foreground.isStateful()) {
18491                foreground.setState(getDrawableState());
18492            }
18493            applyForegroundTint();
18494            if (isAttachedToWindow()) {
18495                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18496            }
18497            // Set callback last, since the view may still be initializing.
18498            foreground.setCallback(this);
18499        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
18500            mPrivateFlags |= PFLAG_SKIP_DRAW;
18501        }
18502        requestLayout();
18503        invalidate();
18504    }
18505
18506    /**
18507     * Magic bit used to support features of framework-internal window decor implementation details.
18508     * This used to live exclusively in FrameLayout.
18509     *
18510     * @return true if the foreground should draw inside the padding region or false
18511     *         if it should draw inset by the view's padding
18512     * @hide internal use only; only used by FrameLayout and internal screen layouts.
18513     */
18514    public boolean isForegroundInsidePadding() {
18515        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
18516    }
18517
18518    /**
18519     * Describes how the foreground is positioned.
18520     *
18521     * @return foreground gravity.
18522     *
18523     * @see #setForegroundGravity(int)
18524     *
18525     * @attr ref android.R.styleable#View_foregroundGravity
18526     */
18527    public int getForegroundGravity() {
18528        return mForegroundInfo != null ? mForegroundInfo.mGravity
18529                : Gravity.START | Gravity.TOP;
18530    }
18531
18532    /**
18533     * Describes how the foreground is positioned. Defaults to START and TOP.
18534     *
18535     * @param gravity see {@link android.view.Gravity}
18536     *
18537     * @see #getForegroundGravity()
18538     *
18539     * @attr ref android.R.styleable#View_foregroundGravity
18540     */
18541    public void setForegroundGravity(int gravity) {
18542        if (mForegroundInfo == null) {
18543            mForegroundInfo = new ForegroundInfo();
18544        }
18545
18546        if (mForegroundInfo.mGravity != gravity) {
18547            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
18548                gravity |= Gravity.START;
18549            }
18550
18551            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
18552                gravity |= Gravity.TOP;
18553            }
18554
18555            mForegroundInfo.mGravity = gravity;
18556            requestLayout();
18557        }
18558    }
18559
18560    /**
18561     * Applies a tint to the foreground drawable. Does not modify the current tint
18562     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18563     * <p>
18564     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
18565     * mutate the drawable and apply the specified tint and tint mode using
18566     * {@link Drawable#setTintList(ColorStateList)}.
18567     *
18568     * @param tint the tint to apply, may be {@code null} to clear tint
18569     *
18570     * @attr ref android.R.styleable#View_foregroundTint
18571     * @see #getForegroundTintList()
18572     * @see Drawable#setTintList(ColorStateList)
18573     */
18574    public void setForegroundTintList(@Nullable ColorStateList tint) {
18575        if (mForegroundInfo == null) {
18576            mForegroundInfo = new ForegroundInfo();
18577        }
18578        if (mForegroundInfo.mTintInfo == null) {
18579            mForegroundInfo.mTintInfo = new TintInfo();
18580        }
18581        mForegroundInfo.mTintInfo.mTintList = tint;
18582        mForegroundInfo.mTintInfo.mHasTintList = true;
18583
18584        applyForegroundTint();
18585    }
18586
18587    /**
18588     * Return the tint applied to the foreground drawable, if specified.
18589     *
18590     * @return the tint applied to the foreground drawable
18591     * @attr ref android.R.styleable#View_foregroundTint
18592     * @see #setForegroundTintList(ColorStateList)
18593     */
18594    @Nullable
18595    public ColorStateList getForegroundTintList() {
18596        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18597                ? mForegroundInfo.mTintInfo.mTintList : null;
18598    }
18599
18600    /**
18601     * Specifies the blending mode used to apply the tint specified by
18602     * {@link #setForegroundTintList(ColorStateList)}} to the background
18603     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18604     *
18605     * @param tintMode the blending mode used to apply the tint, may be
18606     *                 {@code null} to clear tint
18607     * @attr ref android.R.styleable#View_foregroundTintMode
18608     * @see #getForegroundTintMode()
18609     * @see Drawable#setTintMode(PorterDuff.Mode)
18610     */
18611    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18612        if (mForegroundInfo == null) {
18613            mForegroundInfo = new ForegroundInfo();
18614        }
18615        if (mForegroundInfo.mTintInfo == null) {
18616            mForegroundInfo.mTintInfo = new TintInfo();
18617        }
18618        mForegroundInfo.mTintInfo.mTintMode = tintMode;
18619        mForegroundInfo.mTintInfo.mHasTintMode = true;
18620
18621        applyForegroundTint();
18622    }
18623
18624    /**
18625     * Return the blending mode used to apply the tint to the foreground
18626     * drawable, if specified.
18627     *
18628     * @return the blending mode used to apply the tint to the foreground
18629     *         drawable
18630     * @attr ref android.R.styleable#View_foregroundTintMode
18631     * @see #setForegroundTintMode(PorterDuff.Mode)
18632     */
18633    @Nullable
18634    public PorterDuff.Mode getForegroundTintMode() {
18635        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18636                ? mForegroundInfo.mTintInfo.mTintMode : null;
18637    }
18638
18639    private void applyForegroundTint() {
18640        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
18641                && mForegroundInfo.mTintInfo != null) {
18642            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
18643            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18644                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
18645
18646                if (tintInfo.mHasTintList) {
18647                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
18648                }
18649
18650                if (tintInfo.mHasTintMode) {
18651                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
18652                }
18653
18654                // The drawable (or one of its children) may not have been
18655                // stateful before applying the tint, so let's try again.
18656                if (mForegroundInfo.mDrawable.isStateful()) {
18657                    mForegroundInfo.mDrawable.setState(getDrawableState());
18658                }
18659            }
18660        }
18661    }
18662
18663    /**
18664     * Draw any foreground content for this view.
18665     *
18666     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
18667     * drawable or other view-specific decorations. The foreground is drawn on top of the
18668     * primary view content.</p>
18669     *
18670     * @param canvas canvas to draw into
18671     */
18672    public void onDrawForeground(Canvas canvas) {
18673        onDrawScrollIndicators(canvas);
18674        onDrawScrollBars(canvas);
18675
18676        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18677        if (foreground != null) {
18678            if (mForegroundInfo.mBoundsChanged) {
18679                mForegroundInfo.mBoundsChanged = false;
18680                final Rect selfBounds = mForegroundInfo.mSelfBounds;
18681                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
18682
18683                if (mForegroundInfo.mInsidePadding) {
18684                    selfBounds.set(0, 0, getWidth(), getHeight());
18685                } else {
18686                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
18687                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
18688                }
18689
18690                final int ld = getLayoutDirection();
18691                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
18692                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
18693                foreground.setBounds(overlayBounds);
18694            }
18695
18696            foreground.draw(canvas);
18697        }
18698    }
18699
18700    /**
18701     * Sets the padding. The view may add on the space required to display
18702     * the scrollbars, depending on the style and visibility of the scrollbars.
18703     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
18704     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
18705     * from the values set in this call.
18706     *
18707     * @attr ref android.R.styleable#View_padding
18708     * @attr ref android.R.styleable#View_paddingBottom
18709     * @attr ref android.R.styleable#View_paddingLeft
18710     * @attr ref android.R.styleable#View_paddingRight
18711     * @attr ref android.R.styleable#View_paddingTop
18712     * @param left the left padding in pixels
18713     * @param top the top padding in pixels
18714     * @param right the right padding in pixels
18715     * @param bottom the bottom padding in pixels
18716     */
18717    public void setPadding(int left, int top, int right, int bottom) {
18718        resetResolvedPaddingInternal();
18719
18720        mUserPaddingStart = UNDEFINED_PADDING;
18721        mUserPaddingEnd = UNDEFINED_PADDING;
18722
18723        mUserPaddingLeftInitial = left;
18724        mUserPaddingRightInitial = right;
18725
18726        mLeftPaddingDefined = true;
18727        mRightPaddingDefined = true;
18728
18729        internalSetPadding(left, top, right, bottom);
18730    }
18731
18732    /**
18733     * @hide
18734     */
18735    protected void internalSetPadding(int left, int top, int right, int bottom) {
18736        mUserPaddingLeft = left;
18737        mUserPaddingRight = right;
18738        mUserPaddingBottom = bottom;
18739
18740        final int viewFlags = mViewFlags;
18741        boolean changed = false;
18742
18743        // Common case is there are no scroll bars.
18744        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
18745            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
18746                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
18747                        ? 0 : getVerticalScrollbarWidth();
18748                switch (mVerticalScrollbarPosition) {
18749                    case SCROLLBAR_POSITION_DEFAULT:
18750                        if (isLayoutRtl()) {
18751                            left += offset;
18752                        } else {
18753                            right += offset;
18754                        }
18755                        break;
18756                    case SCROLLBAR_POSITION_RIGHT:
18757                        right += offset;
18758                        break;
18759                    case SCROLLBAR_POSITION_LEFT:
18760                        left += offset;
18761                        break;
18762                }
18763            }
18764            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
18765                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
18766                        ? 0 : getHorizontalScrollbarHeight();
18767            }
18768        }
18769
18770        if (mPaddingLeft != left) {
18771            changed = true;
18772            mPaddingLeft = left;
18773        }
18774        if (mPaddingTop != top) {
18775            changed = true;
18776            mPaddingTop = top;
18777        }
18778        if (mPaddingRight != right) {
18779            changed = true;
18780            mPaddingRight = right;
18781        }
18782        if (mPaddingBottom != bottom) {
18783            changed = true;
18784            mPaddingBottom = bottom;
18785        }
18786
18787        if (changed) {
18788            requestLayout();
18789            invalidateOutline();
18790        }
18791    }
18792
18793    /**
18794     * Sets the relative padding. The view may add on the space required to display
18795     * the scrollbars, depending on the style and visibility of the scrollbars.
18796     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
18797     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
18798     * from the values set in this call.
18799     *
18800     * @attr ref android.R.styleable#View_padding
18801     * @attr ref android.R.styleable#View_paddingBottom
18802     * @attr ref android.R.styleable#View_paddingStart
18803     * @attr ref android.R.styleable#View_paddingEnd
18804     * @attr ref android.R.styleable#View_paddingTop
18805     * @param start the start padding in pixels
18806     * @param top the top padding in pixels
18807     * @param end the end padding in pixels
18808     * @param bottom the bottom padding in pixels
18809     */
18810    public void setPaddingRelative(int start, int top, int end, int bottom) {
18811        resetResolvedPaddingInternal();
18812
18813        mUserPaddingStart = start;
18814        mUserPaddingEnd = end;
18815        mLeftPaddingDefined = true;
18816        mRightPaddingDefined = true;
18817
18818        switch(getLayoutDirection()) {
18819            case LAYOUT_DIRECTION_RTL:
18820                mUserPaddingLeftInitial = end;
18821                mUserPaddingRightInitial = start;
18822                internalSetPadding(end, top, start, bottom);
18823                break;
18824            case LAYOUT_DIRECTION_LTR:
18825            default:
18826                mUserPaddingLeftInitial = start;
18827                mUserPaddingRightInitial = end;
18828                internalSetPadding(start, top, end, bottom);
18829        }
18830    }
18831
18832    /**
18833     * Returns the top padding of this view.
18834     *
18835     * @return the top padding in pixels
18836     */
18837    public int getPaddingTop() {
18838        return mPaddingTop;
18839    }
18840
18841    /**
18842     * Returns the bottom padding of this view. If there are inset and enabled
18843     * scrollbars, this value may include the space required to display the
18844     * scrollbars as well.
18845     *
18846     * @return the bottom padding in pixels
18847     */
18848    public int getPaddingBottom() {
18849        return mPaddingBottom;
18850    }
18851
18852    /**
18853     * Returns the left padding of this view. If there are inset and enabled
18854     * scrollbars, this value may include the space required to display the
18855     * scrollbars as well.
18856     *
18857     * @return the left padding in pixels
18858     */
18859    public int getPaddingLeft() {
18860        if (!isPaddingResolved()) {
18861            resolvePadding();
18862        }
18863        return mPaddingLeft;
18864    }
18865
18866    /**
18867     * Returns the start padding of this view depending on its resolved layout direction.
18868     * If there are inset and enabled scrollbars, this value may include the space
18869     * required to display the scrollbars as well.
18870     *
18871     * @return the start padding in pixels
18872     */
18873    public int getPaddingStart() {
18874        if (!isPaddingResolved()) {
18875            resolvePadding();
18876        }
18877        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18878                mPaddingRight : mPaddingLeft;
18879    }
18880
18881    /**
18882     * Returns the right padding of this view. If there are inset and enabled
18883     * scrollbars, this value may include the space required to display the
18884     * scrollbars as well.
18885     *
18886     * @return the right padding in pixels
18887     */
18888    public int getPaddingRight() {
18889        if (!isPaddingResolved()) {
18890            resolvePadding();
18891        }
18892        return mPaddingRight;
18893    }
18894
18895    /**
18896     * Returns the end padding of this view depending on its resolved layout direction.
18897     * If there are inset and enabled scrollbars, this value may include the space
18898     * required to display the scrollbars as well.
18899     *
18900     * @return the end padding in pixels
18901     */
18902    public int getPaddingEnd() {
18903        if (!isPaddingResolved()) {
18904            resolvePadding();
18905        }
18906        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18907                mPaddingLeft : mPaddingRight;
18908    }
18909
18910    /**
18911     * Return if the padding has been set through relative values
18912     * {@link #setPaddingRelative(int, int, int, int)} or through
18913     * @attr ref android.R.styleable#View_paddingStart or
18914     * @attr ref android.R.styleable#View_paddingEnd
18915     *
18916     * @return true if the padding is relative or false if it is not.
18917     */
18918    public boolean isPaddingRelative() {
18919        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18920    }
18921
18922    Insets computeOpticalInsets() {
18923        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18924    }
18925
18926    /**
18927     * @hide
18928     */
18929    public void resetPaddingToInitialValues() {
18930        if (isRtlCompatibilityMode()) {
18931            mPaddingLeft = mUserPaddingLeftInitial;
18932            mPaddingRight = mUserPaddingRightInitial;
18933            return;
18934        }
18935        if (isLayoutRtl()) {
18936            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18937            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18938        } else {
18939            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18940            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18941        }
18942    }
18943
18944    /**
18945     * @hide
18946     */
18947    public Insets getOpticalInsets() {
18948        if (mLayoutInsets == null) {
18949            mLayoutInsets = computeOpticalInsets();
18950        }
18951        return mLayoutInsets;
18952    }
18953
18954    /**
18955     * Set this view's optical insets.
18956     *
18957     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
18958     * property. Views that compute their own optical insets should call it as part of measurement.
18959     * This method does not request layout. If you are setting optical insets outside of
18960     * measure/layout itself you will want to call requestLayout() yourself.
18961     * </p>
18962     * @hide
18963     */
18964    public void setOpticalInsets(Insets insets) {
18965        mLayoutInsets = insets;
18966    }
18967
18968    /**
18969     * Changes the selection state of this view. A view can be selected or not.
18970     * Note that selection is not the same as focus. Views are typically
18971     * selected in the context of an AdapterView like ListView or GridView;
18972     * the selected view is the view that is highlighted.
18973     *
18974     * @param selected true if the view must be selected, false otherwise
18975     */
18976    public void setSelected(boolean selected) {
18977        //noinspection DoubleNegation
18978        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
18979            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
18980            if (!selected) resetPressedState();
18981            invalidate(true);
18982            refreshDrawableState();
18983            dispatchSetSelected(selected);
18984            if (selected) {
18985                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
18986            } else {
18987                notifyViewAccessibilityStateChangedIfNeeded(
18988                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
18989            }
18990        }
18991    }
18992
18993    /**
18994     * Dispatch setSelected to all of this View's children.
18995     *
18996     * @see #setSelected(boolean)
18997     *
18998     * @param selected The new selected state
18999     */
19000    protected void dispatchSetSelected(boolean selected) {
19001    }
19002
19003    /**
19004     * Indicates the selection state of this view.
19005     *
19006     * @return true if the view is selected, false otherwise
19007     */
19008    @ViewDebug.ExportedProperty
19009    public boolean isSelected() {
19010        return (mPrivateFlags & PFLAG_SELECTED) != 0;
19011    }
19012
19013    /**
19014     * Changes the activated state of this view. A view can be activated or not.
19015     * Note that activation is not the same as selection.  Selection is
19016     * a transient property, representing the view (hierarchy) the user is
19017     * currently interacting with.  Activation is a longer-term state that the
19018     * user can move views in and out of.  For example, in a list view with
19019     * single or multiple selection enabled, the views in the current selection
19020     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
19021     * here.)  The activated state is propagated down to children of the view it
19022     * is set on.
19023     *
19024     * @param activated true if the view must be activated, false otherwise
19025     */
19026    public void setActivated(boolean activated) {
19027        //noinspection DoubleNegation
19028        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
19029            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
19030            invalidate(true);
19031            refreshDrawableState();
19032            dispatchSetActivated(activated);
19033        }
19034    }
19035
19036    /**
19037     * Dispatch setActivated to all of this View's children.
19038     *
19039     * @see #setActivated(boolean)
19040     *
19041     * @param activated The new activated state
19042     */
19043    protected void dispatchSetActivated(boolean activated) {
19044    }
19045
19046    /**
19047     * Indicates the activation state of this view.
19048     *
19049     * @return true if the view is activated, false otherwise
19050     */
19051    @ViewDebug.ExportedProperty
19052    public boolean isActivated() {
19053        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
19054    }
19055
19056    /**
19057     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
19058     * observer can be used to get notifications when global events, like
19059     * layout, happen.
19060     *
19061     * The returned ViewTreeObserver observer is not guaranteed to remain
19062     * valid for the lifetime of this View. If the caller of this method keeps
19063     * a long-lived reference to ViewTreeObserver, it should always check for
19064     * the return value of {@link ViewTreeObserver#isAlive()}.
19065     *
19066     * @return The ViewTreeObserver for this view's hierarchy.
19067     */
19068    public ViewTreeObserver getViewTreeObserver() {
19069        if (mAttachInfo != null) {
19070            return mAttachInfo.mTreeObserver;
19071        }
19072        if (mFloatingTreeObserver == null) {
19073            mFloatingTreeObserver = new ViewTreeObserver();
19074        }
19075        return mFloatingTreeObserver;
19076    }
19077
19078    /**
19079     * <p>Finds the topmost view in the current view hierarchy.</p>
19080     *
19081     * @return the topmost view containing this view
19082     */
19083    public View getRootView() {
19084        if (mAttachInfo != null) {
19085            final View v = mAttachInfo.mRootView;
19086            if (v != null) {
19087                return v;
19088            }
19089        }
19090
19091        View parent = this;
19092
19093        while (parent.mParent != null && parent.mParent instanceof View) {
19094            parent = (View) parent.mParent;
19095        }
19096
19097        return parent;
19098    }
19099
19100    /**
19101     * Transforms a motion event from view-local coordinates to on-screen
19102     * coordinates.
19103     *
19104     * @param ev the view-local motion event
19105     * @return false if the transformation could not be applied
19106     * @hide
19107     */
19108    public boolean toGlobalMotionEvent(MotionEvent ev) {
19109        final AttachInfo info = mAttachInfo;
19110        if (info == null) {
19111            return false;
19112        }
19113
19114        final Matrix m = info.mTmpMatrix;
19115        m.set(Matrix.IDENTITY_MATRIX);
19116        transformMatrixToGlobal(m);
19117        ev.transform(m);
19118        return true;
19119    }
19120
19121    /**
19122     * Transforms a motion event from on-screen coordinates to view-local
19123     * coordinates.
19124     *
19125     * @param ev the on-screen motion event
19126     * @return false if the transformation could not be applied
19127     * @hide
19128     */
19129    public boolean toLocalMotionEvent(MotionEvent ev) {
19130        final AttachInfo info = mAttachInfo;
19131        if (info == null) {
19132            return false;
19133        }
19134
19135        final Matrix m = info.mTmpMatrix;
19136        m.set(Matrix.IDENTITY_MATRIX);
19137        transformMatrixToLocal(m);
19138        ev.transform(m);
19139        return true;
19140    }
19141
19142    /**
19143     * Modifies the input matrix such that it maps view-local coordinates to
19144     * on-screen coordinates.
19145     *
19146     * @param m input matrix to modify
19147     * @hide
19148     */
19149    public void transformMatrixToGlobal(Matrix m) {
19150        final ViewParent parent = mParent;
19151        if (parent instanceof View) {
19152            final View vp = (View) parent;
19153            vp.transformMatrixToGlobal(m);
19154            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
19155        } else if (parent instanceof ViewRootImpl) {
19156            final ViewRootImpl vr = (ViewRootImpl) parent;
19157            vr.transformMatrixToGlobal(m);
19158            m.preTranslate(0, -vr.mCurScrollY);
19159        }
19160
19161        m.preTranslate(mLeft, mTop);
19162
19163        if (!hasIdentityMatrix()) {
19164            m.preConcat(getMatrix());
19165        }
19166    }
19167
19168    /**
19169     * Modifies the input matrix such that it maps on-screen coordinates to
19170     * view-local coordinates.
19171     *
19172     * @param m input matrix to modify
19173     * @hide
19174     */
19175    public void transformMatrixToLocal(Matrix m) {
19176        final ViewParent parent = mParent;
19177        if (parent instanceof View) {
19178            final View vp = (View) parent;
19179            vp.transformMatrixToLocal(m);
19180            m.postTranslate(vp.mScrollX, vp.mScrollY);
19181        } else if (parent instanceof ViewRootImpl) {
19182            final ViewRootImpl vr = (ViewRootImpl) parent;
19183            vr.transformMatrixToLocal(m);
19184            m.postTranslate(0, vr.mCurScrollY);
19185        }
19186
19187        m.postTranslate(-mLeft, -mTop);
19188
19189        if (!hasIdentityMatrix()) {
19190            m.postConcat(getInverseMatrix());
19191        }
19192    }
19193
19194    /**
19195     * @hide
19196     */
19197    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
19198            @ViewDebug.IntToString(from = 0, to = "x"),
19199            @ViewDebug.IntToString(from = 1, to = "y")
19200    })
19201    public int[] getLocationOnScreen() {
19202        int[] location = new int[2];
19203        getLocationOnScreen(location);
19204        return location;
19205    }
19206
19207    /**
19208     * <p>Computes the coordinates of this view on the screen. The argument
19209     * must be an array of two integers. After the method returns, the array
19210     * contains the x and y location in that order.</p>
19211     *
19212     * @param outLocation an array of two integers in which to hold the coordinates
19213     */
19214    public void getLocationOnScreen(@Size(2) int[] outLocation) {
19215        getLocationInWindow(outLocation);
19216
19217        final AttachInfo info = mAttachInfo;
19218        if (info != null) {
19219            outLocation[0] += info.mWindowLeft;
19220            outLocation[1] += info.mWindowTop;
19221        }
19222    }
19223
19224    /**
19225     * <p>Computes the coordinates of this view in its window. The argument
19226     * must be an array of two integers. After the method returns, the array
19227     * contains the x and y location in that order.</p>
19228     *
19229     * @param outLocation an array of two integers in which to hold the coordinates
19230     */
19231    public void getLocationInWindow(@Size(2) int[] outLocation) {
19232        if (outLocation == null || outLocation.length < 2) {
19233            throw new IllegalArgumentException("outLocation must be an array of two integers");
19234        }
19235
19236        outLocation[0] = 0;
19237        outLocation[1] = 0;
19238
19239        transformFromViewToWindowSpace(outLocation);
19240    }
19241
19242    /** @hide */
19243    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
19244        if (inOutLocation == null || inOutLocation.length < 2) {
19245            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
19246        }
19247
19248        if (mAttachInfo == null) {
19249            // When the view is not attached to a window, this method does not make sense
19250            inOutLocation[0] = inOutLocation[1] = 0;
19251            return;
19252        }
19253
19254        float position[] = mAttachInfo.mTmpTransformLocation;
19255        position[0] = inOutLocation[0];
19256        position[1] = inOutLocation[1];
19257
19258        if (!hasIdentityMatrix()) {
19259            getMatrix().mapPoints(position);
19260        }
19261
19262        position[0] += mLeft;
19263        position[1] += mTop;
19264
19265        ViewParent viewParent = mParent;
19266        while (viewParent instanceof View) {
19267            final View view = (View) viewParent;
19268
19269            position[0] -= view.mScrollX;
19270            position[1] -= view.mScrollY;
19271
19272            if (!view.hasIdentityMatrix()) {
19273                view.getMatrix().mapPoints(position);
19274            }
19275
19276            position[0] += view.mLeft;
19277            position[1] += view.mTop;
19278
19279            viewParent = view.mParent;
19280         }
19281
19282        if (viewParent instanceof ViewRootImpl) {
19283            // *cough*
19284            final ViewRootImpl vr = (ViewRootImpl) viewParent;
19285            position[1] -= vr.mCurScrollY;
19286        }
19287
19288        inOutLocation[0] = Math.round(position[0]);
19289        inOutLocation[1] = Math.round(position[1]);
19290    }
19291
19292    /**
19293     * {@hide}
19294     * @param id the id of the view to be found
19295     * @return the view of the specified id, null if cannot be found
19296     */
19297    protected View findViewTraversal(@IdRes int id) {
19298        if (id == mID) {
19299            return this;
19300        }
19301        return null;
19302    }
19303
19304    /**
19305     * {@hide}
19306     * @param tag the tag of the view to be found
19307     * @return the view of specified tag, null if cannot be found
19308     */
19309    protected View findViewWithTagTraversal(Object tag) {
19310        if (tag != null && tag.equals(mTag)) {
19311            return this;
19312        }
19313        return null;
19314    }
19315
19316    /**
19317     * {@hide}
19318     * @param predicate The predicate to evaluate.
19319     * @param childToSkip If not null, ignores this child during the recursive traversal.
19320     * @return The first view that matches the predicate or null.
19321     */
19322    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
19323        if (predicate.apply(this)) {
19324            return this;
19325        }
19326        return null;
19327    }
19328
19329    /**
19330     * Look for a child view with the given id.  If this view has the given
19331     * id, return this view.
19332     *
19333     * @param id The id to search for.
19334     * @return The view that has the given id in the hierarchy or null
19335     */
19336    @Nullable
19337    public final View findViewById(@IdRes int id) {
19338        if (id < 0) {
19339            return null;
19340        }
19341        return findViewTraversal(id);
19342    }
19343
19344    /**
19345     * Finds a view by its unuque and stable accessibility id.
19346     *
19347     * @param accessibilityId The searched accessibility id.
19348     * @return The found view.
19349     */
19350    final View findViewByAccessibilityId(int accessibilityId) {
19351        if (accessibilityId < 0) {
19352            return null;
19353        }
19354        View view = findViewByAccessibilityIdTraversal(accessibilityId);
19355        if (view != null) {
19356            return view.includeForAccessibility() ? view : null;
19357        }
19358        return null;
19359    }
19360
19361    /**
19362     * Performs the traversal to find a view by its unuque and stable accessibility id.
19363     *
19364     * <strong>Note:</strong>This method does not stop at the root namespace
19365     * boundary since the user can touch the screen at an arbitrary location
19366     * potentially crossing the root namespace bounday which will send an
19367     * accessibility event to accessibility services and they should be able
19368     * to obtain the event source. Also accessibility ids are guaranteed to be
19369     * unique in the window.
19370     *
19371     * @param accessibilityId The accessibility id.
19372     * @return The found view.
19373     *
19374     * @hide
19375     */
19376    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
19377        if (getAccessibilityViewId() == accessibilityId) {
19378            return this;
19379        }
19380        return null;
19381    }
19382
19383    /**
19384     * Look for a child view with the given tag.  If this view has the given
19385     * tag, return this view.
19386     *
19387     * @param tag The tag to search for, using "tag.equals(getTag())".
19388     * @return The View that has the given tag in the hierarchy or null
19389     */
19390    public final View findViewWithTag(Object tag) {
19391        if (tag == null) {
19392            return null;
19393        }
19394        return findViewWithTagTraversal(tag);
19395    }
19396
19397    /**
19398     * {@hide}
19399     * Look for a child view that matches the specified predicate.
19400     * If this view matches the predicate, return this view.
19401     *
19402     * @param predicate The predicate to evaluate.
19403     * @return The first view that matches the predicate or null.
19404     */
19405    public final View findViewByPredicate(Predicate<View> predicate) {
19406        return findViewByPredicateTraversal(predicate, null);
19407    }
19408
19409    /**
19410     * {@hide}
19411     * Look for a child view that matches the specified predicate,
19412     * starting with the specified view and its descendents and then
19413     * recusively searching the ancestors and siblings of that view
19414     * until this view is reached.
19415     *
19416     * This method is useful in cases where the predicate does not match
19417     * a single unique view (perhaps multiple views use the same id)
19418     * and we are trying to find the view that is "closest" in scope to the
19419     * starting view.
19420     *
19421     * @param start The view to start from.
19422     * @param predicate The predicate to evaluate.
19423     * @return The first view that matches the predicate or null.
19424     */
19425    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
19426        View childToSkip = null;
19427        for (;;) {
19428            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
19429            if (view != null || start == this) {
19430                return view;
19431            }
19432
19433            ViewParent parent = start.getParent();
19434            if (parent == null || !(parent instanceof View)) {
19435                return null;
19436            }
19437
19438            childToSkip = start;
19439            start = (View) parent;
19440        }
19441    }
19442
19443    /**
19444     * Sets the identifier for this view. The identifier does not have to be
19445     * unique in this view's hierarchy. The identifier should be a positive
19446     * number.
19447     *
19448     * @see #NO_ID
19449     * @see #getId()
19450     * @see #findViewById(int)
19451     *
19452     * @param id a number used to identify the view
19453     *
19454     * @attr ref android.R.styleable#View_id
19455     */
19456    public void setId(@IdRes int id) {
19457        mID = id;
19458        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
19459            mID = generateViewId();
19460        }
19461    }
19462
19463    /**
19464     * {@hide}
19465     *
19466     * @param isRoot true if the view belongs to the root namespace, false
19467     *        otherwise
19468     */
19469    public void setIsRootNamespace(boolean isRoot) {
19470        if (isRoot) {
19471            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
19472        } else {
19473            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
19474        }
19475    }
19476
19477    /**
19478     * {@hide}
19479     *
19480     * @return true if the view belongs to the root namespace, false otherwise
19481     */
19482    public boolean isRootNamespace() {
19483        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
19484    }
19485
19486    /**
19487     * Returns this view's identifier.
19488     *
19489     * @return a positive integer used to identify the view or {@link #NO_ID}
19490     *         if the view has no ID
19491     *
19492     * @see #setId(int)
19493     * @see #findViewById(int)
19494     * @attr ref android.R.styleable#View_id
19495     */
19496    @IdRes
19497    @ViewDebug.CapturedViewProperty
19498    public int getId() {
19499        return mID;
19500    }
19501
19502    /**
19503     * Returns this view's tag.
19504     *
19505     * @return the Object stored in this view as a tag, or {@code null} if not
19506     *         set
19507     *
19508     * @see #setTag(Object)
19509     * @see #getTag(int)
19510     */
19511    @ViewDebug.ExportedProperty
19512    public Object getTag() {
19513        return mTag;
19514    }
19515
19516    /**
19517     * Sets the tag associated with this view. A tag can be used to mark
19518     * a view in its hierarchy and does not have to be unique within the
19519     * hierarchy. Tags can also be used to store data within a view without
19520     * resorting to another data structure.
19521     *
19522     * @param tag an Object to tag the view with
19523     *
19524     * @see #getTag()
19525     * @see #setTag(int, Object)
19526     */
19527    public void setTag(final Object tag) {
19528        mTag = tag;
19529    }
19530
19531    /**
19532     * Returns the tag associated with this view and the specified key.
19533     *
19534     * @param key The key identifying the tag
19535     *
19536     * @return the Object stored in this view as a tag, or {@code null} if not
19537     *         set
19538     *
19539     * @see #setTag(int, Object)
19540     * @see #getTag()
19541     */
19542    public Object getTag(int key) {
19543        if (mKeyedTags != null) return mKeyedTags.get(key);
19544        return null;
19545    }
19546
19547    /**
19548     * Sets a tag associated with this view and a key. A tag can be used
19549     * to mark a view in its hierarchy and does not have to be unique within
19550     * the hierarchy. Tags can also be used to store data within a view
19551     * without resorting to another data structure.
19552     *
19553     * The specified key should be an id declared in the resources of the
19554     * application to ensure it is unique (see the <a
19555     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
19556     * Keys identified as belonging to
19557     * the Android framework or not associated with any package will cause
19558     * an {@link IllegalArgumentException} to be thrown.
19559     *
19560     * @param key The key identifying the tag
19561     * @param tag An Object to tag the view with
19562     *
19563     * @throws IllegalArgumentException If they specified key is not valid
19564     *
19565     * @see #setTag(Object)
19566     * @see #getTag(int)
19567     */
19568    public void setTag(int key, final Object tag) {
19569        // If the package id is 0x00 or 0x01, it's either an undefined package
19570        // or a framework id
19571        if ((key >>> 24) < 2) {
19572            throw new IllegalArgumentException("The key must be an application-specific "
19573                    + "resource id.");
19574        }
19575
19576        setKeyedTag(key, tag);
19577    }
19578
19579    /**
19580     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
19581     * framework id.
19582     *
19583     * @hide
19584     */
19585    public void setTagInternal(int key, Object tag) {
19586        if ((key >>> 24) != 0x1) {
19587            throw new IllegalArgumentException("The key must be a framework-specific "
19588                    + "resource id.");
19589        }
19590
19591        setKeyedTag(key, tag);
19592    }
19593
19594    private void setKeyedTag(int key, Object tag) {
19595        if (mKeyedTags == null) {
19596            mKeyedTags = new SparseArray<Object>(2);
19597        }
19598
19599        mKeyedTags.put(key, tag);
19600    }
19601
19602    /**
19603     * Prints information about this view in the log output, with the tag
19604     * {@link #VIEW_LOG_TAG}.
19605     *
19606     * @hide
19607     */
19608    public void debug() {
19609        debug(0);
19610    }
19611
19612    /**
19613     * Prints information about this view in the log output, with the tag
19614     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
19615     * indentation defined by the <code>depth</code>.
19616     *
19617     * @param depth the indentation level
19618     *
19619     * @hide
19620     */
19621    protected void debug(int depth) {
19622        String output = debugIndent(depth - 1);
19623
19624        output += "+ " + this;
19625        int id = getId();
19626        if (id != -1) {
19627            output += " (id=" + id + ")";
19628        }
19629        Object tag = getTag();
19630        if (tag != null) {
19631            output += " (tag=" + tag + ")";
19632        }
19633        Log.d(VIEW_LOG_TAG, output);
19634
19635        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
19636            output = debugIndent(depth) + " FOCUSED";
19637            Log.d(VIEW_LOG_TAG, output);
19638        }
19639
19640        output = debugIndent(depth);
19641        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
19642                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
19643                + "} ";
19644        Log.d(VIEW_LOG_TAG, output);
19645
19646        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
19647                || mPaddingBottom != 0) {
19648            output = debugIndent(depth);
19649            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
19650                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
19651            Log.d(VIEW_LOG_TAG, output);
19652        }
19653
19654        output = debugIndent(depth);
19655        output += "mMeasureWidth=" + mMeasuredWidth +
19656                " mMeasureHeight=" + mMeasuredHeight;
19657        Log.d(VIEW_LOG_TAG, output);
19658
19659        output = debugIndent(depth);
19660        if (mLayoutParams == null) {
19661            output += "BAD! no layout params";
19662        } else {
19663            output = mLayoutParams.debug(output);
19664        }
19665        Log.d(VIEW_LOG_TAG, output);
19666
19667        output = debugIndent(depth);
19668        output += "flags={";
19669        output += View.printFlags(mViewFlags);
19670        output += "}";
19671        Log.d(VIEW_LOG_TAG, output);
19672
19673        output = debugIndent(depth);
19674        output += "privateFlags={";
19675        output += View.printPrivateFlags(mPrivateFlags);
19676        output += "}";
19677        Log.d(VIEW_LOG_TAG, output);
19678    }
19679
19680    /**
19681     * Creates a string of whitespaces used for indentation.
19682     *
19683     * @param depth the indentation level
19684     * @return a String containing (depth * 2 + 3) * 2 white spaces
19685     *
19686     * @hide
19687     */
19688    protected static String debugIndent(int depth) {
19689        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
19690        for (int i = 0; i < (depth * 2) + 3; i++) {
19691            spaces.append(' ').append(' ');
19692        }
19693        return spaces.toString();
19694    }
19695
19696    /**
19697     * <p>Return the offset of the widget's text baseline from the widget's top
19698     * boundary. If this widget does not support baseline alignment, this
19699     * method returns -1. </p>
19700     *
19701     * @return the offset of the baseline within the widget's bounds or -1
19702     *         if baseline alignment is not supported
19703     */
19704    @ViewDebug.ExportedProperty(category = "layout")
19705    public int getBaseline() {
19706        return -1;
19707    }
19708
19709    /**
19710     * Returns whether the view hierarchy is currently undergoing a layout pass. This
19711     * information is useful to avoid situations such as calling {@link #requestLayout()} during
19712     * a layout pass.
19713     *
19714     * @return whether the view hierarchy is currently undergoing a layout pass
19715     */
19716    public boolean isInLayout() {
19717        ViewRootImpl viewRoot = getViewRootImpl();
19718        return (viewRoot != null && viewRoot.isInLayout());
19719    }
19720
19721    /**
19722     * Call this when something has changed which has invalidated the
19723     * layout of this view. This will schedule a layout pass of the view
19724     * tree. This should not be called while the view hierarchy is currently in a layout
19725     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
19726     * end of the current layout pass (and then layout will run again) or after the current
19727     * frame is drawn and the next layout occurs.
19728     *
19729     * <p>Subclasses which override this method should call the superclass method to
19730     * handle possible request-during-layout errors correctly.</p>
19731     */
19732    @CallSuper
19733    public void requestLayout() {
19734        if (mMeasureCache != null) mMeasureCache.clear();
19735
19736        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
19737            // Only trigger request-during-layout logic if this is the view requesting it,
19738            // not the views in its parent hierarchy
19739            ViewRootImpl viewRoot = getViewRootImpl();
19740            if (viewRoot != null && viewRoot.isInLayout()) {
19741                if (!viewRoot.requestLayoutDuringLayout(this)) {
19742                    return;
19743                }
19744            }
19745            mAttachInfo.mViewRequestingLayout = this;
19746        }
19747
19748        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19749        mPrivateFlags |= PFLAG_INVALIDATED;
19750
19751        if (mParent != null && !mParent.isLayoutRequested()) {
19752            mParent.requestLayout();
19753        }
19754        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
19755            mAttachInfo.mViewRequestingLayout = null;
19756        }
19757    }
19758
19759    /**
19760     * Forces this view to be laid out during the next layout pass.
19761     * This method does not call requestLayout() or forceLayout()
19762     * on the parent.
19763     */
19764    public void forceLayout() {
19765        if (mMeasureCache != null) mMeasureCache.clear();
19766
19767        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19768        mPrivateFlags |= PFLAG_INVALIDATED;
19769    }
19770
19771    /**
19772     * <p>
19773     * This is called to find out how big a view should be. The parent
19774     * supplies constraint information in the width and height parameters.
19775     * </p>
19776     *
19777     * <p>
19778     * The actual measurement work of a view is performed in
19779     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
19780     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
19781     * </p>
19782     *
19783     *
19784     * @param widthMeasureSpec Horizontal space requirements as imposed by the
19785     *        parent
19786     * @param heightMeasureSpec Vertical space requirements as imposed by the
19787     *        parent
19788     *
19789     * @see #onMeasure(int, int)
19790     */
19791    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
19792        boolean optical = isLayoutModeOptical(this);
19793        if (optical != isLayoutModeOptical(mParent)) {
19794            Insets insets = getOpticalInsets();
19795            int oWidth  = insets.left + insets.right;
19796            int oHeight = insets.top  + insets.bottom;
19797            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
19798            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
19799        }
19800
19801        // Suppress sign extension for the low bytes
19802        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
19803        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
19804
19805        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19806
19807        // Optimize layout by avoiding an extra EXACTLY pass when the view is
19808        // already measured as the correct size. In API 23 and below, this
19809        // extra pass is required to make LinearLayout re-distribute weight.
19810        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
19811                || heightMeasureSpec != mOldHeightMeasureSpec;
19812        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
19813                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
19814        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
19815                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
19816        final boolean needsLayout = specChanged
19817                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
19818
19819        if (forceLayout || needsLayout) {
19820            // first clears the measured dimension flag
19821            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
19822
19823            resolveRtlPropertiesIfNeeded();
19824
19825            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
19826            if (cacheIndex < 0 || sIgnoreMeasureCache) {
19827                // measure ourselves, this should set the measured dimension flag back
19828                onMeasure(widthMeasureSpec, heightMeasureSpec);
19829                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19830            } else {
19831                long value = mMeasureCache.valueAt(cacheIndex);
19832                // Casting a long to int drops the high 32 bits, no mask needed
19833                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
19834                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19835            }
19836
19837            // flag not set, setMeasuredDimension() was not invoked, we raise
19838            // an exception to warn the developer
19839            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
19840                throw new IllegalStateException("View with id " + getId() + ": "
19841                        + getClass().getName() + "#onMeasure() did not set the"
19842                        + " measured dimension by calling"
19843                        + " setMeasuredDimension()");
19844            }
19845
19846            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
19847        }
19848
19849        mOldWidthMeasureSpec = widthMeasureSpec;
19850        mOldHeightMeasureSpec = heightMeasureSpec;
19851
19852        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
19853                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
19854    }
19855
19856    /**
19857     * <p>
19858     * Measure the view and its content to determine the measured width and the
19859     * measured height. This method is invoked by {@link #measure(int, int)} and
19860     * should be overridden by subclasses to provide accurate and efficient
19861     * measurement of their contents.
19862     * </p>
19863     *
19864     * <p>
19865     * <strong>CONTRACT:</strong> When overriding this method, you
19866     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
19867     * measured width and height of this view. Failure to do so will trigger an
19868     * <code>IllegalStateException</code>, thrown by
19869     * {@link #measure(int, int)}. Calling the superclass'
19870     * {@link #onMeasure(int, int)} is a valid use.
19871     * </p>
19872     *
19873     * <p>
19874     * The base class implementation of measure defaults to the background size,
19875     * unless a larger size is allowed by the MeasureSpec. Subclasses should
19876     * override {@link #onMeasure(int, int)} to provide better measurements of
19877     * their content.
19878     * </p>
19879     *
19880     * <p>
19881     * If this method is overridden, it is the subclass's responsibility to make
19882     * sure the measured height and width are at least the view's minimum height
19883     * and width ({@link #getSuggestedMinimumHeight()} and
19884     * {@link #getSuggestedMinimumWidth()}).
19885     * </p>
19886     *
19887     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
19888     *                         The requirements are encoded with
19889     *                         {@link android.view.View.MeasureSpec}.
19890     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19891     *                         The requirements are encoded with
19892     *                         {@link android.view.View.MeasureSpec}.
19893     *
19894     * @see #getMeasuredWidth()
19895     * @see #getMeasuredHeight()
19896     * @see #setMeasuredDimension(int, int)
19897     * @see #getSuggestedMinimumHeight()
19898     * @see #getSuggestedMinimumWidth()
19899     * @see android.view.View.MeasureSpec#getMode(int)
19900     * @see android.view.View.MeasureSpec#getSize(int)
19901     */
19902    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19903        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19904                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19905    }
19906
19907    /**
19908     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19909     * measured width and measured height. Failing to do so will trigger an
19910     * exception at measurement time.</p>
19911     *
19912     * @param measuredWidth The measured width of this view.  May be a complex
19913     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19914     * {@link #MEASURED_STATE_TOO_SMALL}.
19915     * @param measuredHeight The measured height of this view.  May be a complex
19916     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19917     * {@link #MEASURED_STATE_TOO_SMALL}.
19918     */
19919    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19920        boolean optical = isLayoutModeOptical(this);
19921        if (optical != isLayoutModeOptical(mParent)) {
19922            Insets insets = getOpticalInsets();
19923            int opticalWidth  = insets.left + insets.right;
19924            int opticalHeight = insets.top  + insets.bottom;
19925
19926            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
19927            measuredHeight += optical ? opticalHeight : -opticalHeight;
19928        }
19929        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19930    }
19931
19932    /**
19933     * Sets the measured dimension without extra processing for things like optical bounds.
19934     * Useful for reapplying consistent values that have already been cooked with adjustments
19935     * for optical bounds, etc. such as those from the measurement cache.
19936     *
19937     * @param measuredWidth The measured width of this view.  May be a complex
19938     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19939     * {@link #MEASURED_STATE_TOO_SMALL}.
19940     * @param measuredHeight The measured height of this view.  May be a complex
19941     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19942     * {@link #MEASURED_STATE_TOO_SMALL}.
19943     */
19944    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19945        mMeasuredWidth = measuredWidth;
19946        mMeasuredHeight = measuredHeight;
19947
19948        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19949    }
19950
19951    /**
19952     * Merge two states as returned by {@link #getMeasuredState()}.
19953     * @param curState The current state as returned from a view or the result
19954     * of combining multiple views.
19955     * @param newState The new view state to combine.
19956     * @return Returns a new integer reflecting the combination of the two
19957     * states.
19958     */
19959    public static int combineMeasuredStates(int curState, int newState) {
19960        return curState | newState;
19961    }
19962
19963    /**
19964     * Version of {@link #resolveSizeAndState(int, int, int)}
19965     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
19966     */
19967    public static int resolveSize(int size, int measureSpec) {
19968        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
19969    }
19970
19971    /**
19972     * Utility to reconcile a desired size and state, with constraints imposed
19973     * by a MeasureSpec. Will take the desired size, unless a different size
19974     * is imposed by the constraints. The returned value is a compound integer,
19975     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
19976     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
19977     * resulting size is smaller than the size the view wants to be.
19978     *
19979     * @param size How big the view wants to be.
19980     * @param measureSpec Constraints imposed by the parent.
19981     * @param childMeasuredState Size information bit mask for the view's
19982     *                           children.
19983     * @return Size information bit mask as defined by
19984     *         {@link #MEASURED_SIZE_MASK} and
19985     *         {@link #MEASURED_STATE_TOO_SMALL}.
19986     */
19987    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
19988        final int specMode = MeasureSpec.getMode(measureSpec);
19989        final int specSize = MeasureSpec.getSize(measureSpec);
19990        final int result;
19991        switch (specMode) {
19992            case MeasureSpec.AT_MOST:
19993                if (specSize < size) {
19994                    result = specSize | MEASURED_STATE_TOO_SMALL;
19995                } else {
19996                    result = size;
19997                }
19998                break;
19999            case MeasureSpec.EXACTLY:
20000                result = specSize;
20001                break;
20002            case MeasureSpec.UNSPECIFIED:
20003            default:
20004                result = size;
20005        }
20006        return result | (childMeasuredState & MEASURED_STATE_MASK);
20007    }
20008
20009    /**
20010     * Utility to return a default size. Uses the supplied size if the
20011     * MeasureSpec imposed no constraints. Will get larger if allowed
20012     * by the MeasureSpec.
20013     *
20014     * @param size Default size for this view
20015     * @param measureSpec Constraints imposed by the parent
20016     * @return The size this view should be.
20017     */
20018    public static int getDefaultSize(int size, int measureSpec) {
20019        int result = size;
20020        int specMode = MeasureSpec.getMode(measureSpec);
20021        int specSize = MeasureSpec.getSize(measureSpec);
20022
20023        switch (specMode) {
20024        case MeasureSpec.UNSPECIFIED:
20025            result = size;
20026            break;
20027        case MeasureSpec.AT_MOST:
20028        case MeasureSpec.EXACTLY:
20029            result = specSize;
20030            break;
20031        }
20032        return result;
20033    }
20034
20035    /**
20036     * Returns the suggested minimum height that the view should use. This
20037     * returns the maximum of the view's minimum height
20038     * and the background's minimum height
20039     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
20040     * <p>
20041     * When being used in {@link #onMeasure(int, int)}, the caller should still
20042     * ensure the returned height is within the requirements of the parent.
20043     *
20044     * @return The suggested minimum height of the view.
20045     */
20046    protected int getSuggestedMinimumHeight() {
20047        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
20048
20049    }
20050
20051    /**
20052     * Returns the suggested minimum width that the view should use. This
20053     * returns the maximum of the view's minimum width
20054     * and the background's minimum width
20055     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
20056     * <p>
20057     * When being used in {@link #onMeasure(int, int)}, the caller should still
20058     * ensure the returned width is within the requirements of the parent.
20059     *
20060     * @return The suggested minimum width of the view.
20061     */
20062    protected int getSuggestedMinimumWidth() {
20063        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
20064    }
20065
20066    /**
20067     * Returns the minimum height of the view.
20068     *
20069     * @return the minimum height the view will try to be.
20070     *
20071     * @see #setMinimumHeight(int)
20072     *
20073     * @attr ref android.R.styleable#View_minHeight
20074     */
20075    public int getMinimumHeight() {
20076        return mMinHeight;
20077    }
20078
20079    /**
20080     * Sets the minimum height of the view. It is not guaranteed the view will
20081     * be able to achieve this minimum height (for example, if its parent layout
20082     * constrains it with less available height).
20083     *
20084     * @param minHeight The minimum height the view will try to be.
20085     *
20086     * @see #getMinimumHeight()
20087     *
20088     * @attr ref android.R.styleable#View_minHeight
20089     */
20090    @RemotableViewMethod
20091    public void setMinimumHeight(int minHeight) {
20092        mMinHeight = minHeight;
20093        requestLayout();
20094    }
20095
20096    /**
20097     * Returns the minimum width of the view.
20098     *
20099     * @return the minimum width the view will try to be.
20100     *
20101     * @see #setMinimumWidth(int)
20102     *
20103     * @attr ref android.R.styleable#View_minWidth
20104     */
20105    public int getMinimumWidth() {
20106        return mMinWidth;
20107    }
20108
20109    /**
20110     * Sets the minimum width of the view. It is not guaranteed the view will
20111     * be able to achieve this minimum width (for example, if its parent layout
20112     * constrains it with less available width).
20113     *
20114     * @param minWidth The minimum width the view will try to be.
20115     *
20116     * @see #getMinimumWidth()
20117     *
20118     * @attr ref android.R.styleable#View_minWidth
20119     */
20120    public void setMinimumWidth(int minWidth) {
20121        mMinWidth = minWidth;
20122        requestLayout();
20123
20124    }
20125
20126    /**
20127     * Get the animation currently associated with this view.
20128     *
20129     * @return The animation that is currently playing or
20130     *         scheduled to play for this view.
20131     */
20132    public Animation getAnimation() {
20133        return mCurrentAnimation;
20134    }
20135
20136    /**
20137     * Start the specified animation now.
20138     *
20139     * @param animation the animation to start now
20140     */
20141    public void startAnimation(Animation animation) {
20142        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
20143        setAnimation(animation);
20144        invalidateParentCaches();
20145        invalidate(true);
20146    }
20147
20148    /**
20149     * Cancels any animations for this view.
20150     */
20151    public void clearAnimation() {
20152        if (mCurrentAnimation != null) {
20153            mCurrentAnimation.detach();
20154        }
20155        mCurrentAnimation = null;
20156        invalidateParentIfNeeded();
20157    }
20158
20159    /**
20160     * Sets the next animation to play for this view.
20161     * If you want the animation to play immediately, use
20162     * {@link #startAnimation(android.view.animation.Animation)} instead.
20163     * This method provides allows fine-grained
20164     * control over the start time and invalidation, but you
20165     * must make sure that 1) the animation has a start time set, and
20166     * 2) the view's parent (which controls animations on its children)
20167     * will be invalidated when the animation is supposed to
20168     * start.
20169     *
20170     * @param animation The next animation, or null.
20171     */
20172    public void setAnimation(Animation animation) {
20173        mCurrentAnimation = animation;
20174
20175        if (animation != null) {
20176            // If the screen is off assume the animation start time is now instead of
20177            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
20178            // would cause the animation to start when the screen turns back on
20179            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
20180                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
20181                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
20182            }
20183            animation.reset();
20184        }
20185    }
20186
20187    /**
20188     * Invoked by a parent ViewGroup to notify the start of the animation
20189     * currently associated with this view. If you override this method,
20190     * always call super.onAnimationStart();
20191     *
20192     * @see #setAnimation(android.view.animation.Animation)
20193     * @see #getAnimation()
20194     */
20195    @CallSuper
20196    protected void onAnimationStart() {
20197        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
20198    }
20199
20200    /**
20201     * Invoked by a parent ViewGroup to notify the end of the animation
20202     * currently associated with this view. If you override this method,
20203     * always call super.onAnimationEnd();
20204     *
20205     * @see #setAnimation(android.view.animation.Animation)
20206     * @see #getAnimation()
20207     */
20208    @CallSuper
20209    protected void onAnimationEnd() {
20210        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
20211    }
20212
20213    /**
20214     * Invoked if there is a Transform that involves alpha. Subclass that can
20215     * draw themselves with the specified alpha should return true, and then
20216     * respect that alpha when their onDraw() is called. If this returns false
20217     * then the view may be redirected to draw into an offscreen buffer to
20218     * fulfill the request, which will look fine, but may be slower than if the
20219     * subclass handles it internally. The default implementation returns false.
20220     *
20221     * @param alpha The alpha (0..255) to apply to the view's drawing
20222     * @return true if the view can draw with the specified alpha.
20223     */
20224    protected boolean onSetAlpha(int alpha) {
20225        return false;
20226    }
20227
20228    /**
20229     * This is used by the RootView to perform an optimization when
20230     * the view hierarchy contains one or several SurfaceView.
20231     * SurfaceView is always considered transparent, but its children are not,
20232     * therefore all View objects remove themselves from the global transparent
20233     * region (passed as a parameter to this function).
20234     *
20235     * @param region The transparent region for this ViewAncestor (window).
20236     *
20237     * @return Returns true if the effective visibility of the view at this
20238     * point is opaque, regardless of the transparent region; returns false
20239     * if it is possible for underlying windows to be seen behind the view.
20240     *
20241     * {@hide}
20242     */
20243    public boolean gatherTransparentRegion(Region region) {
20244        final AttachInfo attachInfo = mAttachInfo;
20245        if (region != null && attachInfo != null) {
20246            final int pflags = mPrivateFlags;
20247            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
20248                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
20249                // remove it from the transparent region.
20250                final int[] location = attachInfo.mTransparentLocation;
20251                getLocationInWindow(location);
20252                region.op(location[0], location[1], location[0] + mRight - mLeft,
20253                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
20254            } else {
20255                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
20256                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
20257                    // the background drawable's non-transparent parts from this transparent region.
20258                    applyDrawableToTransparentRegion(mBackground, region);
20259                }
20260                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20261                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
20262                    // Similarly, we remove the foreground drawable's non-transparent parts.
20263                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
20264                }
20265            }
20266        }
20267        return true;
20268    }
20269
20270    /**
20271     * Play a sound effect for this view.
20272     *
20273     * <p>The framework will play sound effects for some built in actions, such as
20274     * clicking, but you may wish to play these effects in your widget,
20275     * for instance, for internal navigation.
20276     *
20277     * <p>The sound effect will only be played if sound effects are enabled by the user, and
20278     * {@link #isSoundEffectsEnabled()} is true.
20279     *
20280     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
20281     */
20282    public void playSoundEffect(int soundConstant) {
20283        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
20284            return;
20285        }
20286        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
20287    }
20288
20289    /**
20290     * BZZZTT!!1!
20291     *
20292     * <p>Provide haptic feedback to the user for this view.
20293     *
20294     * <p>The framework will provide haptic feedback for some built in actions,
20295     * such as long presses, but you may wish to provide feedback for your
20296     * own widget.
20297     *
20298     * <p>The feedback will only be performed if
20299     * {@link #isHapticFeedbackEnabled()} is true.
20300     *
20301     * @param feedbackConstant One of the constants defined in
20302     * {@link HapticFeedbackConstants}
20303     */
20304    public boolean performHapticFeedback(int feedbackConstant) {
20305        return performHapticFeedback(feedbackConstant, 0);
20306    }
20307
20308    /**
20309     * BZZZTT!!1!
20310     *
20311     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
20312     *
20313     * @param feedbackConstant One of the constants defined in
20314     * {@link HapticFeedbackConstants}
20315     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
20316     */
20317    public boolean performHapticFeedback(int feedbackConstant, int flags) {
20318        if (mAttachInfo == null) {
20319            return false;
20320        }
20321        //noinspection SimplifiableIfStatement
20322        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
20323                && !isHapticFeedbackEnabled()) {
20324            return false;
20325        }
20326        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
20327                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
20328    }
20329
20330    /**
20331     * Request that the visibility of the status bar or other screen/window
20332     * decorations be changed.
20333     *
20334     * <p>This method is used to put the over device UI into temporary modes
20335     * where the user's attention is focused more on the application content,
20336     * by dimming or hiding surrounding system affordances.  This is typically
20337     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
20338     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
20339     * to be placed behind the action bar (and with these flags other system
20340     * affordances) so that smooth transitions between hiding and showing them
20341     * can be done.
20342     *
20343     * <p>Two representative examples of the use of system UI visibility is
20344     * implementing a content browsing application (like a magazine reader)
20345     * and a video playing application.
20346     *
20347     * <p>The first code shows a typical implementation of a View in a content
20348     * browsing application.  In this implementation, the application goes
20349     * into a content-oriented mode by hiding the status bar and action bar,
20350     * and putting the navigation elements into lights out mode.  The user can
20351     * then interact with content while in this mode.  Such an application should
20352     * provide an easy way for the user to toggle out of the mode (such as to
20353     * check information in the status bar or access notifications).  In the
20354     * implementation here, this is done simply by tapping on the content.
20355     *
20356     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
20357     *      content}
20358     *
20359     * <p>This second code sample shows a typical implementation of a View
20360     * in a video playing application.  In this situation, while the video is
20361     * playing the application would like to go into a complete full-screen mode,
20362     * to use as much of the display as possible for the video.  When in this state
20363     * the user can not interact with the application; the system intercepts
20364     * touching on the screen to pop the UI out of full screen mode.  See
20365     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
20366     *
20367     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
20368     *      content}
20369     *
20370     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20371     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20372     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20373     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20374     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20375     */
20376    public void setSystemUiVisibility(int visibility) {
20377        if (visibility != mSystemUiVisibility) {
20378            mSystemUiVisibility = visibility;
20379            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20380                mParent.recomputeViewAttributes(this);
20381            }
20382        }
20383    }
20384
20385    /**
20386     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
20387     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20388     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20389     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20390     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20391     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20392     */
20393    public int getSystemUiVisibility() {
20394        return mSystemUiVisibility;
20395    }
20396
20397    /**
20398     * Returns the current system UI visibility that is currently set for
20399     * the entire window.  This is the combination of the
20400     * {@link #setSystemUiVisibility(int)} values supplied by all of the
20401     * views in the window.
20402     */
20403    public int getWindowSystemUiVisibility() {
20404        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
20405    }
20406
20407    /**
20408     * Override to find out when the window's requested system UI visibility
20409     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
20410     * This is different from the callbacks received through
20411     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
20412     * in that this is only telling you about the local request of the window,
20413     * not the actual values applied by the system.
20414     */
20415    public void onWindowSystemUiVisibilityChanged(int visible) {
20416    }
20417
20418    /**
20419     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
20420     * the view hierarchy.
20421     */
20422    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
20423        onWindowSystemUiVisibilityChanged(visible);
20424    }
20425
20426    /**
20427     * Set a listener to receive callbacks when the visibility of the system bar changes.
20428     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
20429     */
20430    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
20431        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
20432        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20433            mParent.recomputeViewAttributes(this);
20434        }
20435    }
20436
20437    /**
20438     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
20439     * the view hierarchy.
20440     */
20441    public void dispatchSystemUiVisibilityChanged(int visibility) {
20442        ListenerInfo li = mListenerInfo;
20443        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
20444            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
20445                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
20446        }
20447    }
20448
20449    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
20450        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
20451        if (val != mSystemUiVisibility) {
20452            setSystemUiVisibility(val);
20453            return true;
20454        }
20455        return false;
20456    }
20457
20458    /** @hide */
20459    public void setDisabledSystemUiVisibility(int flags) {
20460        if (mAttachInfo != null) {
20461            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
20462                mAttachInfo.mDisabledSystemUiVisibility = flags;
20463                if (mParent != null) {
20464                    mParent.recomputeViewAttributes(this);
20465                }
20466            }
20467        }
20468    }
20469
20470    /**
20471     * Creates an image that the system displays during the drag and drop
20472     * operation. This is called a &quot;drag shadow&quot;. The default implementation
20473     * for a DragShadowBuilder based on a View returns an image that has exactly the same
20474     * appearance as the given View. The default also positions the center of the drag shadow
20475     * directly under the touch point. If no View is provided (the constructor with no parameters
20476     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
20477     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
20478     * default is an invisible drag shadow.
20479     * <p>
20480     * You are not required to use the View you provide to the constructor as the basis of the
20481     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
20482     * anything you want as the drag shadow.
20483     * </p>
20484     * <p>
20485     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
20486     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
20487     *  size and position of the drag shadow. It uses this data to construct a
20488     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
20489     *  so that your application can draw the shadow image in the Canvas.
20490     * </p>
20491     *
20492     * <div class="special reference">
20493     * <h3>Developer Guides</h3>
20494     * <p>For a guide to implementing drag and drop features, read the
20495     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20496     * </div>
20497     */
20498    public static class DragShadowBuilder {
20499        private final WeakReference<View> mView;
20500
20501        /**
20502         * Constructs a shadow image builder based on a View. By default, the resulting drag
20503         * shadow will have the same appearance and dimensions as the View, with the touch point
20504         * over the center of the View.
20505         * @param view A View. Any View in scope can be used.
20506         */
20507        public DragShadowBuilder(View view) {
20508            mView = new WeakReference<View>(view);
20509        }
20510
20511        /**
20512         * Construct a shadow builder object with no associated View.  This
20513         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
20514         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
20515         * to supply the drag shadow's dimensions and appearance without
20516         * reference to any View object. If they are not overridden, then the result is an
20517         * invisible drag shadow.
20518         */
20519        public DragShadowBuilder() {
20520            mView = new WeakReference<View>(null);
20521        }
20522
20523        /**
20524         * Returns the View object that had been passed to the
20525         * {@link #View.DragShadowBuilder(View)}
20526         * constructor.  If that View parameter was {@code null} or if the
20527         * {@link #View.DragShadowBuilder()}
20528         * constructor was used to instantiate the builder object, this method will return
20529         * null.
20530         *
20531         * @return The View object associate with this builder object.
20532         */
20533        @SuppressWarnings({"JavadocReference"})
20534        final public View getView() {
20535            return mView.get();
20536        }
20537
20538        /**
20539         * Provides the metrics for the shadow image. These include the dimensions of
20540         * the shadow image, and the point within that shadow that should
20541         * be centered under the touch location while dragging.
20542         * <p>
20543         * The default implementation sets the dimensions of the shadow to be the
20544         * same as the dimensions of the View itself and centers the shadow under
20545         * the touch point.
20546         * </p>
20547         *
20548         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
20549         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
20550         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
20551         * image.
20552         *
20553         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
20554         * shadow image that should be underneath the touch point during the drag and drop
20555         * operation. Your application must set {@link android.graphics.Point#x} to the
20556         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
20557         */
20558        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
20559            final View view = mView.get();
20560            if (view != null) {
20561                outShadowSize.set(view.getWidth(), view.getHeight());
20562                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
20563            } else {
20564                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
20565            }
20566        }
20567
20568        /**
20569         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
20570         * based on the dimensions it received from the
20571         * {@link #onProvideShadowMetrics(Point, Point)} callback.
20572         *
20573         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
20574         */
20575        public void onDrawShadow(Canvas canvas) {
20576            final View view = mView.get();
20577            if (view != null) {
20578                view.draw(canvas);
20579            } else {
20580                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
20581            }
20582        }
20583    }
20584
20585    /**
20586     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
20587     * startDragAndDrop()} for newer platform versions.
20588     */
20589    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
20590                                   Object myLocalState, int flags) {
20591        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
20592    }
20593
20594    /**
20595     * Starts a drag and drop operation. When your application calls this method, it passes a
20596     * {@link android.view.View.DragShadowBuilder} object to the system. The
20597     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
20598     * to get metrics for the drag shadow, and then calls the object's
20599     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
20600     * <p>
20601     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
20602     *  drag events to all the View objects in your application that are currently visible. It does
20603     *  this either by calling the View object's drag listener (an implementation of
20604     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
20605     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
20606     *  Both are passed a {@link android.view.DragEvent} object that has a
20607     *  {@link android.view.DragEvent#getAction()} value of
20608     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
20609     * </p>
20610     * <p>
20611     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
20612     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
20613     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
20614     * to the View the user selected for dragging.
20615     * </p>
20616     * @param data A {@link android.content.ClipData} object pointing to the data to be
20617     * transferred by the drag and drop operation.
20618     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20619     * drag shadow.
20620     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
20621     * drop operation. This Object is put into every DragEvent object sent by the system during the
20622     * current drag.
20623     * <p>
20624     * myLocalState is a lightweight mechanism for the sending information from the dragged View
20625     * to the target Views. For example, it can contain flags that differentiate between a
20626     * a copy operation and a move operation.
20627     * </p>
20628     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
20629     * flags, or any combination of the following:
20630     *     <ul>
20631     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
20632     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
20633     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
20634     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
20635     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
20636     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
20637     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
20638     *     </ul>
20639     * @return {@code true} if the method completes successfully, or
20640     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
20641     * do a drag, and so no drag operation is in progress.
20642     */
20643    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
20644            Object myLocalState, int flags) {
20645        if (ViewDebug.DEBUG_DRAG) {
20646            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
20647        }
20648        if (mAttachInfo == null) {
20649            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
20650            return false;
20651        }
20652        boolean okay = false;
20653
20654        Point shadowSize = new Point();
20655        Point shadowTouchPoint = new Point();
20656        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
20657
20658        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
20659                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
20660            throw new IllegalStateException("Drag shadow dimensions must not be negative");
20661        }
20662
20663        if (ViewDebug.DEBUG_DRAG) {
20664            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
20665                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
20666        }
20667        if (mAttachInfo.mDragSurface != null) {
20668            mAttachInfo.mDragSurface.release();
20669        }
20670        mAttachInfo.mDragSurface = new Surface();
20671        try {
20672            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
20673                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
20674            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
20675                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
20676            if (mAttachInfo.mDragToken != null) {
20677                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20678                try {
20679                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20680                    shadowBuilder.onDrawShadow(canvas);
20681                } finally {
20682                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20683                }
20684
20685                final ViewRootImpl root = getViewRootImpl();
20686
20687                // Cache the local state object for delivery with DragEvents
20688                root.setLocalDragState(myLocalState);
20689
20690                // repurpose 'shadowSize' for the last touch point
20691                root.getLastTouchPoint(shadowSize);
20692
20693                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
20694                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
20695                        shadowTouchPoint.x, shadowTouchPoint.y, data);
20696                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
20697            }
20698        } catch (Exception e) {
20699            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
20700            mAttachInfo.mDragSurface.destroy();
20701            mAttachInfo.mDragSurface = null;
20702        }
20703
20704        return okay;
20705    }
20706
20707    /**
20708     * Cancels an ongoing drag and drop operation.
20709     * <p>
20710     * A {@link android.view.DragEvent} object with
20711     * {@link android.view.DragEvent#getAction()} value of
20712     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
20713     * {@link android.view.DragEvent#getResult()} value of {@code false}
20714     * will be sent to every
20715     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
20716     * even if they are not currently visible.
20717     * </p>
20718     * <p>
20719     * This method can be called on any View in the same window as the View on which
20720     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
20721     * was called.
20722     * </p>
20723     */
20724    public final void cancelDragAndDrop() {
20725        if (ViewDebug.DEBUG_DRAG) {
20726            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
20727        }
20728        if (mAttachInfo == null) {
20729            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
20730            return;
20731        }
20732        if (mAttachInfo.mDragToken != null) {
20733            try {
20734                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
20735            } catch (Exception e) {
20736                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
20737            }
20738            mAttachInfo.mDragToken = null;
20739        } else {
20740            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
20741        }
20742    }
20743
20744    /**
20745     * Updates the drag shadow for the ongoing drag and drop operation.
20746     *
20747     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20748     * new drag shadow.
20749     */
20750    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
20751        if (ViewDebug.DEBUG_DRAG) {
20752            Log.d(VIEW_LOG_TAG, "updateDragShadow");
20753        }
20754        if (mAttachInfo == null) {
20755            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
20756            return;
20757        }
20758        if (mAttachInfo.mDragToken != null) {
20759            try {
20760                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20761                try {
20762                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20763                    shadowBuilder.onDrawShadow(canvas);
20764                } finally {
20765                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20766                }
20767            } catch (Exception e) {
20768                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
20769            }
20770        } else {
20771            Log.e(VIEW_LOG_TAG, "No active drag");
20772        }
20773    }
20774
20775    /**
20776     * Starts a move from {startX, startY}, the amount of the movement will be the offset
20777     * between {startX, startY} and the new cursor positon.
20778     * @param startX horizontal coordinate where the move started.
20779     * @param startY vertical coordinate where the move started.
20780     * @return whether moving was started successfully.
20781     * @hide
20782     */
20783    public final boolean startMovingTask(float startX, float startY) {
20784        if (ViewDebug.DEBUG_POSITIONING) {
20785            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
20786        }
20787        try {
20788            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
20789        } catch (RemoteException e) {
20790            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
20791        }
20792        return false;
20793    }
20794
20795    /**
20796     * Handles drag events sent by the system following a call to
20797     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
20798     * startDragAndDrop()}.
20799     *<p>
20800     * When the system calls this method, it passes a
20801     * {@link android.view.DragEvent} object. A call to
20802     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
20803     * in DragEvent. The method uses these to determine what is happening in the drag and drop
20804     * operation.
20805     * @param event The {@link android.view.DragEvent} sent by the system.
20806     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
20807     * in DragEvent, indicating the type of drag event represented by this object.
20808     * @return {@code true} if the method was successful, otherwise {@code false}.
20809     * <p>
20810     *  The method should return {@code true} in response to an action type of
20811     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
20812     *  operation.
20813     * </p>
20814     * <p>
20815     *  The method should also return {@code true} in response to an action type of
20816     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
20817     *  {@code false} if it didn't.
20818     * </p>
20819     */
20820    public boolean onDragEvent(DragEvent event) {
20821        return false;
20822    }
20823
20824    /**
20825     * Detects if this View is enabled and has a drag event listener.
20826     * If both are true, then it calls the drag event listener with the
20827     * {@link android.view.DragEvent} it received. If the drag event listener returns
20828     * {@code true}, then dispatchDragEvent() returns {@code true}.
20829     * <p>
20830     * For all other cases, the method calls the
20831     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
20832     * method and returns its result.
20833     * </p>
20834     * <p>
20835     * This ensures that a drag event is always consumed, even if the View does not have a drag
20836     * event listener. However, if the View has a listener and the listener returns true, then
20837     * onDragEvent() is not called.
20838     * </p>
20839     */
20840    public boolean dispatchDragEvent(DragEvent event) {
20841        ListenerInfo li = mListenerInfo;
20842        //noinspection SimplifiableIfStatement
20843        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
20844                && li.mOnDragListener.onDrag(this, event)) {
20845            return true;
20846        }
20847        return onDragEvent(event);
20848    }
20849
20850    boolean canAcceptDrag() {
20851        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
20852    }
20853
20854    /**
20855     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
20856     * it is ever exposed at all.
20857     * @hide
20858     */
20859    public void onCloseSystemDialogs(String reason) {
20860    }
20861
20862    /**
20863     * Given a Drawable whose bounds have been set to draw into this view,
20864     * update a Region being computed for
20865     * {@link #gatherTransparentRegion(android.graphics.Region)} so
20866     * that any non-transparent parts of the Drawable are removed from the
20867     * given transparent region.
20868     *
20869     * @param dr The Drawable whose transparency is to be applied to the region.
20870     * @param region A Region holding the current transparency information,
20871     * where any parts of the region that are set are considered to be
20872     * transparent.  On return, this region will be modified to have the
20873     * transparency information reduced by the corresponding parts of the
20874     * Drawable that are not transparent.
20875     * {@hide}
20876     */
20877    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
20878        if (DBG) {
20879            Log.i("View", "Getting transparent region for: " + this);
20880        }
20881        final Region r = dr.getTransparentRegion();
20882        final Rect db = dr.getBounds();
20883        final AttachInfo attachInfo = mAttachInfo;
20884        if (r != null && attachInfo != null) {
20885            final int w = getRight()-getLeft();
20886            final int h = getBottom()-getTop();
20887            if (db.left > 0) {
20888                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
20889                r.op(0, 0, db.left, h, Region.Op.UNION);
20890            }
20891            if (db.right < w) {
20892                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
20893                r.op(db.right, 0, w, h, Region.Op.UNION);
20894            }
20895            if (db.top > 0) {
20896                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
20897                r.op(0, 0, w, db.top, Region.Op.UNION);
20898            }
20899            if (db.bottom < h) {
20900                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
20901                r.op(0, db.bottom, w, h, Region.Op.UNION);
20902            }
20903            final int[] location = attachInfo.mTransparentLocation;
20904            getLocationInWindow(location);
20905            r.translate(location[0], location[1]);
20906            region.op(r, Region.Op.INTERSECT);
20907        } else {
20908            region.op(db, Region.Op.DIFFERENCE);
20909        }
20910    }
20911
20912    private void checkForLongClick(int delayOffset, float x, float y) {
20913        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
20914            mHasPerformedLongPress = false;
20915
20916            if (mPendingCheckForLongPress == null) {
20917                mPendingCheckForLongPress = new CheckForLongPress();
20918            }
20919            mPendingCheckForLongPress.setAnchor(x, y);
20920            mPendingCheckForLongPress.rememberWindowAttachCount();
20921            postDelayed(mPendingCheckForLongPress,
20922                    ViewConfiguration.getLongPressTimeout() - delayOffset);
20923        }
20924    }
20925
20926    /**
20927     * Inflate a view from an XML resource.  This convenience method wraps the {@link
20928     * LayoutInflater} class, which provides a full range of options for view inflation.
20929     *
20930     * @param context The Context object for your activity or application.
20931     * @param resource The resource ID to inflate
20932     * @param root A view group that will be the parent.  Used to properly inflate the
20933     * layout_* parameters.
20934     * @see LayoutInflater
20935     */
20936    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
20937        LayoutInflater factory = LayoutInflater.from(context);
20938        return factory.inflate(resource, root);
20939    }
20940
20941    /**
20942     * Scroll the view with standard behavior for scrolling beyond the normal
20943     * content boundaries. Views that call this method should override
20944     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
20945     * results of an over-scroll operation.
20946     *
20947     * Views can use this method to handle any touch or fling-based scrolling.
20948     *
20949     * @param deltaX Change in X in pixels
20950     * @param deltaY Change in Y in pixels
20951     * @param scrollX Current X scroll value in pixels before applying deltaX
20952     * @param scrollY Current Y scroll value in pixels before applying deltaY
20953     * @param scrollRangeX Maximum content scroll range along the X axis
20954     * @param scrollRangeY Maximum content scroll range along the Y axis
20955     * @param maxOverScrollX Number of pixels to overscroll by in either direction
20956     *          along the X axis.
20957     * @param maxOverScrollY Number of pixels to overscroll by in either direction
20958     *          along the Y axis.
20959     * @param isTouchEvent true if this scroll operation is the result of a touch event.
20960     * @return true if scrolling was clamped to an over-scroll boundary along either
20961     *          axis, false otherwise.
20962     */
20963    @SuppressWarnings({"UnusedParameters"})
20964    protected boolean overScrollBy(int deltaX, int deltaY,
20965            int scrollX, int scrollY,
20966            int scrollRangeX, int scrollRangeY,
20967            int maxOverScrollX, int maxOverScrollY,
20968            boolean isTouchEvent) {
20969        final int overScrollMode = mOverScrollMode;
20970        final boolean canScrollHorizontal =
20971                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
20972        final boolean canScrollVertical =
20973                computeVerticalScrollRange() > computeVerticalScrollExtent();
20974        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
20975                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
20976        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
20977                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
20978
20979        int newScrollX = scrollX + deltaX;
20980        if (!overScrollHorizontal) {
20981            maxOverScrollX = 0;
20982        }
20983
20984        int newScrollY = scrollY + deltaY;
20985        if (!overScrollVertical) {
20986            maxOverScrollY = 0;
20987        }
20988
20989        // Clamp values if at the limits and record
20990        final int left = -maxOverScrollX;
20991        final int right = maxOverScrollX + scrollRangeX;
20992        final int top = -maxOverScrollY;
20993        final int bottom = maxOverScrollY + scrollRangeY;
20994
20995        boolean clampedX = false;
20996        if (newScrollX > right) {
20997            newScrollX = right;
20998            clampedX = true;
20999        } else if (newScrollX < left) {
21000            newScrollX = left;
21001            clampedX = true;
21002        }
21003
21004        boolean clampedY = false;
21005        if (newScrollY > bottom) {
21006            newScrollY = bottom;
21007            clampedY = true;
21008        } else if (newScrollY < top) {
21009            newScrollY = top;
21010            clampedY = true;
21011        }
21012
21013        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
21014
21015        return clampedX || clampedY;
21016    }
21017
21018    /**
21019     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
21020     * respond to the results of an over-scroll operation.
21021     *
21022     * @param scrollX New X scroll value in pixels
21023     * @param scrollY New Y scroll value in pixels
21024     * @param clampedX True if scrollX was clamped to an over-scroll boundary
21025     * @param clampedY True if scrollY was clamped to an over-scroll boundary
21026     */
21027    protected void onOverScrolled(int scrollX, int scrollY,
21028            boolean clampedX, boolean clampedY) {
21029        // Intentionally empty.
21030    }
21031
21032    /**
21033     * Returns the over-scroll mode for this view. The result will be
21034     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21035     * (allow over-scrolling only if the view content is larger than the container),
21036     * or {@link #OVER_SCROLL_NEVER}.
21037     *
21038     * @return This view's over-scroll mode.
21039     */
21040    public int getOverScrollMode() {
21041        return mOverScrollMode;
21042    }
21043
21044    /**
21045     * Set the over-scroll mode for this view. Valid over-scroll modes are
21046     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21047     * (allow over-scrolling only if the view content is larger than the container),
21048     * or {@link #OVER_SCROLL_NEVER}.
21049     *
21050     * Setting the over-scroll mode of a view will have an effect only if the
21051     * view is capable of scrolling.
21052     *
21053     * @param overScrollMode The new over-scroll mode for this view.
21054     */
21055    public void setOverScrollMode(int overScrollMode) {
21056        if (overScrollMode != OVER_SCROLL_ALWAYS &&
21057                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
21058                overScrollMode != OVER_SCROLL_NEVER) {
21059            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
21060        }
21061        mOverScrollMode = overScrollMode;
21062    }
21063
21064    /**
21065     * Enable or disable nested scrolling for this view.
21066     *
21067     * <p>If this property is set to true the view will be permitted to initiate nested
21068     * scrolling operations with a compatible parent view in the current hierarchy. If this
21069     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
21070     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
21071     * the nested scroll.</p>
21072     *
21073     * @param enabled true to enable nested scrolling, false to disable
21074     *
21075     * @see #isNestedScrollingEnabled()
21076     */
21077    public void setNestedScrollingEnabled(boolean enabled) {
21078        if (enabled) {
21079            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
21080        } else {
21081            stopNestedScroll();
21082            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
21083        }
21084    }
21085
21086    /**
21087     * Returns true if nested scrolling is enabled for this view.
21088     *
21089     * <p>If nested scrolling is enabled and this View class implementation supports it,
21090     * this view will act as a nested scrolling child view when applicable, forwarding data
21091     * about the scroll operation in progress to a compatible and cooperating nested scrolling
21092     * parent.</p>
21093     *
21094     * @return true if nested scrolling is enabled
21095     *
21096     * @see #setNestedScrollingEnabled(boolean)
21097     */
21098    public boolean isNestedScrollingEnabled() {
21099        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
21100                PFLAG3_NESTED_SCROLLING_ENABLED;
21101    }
21102
21103    /**
21104     * Begin a nestable scroll operation along the given axes.
21105     *
21106     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
21107     *
21108     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
21109     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
21110     * In the case of touch scrolling the nested scroll will be terminated automatically in
21111     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
21112     * In the event of programmatic scrolling the caller must explicitly call
21113     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
21114     *
21115     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
21116     * If it returns false the caller may ignore the rest of this contract until the next scroll.
21117     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
21118     *
21119     * <p>At each incremental step of the scroll the caller should invoke
21120     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
21121     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
21122     * parent at least partially consumed the scroll and the caller should adjust the amount it
21123     * scrolls by.</p>
21124     *
21125     * <p>After applying the remainder of the scroll delta the caller should invoke
21126     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
21127     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
21128     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
21129     * </p>
21130     *
21131     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
21132     *             {@link #SCROLL_AXIS_VERTICAL}.
21133     * @return true if a cooperative parent was found and nested scrolling has been enabled for
21134     *         the current gesture.
21135     *
21136     * @see #stopNestedScroll()
21137     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21138     * @see #dispatchNestedScroll(int, int, int, int, int[])
21139     */
21140    public boolean startNestedScroll(int axes) {
21141        if (hasNestedScrollingParent()) {
21142            // Already in progress
21143            return true;
21144        }
21145        if (isNestedScrollingEnabled()) {
21146            ViewParent p = getParent();
21147            View child = this;
21148            while (p != null) {
21149                try {
21150                    if (p.onStartNestedScroll(child, this, axes)) {
21151                        mNestedScrollingParent = p;
21152                        p.onNestedScrollAccepted(child, this, axes);
21153                        return true;
21154                    }
21155                } catch (AbstractMethodError e) {
21156                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
21157                            "method onStartNestedScroll", e);
21158                    // Allow the search upward to continue
21159                }
21160                if (p instanceof View) {
21161                    child = (View) p;
21162                }
21163                p = p.getParent();
21164            }
21165        }
21166        return false;
21167    }
21168
21169    /**
21170     * Stop a nested scroll in progress.
21171     *
21172     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
21173     *
21174     * @see #startNestedScroll(int)
21175     */
21176    public void stopNestedScroll() {
21177        if (mNestedScrollingParent != null) {
21178            mNestedScrollingParent.onStopNestedScroll(this);
21179            mNestedScrollingParent = null;
21180        }
21181    }
21182
21183    /**
21184     * Returns true if this view has a nested scrolling parent.
21185     *
21186     * <p>The presence of a nested scrolling parent indicates that this view has initiated
21187     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
21188     *
21189     * @return whether this view has a nested scrolling parent
21190     */
21191    public boolean hasNestedScrollingParent() {
21192        return mNestedScrollingParent != null;
21193    }
21194
21195    /**
21196     * Dispatch one step of a nested scroll in progress.
21197     *
21198     * <p>Implementations of views that support nested scrolling should call this to report
21199     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
21200     * is not currently in progress or nested scrolling is not
21201     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
21202     *
21203     * <p>Compatible View implementations should also call
21204     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
21205     * consuming a component of the scroll event themselves.</p>
21206     *
21207     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
21208     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
21209     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
21210     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
21211     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21212     *                       in local view coordinates of this view from before this operation
21213     *                       to after it completes. View implementations may use this to adjust
21214     *                       expected input coordinate tracking.
21215     * @return true if the event was dispatched, false if it could not be dispatched.
21216     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21217     */
21218    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
21219            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
21220        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21221            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
21222                int startX = 0;
21223                int startY = 0;
21224                if (offsetInWindow != null) {
21225                    getLocationInWindow(offsetInWindow);
21226                    startX = offsetInWindow[0];
21227                    startY = offsetInWindow[1];
21228                }
21229
21230                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
21231                        dxUnconsumed, dyUnconsumed);
21232
21233                if (offsetInWindow != null) {
21234                    getLocationInWindow(offsetInWindow);
21235                    offsetInWindow[0] -= startX;
21236                    offsetInWindow[1] -= startY;
21237                }
21238                return true;
21239            } else if (offsetInWindow != null) {
21240                // No motion, no dispatch. Keep offsetInWindow up to date.
21241                offsetInWindow[0] = 0;
21242                offsetInWindow[1] = 0;
21243            }
21244        }
21245        return false;
21246    }
21247
21248    /**
21249     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
21250     *
21251     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
21252     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
21253     * scrolling operation to consume some or all of the scroll operation before the child view
21254     * consumes it.</p>
21255     *
21256     * @param dx Horizontal scroll distance in pixels
21257     * @param dy Vertical scroll distance in pixels
21258     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
21259     *                 and consumed[1] the consumed dy.
21260     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21261     *                       in local view coordinates of this view from before this operation
21262     *                       to after it completes. View implementations may use this to adjust
21263     *                       expected input coordinate tracking.
21264     * @return true if the parent consumed some or all of the scroll delta
21265     * @see #dispatchNestedScroll(int, int, int, int, int[])
21266     */
21267    public boolean dispatchNestedPreScroll(int dx, int dy,
21268            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
21269        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21270            if (dx != 0 || dy != 0) {
21271                int startX = 0;
21272                int startY = 0;
21273                if (offsetInWindow != null) {
21274                    getLocationInWindow(offsetInWindow);
21275                    startX = offsetInWindow[0];
21276                    startY = offsetInWindow[1];
21277                }
21278
21279                if (consumed == null) {
21280                    if (mTempNestedScrollConsumed == null) {
21281                        mTempNestedScrollConsumed = new int[2];
21282                    }
21283                    consumed = mTempNestedScrollConsumed;
21284                }
21285                consumed[0] = 0;
21286                consumed[1] = 0;
21287                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
21288
21289                if (offsetInWindow != null) {
21290                    getLocationInWindow(offsetInWindow);
21291                    offsetInWindow[0] -= startX;
21292                    offsetInWindow[1] -= startY;
21293                }
21294                return consumed[0] != 0 || consumed[1] != 0;
21295            } else if (offsetInWindow != null) {
21296                offsetInWindow[0] = 0;
21297                offsetInWindow[1] = 0;
21298            }
21299        }
21300        return false;
21301    }
21302
21303    /**
21304     * Dispatch a fling to a nested scrolling parent.
21305     *
21306     * <p>This method should be used to indicate that a nested scrolling child has detected
21307     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
21308     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
21309     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
21310     * along a scrollable axis.</p>
21311     *
21312     * <p>If a nested scrolling child view would normally fling but it is at the edge of
21313     * its own content, it can use this method to delegate the fling to its nested scrolling
21314     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
21315     *
21316     * @param velocityX Horizontal fling velocity in pixels per second
21317     * @param velocityY Vertical fling velocity in pixels per second
21318     * @param consumed true if the child consumed the fling, false otherwise
21319     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
21320     */
21321    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
21322        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21323            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
21324        }
21325        return false;
21326    }
21327
21328    /**
21329     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
21330     *
21331     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
21332     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
21333     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
21334     * before the child view consumes it. If this method returns <code>true</code>, a nested
21335     * parent view consumed the fling and this view should not scroll as a result.</p>
21336     *
21337     * <p>For a better user experience, only one view in a nested scrolling chain should consume
21338     * the fling at a time. If a parent view consumed the fling this method will return false.
21339     * Custom view implementations should account for this in two ways:</p>
21340     *
21341     * <ul>
21342     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
21343     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
21344     *     position regardless.</li>
21345     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
21346     *     even to settle back to a valid idle position.</li>
21347     * </ul>
21348     *
21349     * <p>Views should also not offer fling velocities to nested parent views along an axis
21350     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
21351     * should not offer a horizontal fling velocity to its parents since scrolling along that
21352     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
21353     *
21354     * @param velocityX Horizontal fling velocity in pixels per second
21355     * @param velocityY Vertical fling velocity in pixels per second
21356     * @return true if a nested scrolling parent consumed the fling
21357     */
21358    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
21359        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21360            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
21361        }
21362        return false;
21363    }
21364
21365    /**
21366     * Gets a scale factor that determines the distance the view should scroll
21367     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
21368     * @return The vertical scroll scale factor.
21369     * @hide
21370     */
21371    protected float getVerticalScrollFactor() {
21372        if (mVerticalScrollFactor == 0) {
21373            TypedValue outValue = new TypedValue();
21374            if (!mContext.getTheme().resolveAttribute(
21375                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
21376                throw new IllegalStateException(
21377                        "Expected theme to define listPreferredItemHeight.");
21378            }
21379            mVerticalScrollFactor = outValue.getDimension(
21380                    mContext.getResources().getDisplayMetrics());
21381        }
21382        return mVerticalScrollFactor;
21383    }
21384
21385    /**
21386     * Gets a scale factor that determines the distance the view should scroll
21387     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
21388     * @return The horizontal scroll scale factor.
21389     * @hide
21390     */
21391    protected float getHorizontalScrollFactor() {
21392        // TODO: Should use something else.
21393        return getVerticalScrollFactor();
21394    }
21395
21396    /**
21397     * Return the value specifying the text direction or policy that was set with
21398     * {@link #setTextDirection(int)}.
21399     *
21400     * @return the defined text direction. It can be one of:
21401     *
21402     * {@link #TEXT_DIRECTION_INHERIT},
21403     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21404     * {@link #TEXT_DIRECTION_ANY_RTL},
21405     * {@link #TEXT_DIRECTION_LTR},
21406     * {@link #TEXT_DIRECTION_RTL},
21407     * {@link #TEXT_DIRECTION_LOCALE},
21408     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21409     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21410     *
21411     * @attr ref android.R.styleable#View_textDirection
21412     *
21413     * @hide
21414     */
21415    @ViewDebug.ExportedProperty(category = "text", mapping = {
21416            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21417            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21418            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21419            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21420            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21421            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21422            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21423            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21424    })
21425    public int getRawTextDirection() {
21426        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
21427    }
21428
21429    /**
21430     * Set the text direction.
21431     *
21432     * @param textDirection the direction to set. Should be one of:
21433     *
21434     * {@link #TEXT_DIRECTION_INHERIT},
21435     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21436     * {@link #TEXT_DIRECTION_ANY_RTL},
21437     * {@link #TEXT_DIRECTION_LTR},
21438     * {@link #TEXT_DIRECTION_RTL},
21439     * {@link #TEXT_DIRECTION_LOCALE}
21440     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21441     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
21442     *
21443     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
21444     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
21445     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
21446     *
21447     * @attr ref android.R.styleable#View_textDirection
21448     */
21449    public void setTextDirection(int textDirection) {
21450        if (getRawTextDirection() != textDirection) {
21451            // Reset the current text direction and the resolved one
21452            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
21453            resetResolvedTextDirection();
21454            // Set the new text direction
21455            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
21456            // Do resolution
21457            resolveTextDirection();
21458            // Notify change
21459            onRtlPropertiesChanged(getLayoutDirection());
21460            // Refresh
21461            requestLayout();
21462            invalidate(true);
21463        }
21464    }
21465
21466    /**
21467     * Return the resolved text direction.
21468     *
21469     * @return the resolved text direction. Returns one of:
21470     *
21471     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21472     * {@link #TEXT_DIRECTION_ANY_RTL},
21473     * {@link #TEXT_DIRECTION_LTR},
21474     * {@link #TEXT_DIRECTION_RTL},
21475     * {@link #TEXT_DIRECTION_LOCALE},
21476     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21477     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21478     *
21479     * @attr ref android.R.styleable#View_textDirection
21480     */
21481    @ViewDebug.ExportedProperty(category = "text", mapping = {
21482            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21483            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21484            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21485            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21486            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21487            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21488            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21489            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21490    })
21491    public int getTextDirection() {
21492        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
21493    }
21494
21495    /**
21496     * Resolve the text direction.
21497     *
21498     * @return true if resolution has been done, false otherwise.
21499     *
21500     * @hide
21501     */
21502    public boolean resolveTextDirection() {
21503        // Reset any previous text direction resolution
21504        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21505
21506        if (hasRtlSupport()) {
21507            // Set resolved text direction flag depending on text direction flag
21508            final int textDirection = getRawTextDirection();
21509            switch(textDirection) {
21510                case TEXT_DIRECTION_INHERIT:
21511                    if (!canResolveTextDirection()) {
21512                        // We cannot do the resolution if there is no parent, so use the default one
21513                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21514                        // Resolution will need to happen again later
21515                        return false;
21516                    }
21517
21518                    // Parent has not yet resolved, so we still return the default
21519                    try {
21520                        if (!mParent.isTextDirectionResolved()) {
21521                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21522                            // Resolution will need to happen again later
21523                            return false;
21524                        }
21525                    } catch (AbstractMethodError e) {
21526                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21527                                " does not fully implement ViewParent", e);
21528                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
21529                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21530                        return true;
21531                    }
21532
21533                    // Set current resolved direction to the same value as the parent's one
21534                    int parentResolvedDirection;
21535                    try {
21536                        parentResolvedDirection = mParent.getTextDirection();
21537                    } catch (AbstractMethodError e) {
21538                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21539                                " does not fully implement ViewParent", e);
21540                        parentResolvedDirection = TEXT_DIRECTION_LTR;
21541                    }
21542                    switch (parentResolvedDirection) {
21543                        case TEXT_DIRECTION_FIRST_STRONG:
21544                        case TEXT_DIRECTION_ANY_RTL:
21545                        case TEXT_DIRECTION_LTR:
21546                        case TEXT_DIRECTION_RTL:
21547                        case TEXT_DIRECTION_LOCALE:
21548                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
21549                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
21550                            mPrivateFlags2 |=
21551                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21552                            break;
21553                        default:
21554                            // Default resolved direction is "first strong" heuristic
21555                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21556                    }
21557                    break;
21558                case TEXT_DIRECTION_FIRST_STRONG:
21559                case TEXT_DIRECTION_ANY_RTL:
21560                case TEXT_DIRECTION_LTR:
21561                case TEXT_DIRECTION_RTL:
21562                case TEXT_DIRECTION_LOCALE:
21563                case TEXT_DIRECTION_FIRST_STRONG_LTR:
21564                case TEXT_DIRECTION_FIRST_STRONG_RTL:
21565                    // Resolved direction is the same as text direction
21566                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21567                    break;
21568                default:
21569                    // Default resolved direction is "first strong" heuristic
21570                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21571            }
21572        } else {
21573            // Default resolved direction is "first strong" heuristic
21574            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21575        }
21576
21577        // Set to resolved
21578        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
21579        return true;
21580    }
21581
21582    /**
21583     * Check if text direction resolution can be done.
21584     *
21585     * @return true if text direction resolution can be done otherwise return false.
21586     */
21587    public boolean canResolveTextDirection() {
21588        switch (getRawTextDirection()) {
21589            case TEXT_DIRECTION_INHERIT:
21590                if (mParent != null) {
21591                    try {
21592                        return mParent.canResolveTextDirection();
21593                    } catch (AbstractMethodError e) {
21594                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21595                                " does not fully implement ViewParent", e);
21596                    }
21597                }
21598                return false;
21599
21600            default:
21601                return true;
21602        }
21603    }
21604
21605    /**
21606     * Reset resolved text direction. Text direction will be resolved during a call to
21607     * {@link #onMeasure(int, int)}.
21608     *
21609     * @hide
21610     */
21611    public void resetResolvedTextDirection() {
21612        // Reset any previous text direction resolution
21613        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21614        // Set to default value
21615        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21616    }
21617
21618    /**
21619     * @return true if text direction is inherited.
21620     *
21621     * @hide
21622     */
21623    public boolean isTextDirectionInherited() {
21624        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
21625    }
21626
21627    /**
21628     * @return true if text direction is resolved.
21629     */
21630    public boolean isTextDirectionResolved() {
21631        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
21632    }
21633
21634    /**
21635     * Return the value specifying the text alignment or policy that was set with
21636     * {@link #setTextAlignment(int)}.
21637     *
21638     * @return the defined text alignment. It can be one of:
21639     *
21640     * {@link #TEXT_ALIGNMENT_INHERIT},
21641     * {@link #TEXT_ALIGNMENT_GRAVITY},
21642     * {@link #TEXT_ALIGNMENT_CENTER},
21643     * {@link #TEXT_ALIGNMENT_TEXT_START},
21644     * {@link #TEXT_ALIGNMENT_TEXT_END},
21645     * {@link #TEXT_ALIGNMENT_VIEW_START},
21646     * {@link #TEXT_ALIGNMENT_VIEW_END}
21647     *
21648     * @attr ref android.R.styleable#View_textAlignment
21649     *
21650     * @hide
21651     */
21652    @ViewDebug.ExportedProperty(category = "text", mapping = {
21653            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21654            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21655            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21656            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21657            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21658            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21659            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21660    })
21661    @TextAlignment
21662    public int getRawTextAlignment() {
21663        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
21664    }
21665
21666    /**
21667     * Set the text alignment.
21668     *
21669     * @param textAlignment The text alignment to set. Should be one of
21670     *
21671     * {@link #TEXT_ALIGNMENT_INHERIT},
21672     * {@link #TEXT_ALIGNMENT_GRAVITY},
21673     * {@link #TEXT_ALIGNMENT_CENTER},
21674     * {@link #TEXT_ALIGNMENT_TEXT_START},
21675     * {@link #TEXT_ALIGNMENT_TEXT_END},
21676     * {@link #TEXT_ALIGNMENT_VIEW_START},
21677     * {@link #TEXT_ALIGNMENT_VIEW_END}
21678     *
21679     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
21680     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
21681     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
21682     *
21683     * @attr ref android.R.styleable#View_textAlignment
21684     */
21685    public void setTextAlignment(@TextAlignment int textAlignment) {
21686        if (textAlignment != getRawTextAlignment()) {
21687            // Reset the current and resolved text alignment
21688            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
21689            resetResolvedTextAlignment();
21690            // Set the new text alignment
21691            mPrivateFlags2 |=
21692                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
21693            // Do resolution
21694            resolveTextAlignment();
21695            // Notify change
21696            onRtlPropertiesChanged(getLayoutDirection());
21697            // Refresh
21698            requestLayout();
21699            invalidate(true);
21700        }
21701    }
21702
21703    /**
21704     * Return the resolved text alignment.
21705     *
21706     * @return the resolved text alignment. Returns one of:
21707     *
21708     * {@link #TEXT_ALIGNMENT_GRAVITY},
21709     * {@link #TEXT_ALIGNMENT_CENTER},
21710     * {@link #TEXT_ALIGNMENT_TEXT_START},
21711     * {@link #TEXT_ALIGNMENT_TEXT_END},
21712     * {@link #TEXT_ALIGNMENT_VIEW_START},
21713     * {@link #TEXT_ALIGNMENT_VIEW_END}
21714     *
21715     * @attr ref android.R.styleable#View_textAlignment
21716     */
21717    @ViewDebug.ExportedProperty(category = "text", mapping = {
21718            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21719            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21720            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21721            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21722            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21723            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21724            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21725    })
21726    @TextAlignment
21727    public int getTextAlignment() {
21728        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
21729                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
21730    }
21731
21732    /**
21733     * Resolve the text alignment.
21734     *
21735     * @return true if resolution has been done, false otherwise.
21736     *
21737     * @hide
21738     */
21739    public boolean resolveTextAlignment() {
21740        // Reset any previous text alignment resolution
21741        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21742
21743        if (hasRtlSupport()) {
21744            // Set resolved text alignment flag depending on text alignment flag
21745            final int textAlignment = getRawTextAlignment();
21746            switch (textAlignment) {
21747                case TEXT_ALIGNMENT_INHERIT:
21748                    // Check if we can resolve the text alignment
21749                    if (!canResolveTextAlignment()) {
21750                        // We cannot do the resolution if there is no parent so use the default
21751                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21752                        // Resolution will need to happen again later
21753                        return false;
21754                    }
21755
21756                    // Parent has not yet resolved, so we still return the default
21757                    try {
21758                        if (!mParent.isTextAlignmentResolved()) {
21759                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21760                            // Resolution will need to happen again later
21761                            return false;
21762                        }
21763                    } catch (AbstractMethodError e) {
21764                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21765                                " does not fully implement ViewParent", e);
21766                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
21767                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21768                        return true;
21769                    }
21770
21771                    int parentResolvedTextAlignment;
21772                    try {
21773                        parentResolvedTextAlignment = mParent.getTextAlignment();
21774                    } catch (AbstractMethodError e) {
21775                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21776                                " does not fully implement ViewParent", e);
21777                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
21778                    }
21779                    switch (parentResolvedTextAlignment) {
21780                        case TEXT_ALIGNMENT_GRAVITY:
21781                        case TEXT_ALIGNMENT_TEXT_START:
21782                        case TEXT_ALIGNMENT_TEXT_END:
21783                        case TEXT_ALIGNMENT_CENTER:
21784                        case TEXT_ALIGNMENT_VIEW_START:
21785                        case TEXT_ALIGNMENT_VIEW_END:
21786                            // Resolved text alignment is the same as the parent resolved
21787                            // text alignment
21788                            mPrivateFlags2 |=
21789                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21790                            break;
21791                        default:
21792                            // Use default resolved text alignment
21793                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21794                    }
21795                    break;
21796                case TEXT_ALIGNMENT_GRAVITY:
21797                case TEXT_ALIGNMENT_TEXT_START:
21798                case TEXT_ALIGNMENT_TEXT_END:
21799                case TEXT_ALIGNMENT_CENTER:
21800                case TEXT_ALIGNMENT_VIEW_START:
21801                case TEXT_ALIGNMENT_VIEW_END:
21802                    // Resolved text alignment is the same as text alignment
21803                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21804                    break;
21805                default:
21806                    // Use default resolved text alignment
21807                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21808            }
21809        } else {
21810            // Use default resolved text alignment
21811            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21812        }
21813
21814        // Set the resolved
21815        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21816        return true;
21817    }
21818
21819    /**
21820     * Check if text alignment resolution can be done.
21821     *
21822     * @return true if text alignment resolution can be done otherwise return false.
21823     */
21824    public boolean canResolveTextAlignment() {
21825        switch (getRawTextAlignment()) {
21826            case TEXT_DIRECTION_INHERIT:
21827                if (mParent != null) {
21828                    try {
21829                        return mParent.canResolveTextAlignment();
21830                    } catch (AbstractMethodError e) {
21831                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21832                                " does not fully implement ViewParent", e);
21833                    }
21834                }
21835                return false;
21836
21837            default:
21838                return true;
21839        }
21840    }
21841
21842    /**
21843     * Reset resolved text alignment. Text alignment will be resolved during a call to
21844     * {@link #onMeasure(int, int)}.
21845     *
21846     * @hide
21847     */
21848    public void resetResolvedTextAlignment() {
21849        // Reset any previous text alignment resolution
21850        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21851        // Set to default
21852        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21853    }
21854
21855    /**
21856     * @return true if text alignment is inherited.
21857     *
21858     * @hide
21859     */
21860    public boolean isTextAlignmentInherited() {
21861        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
21862    }
21863
21864    /**
21865     * @return true if text alignment is resolved.
21866     */
21867    public boolean isTextAlignmentResolved() {
21868        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21869    }
21870
21871    /**
21872     * Generate a value suitable for use in {@link #setId(int)}.
21873     * This value will not collide with ID values generated at build time by aapt for R.id.
21874     *
21875     * @return a generated ID value
21876     */
21877    public static int generateViewId() {
21878        for (;;) {
21879            final int result = sNextGeneratedId.get();
21880            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
21881            int newValue = result + 1;
21882            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
21883            if (sNextGeneratedId.compareAndSet(result, newValue)) {
21884                return result;
21885            }
21886        }
21887    }
21888
21889    /**
21890     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
21891     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
21892     *                           a normal View or a ViewGroup with
21893     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
21894     * @hide
21895     */
21896    public void captureTransitioningViews(List<View> transitioningViews) {
21897        if (getVisibility() == View.VISIBLE) {
21898            transitioningViews.add(this);
21899        }
21900    }
21901
21902    /**
21903     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
21904     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
21905     * @hide
21906     */
21907    public void findNamedViews(Map<String, View> namedElements) {
21908        if (getVisibility() == VISIBLE || mGhostView != null) {
21909            String transitionName = getTransitionName();
21910            if (transitionName != null) {
21911                namedElements.put(transitionName, this);
21912            }
21913        }
21914    }
21915
21916    /**
21917     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
21918     * The default implementation does not care the location or event types, but some subclasses
21919     * may use it (such as WebViews).
21920     * @param event The MotionEvent from a mouse
21921     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
21922     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
21923     * @see PointerIcon
21924     */
21925    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
21926        final float x = event.getX(pointerIndex);
21927        final float y = event.getY(pointerIndex);
21928        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
21929            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
21930        }
21931        return mPointerIcon;
21932    }
21933
21934    /**
21935     * Set the pointer icon for the current view.
21936     * Passing {@code null} will restore the pointer icon to its default value.
21937     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
21938     */
21939    public void setPointerIcon(PointerIcon pointerIcon) {
21940        mPointerIcon = pointerIcon;
21941        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
21942            return;
21943        }
21944        try {
21945            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
21946        } catch (RemoteException e) {
21947        }
21948    }
21949
21950    /**
21951     * Gets the pointer icon for the current view.
21952     */
21953    public PointerIcon getPointerIcon() {
21954        return mPointerIcon;
21955    }
21956
21957    //
21958    // Properties
21959    //
21960    /**
21961     * A Property wrapper around the <code>alpha</code> functionality handled by the
21962     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
21963     */
21964    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
21965        @Override
21966        public void setValue(View object, float value) {
21967            object.setAlpha(value);
21968        }
21969
21970        @Override
21971        public Float get(View object) {
21972            return object.getAlpha();
21973        }
21974    };
21975
21976    /**
21977     * A Property wrapper around the <code>translationX</code> functionality handled by the
21978     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
21979     */
21980    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
21981        @Override
21982        public void setValue(View object, float value) {
21983            object.setTranslationX(value);
21984        }
21985
21986                @Override
21987        public Float get(View object) {
21988            return object.getTranslationX();
21989        }
21990    };
21991
21992    /**
21993     * A Property wrapper around the <code>translationY</code> functionality handled by the
21994     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
21995     */
21996    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
21997        @Override
21998        public void setValue(View object, float value) {
21999            object.setTranslationY(value);
22000        }
22001
22002        @Override
22003        public Float get(View object) {
22004            return object.getTranslationY();
22005        }
22006    };
22007
22008    /**
22009     * A Property wrapper around the <code>translationZ</code> functionality handled by the
22010     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
22011     */
22012    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
22013        @Override
22014        public void setValue(View object, float value) {
22015            object.setTranslationZ(value);
22016        }
22017
22018        @Override
22019        public Float get(View object) {
22020            return object.getTranslationZ();
22021        }
22022    };
22023
22024    /**
22025     * A Property wrapper around the <code>x</code> functionality handled by the
22026     * {@link View#setX(float)} and {@link View#getX()} methods.
22027     */
22028    public static final Property<View, Float> X = new FloatProperty<View>("x") {
22029        @Override
22030        public void setValue(View object, float value) {
22031            object.setX(value);
22032        }
22033
22034        @Override
22035        public Float get(View object) {
22036            return object.getX();
22037        }
22038    };
22039
22040    /**
22041     * A Property wrapper around the <code>y</code> functionality handled by the
22042     * {@link View#setY(float)} and {@link View#getY()} methods.
22043     */
22044    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
22045        @Override
22046        public void setValue(View object, float value) {
22047            object.setY(value);
22048        }
22049
22050        @Override
22051        public Float get(View object) {
22052            return object.getY();
22053        }
22054    };
22055
22056    /**
22057     * A Property wrapper around the <code>z</code> functionality handled by the
22058     * {@link View#setZ(float)} and {@link View#getZ()} methods.
22059     */
22060    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
22061        @Override
22062        public void setValue(View object, float value) {
22063            object.setZ(value);
22064        }
22065
22066        @Override
22067        public Float get(View object) {
22068            return object.getZ();
22069        }
22070    };
22071
22072    /**
22073     * A Property wrapper around the <code>rotation</code> functionality handled by the
22074     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
22075     */
22076    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
22077        @Override
22078        public void setValue(View object, float value) {
22079            object.setRotation(value);
22080        }
22081
22082        @Override
22083        public Float get(View object) {
22084            return object.getRotation();
22085        }
22086    };
22087
22088    /**
22089     * A Property wrapper around the <code>rotationX</code> functionality handled by the
22090     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
22091     */
22092    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
22093        @Override
22094        public void setValue(View object, float value) {
22095            object.setRotationX(value);
22096        }
22097
22098        @Override
22099        public Float get(View object) {
22100            return object.getRotationX();
22101        }
22102    };
22103
22104    /**
22105     * A Property wrapper around the <code>rotationY</code> functionality handled by the
22106     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
22107     */
22108    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
22109        @Override
22110        public void setValue(View object, float value) {
22111            object.setRotationY(value);
22112        }
22113
22114        @Override
22115        public Float get(View object) {
22116            return object.getRotationY();
22117        }
22118    };
22119
22120    /**
22121     * A Property wrapper around the <code>scaleX</code> functionality handled by the
22122     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
22123     */
22124    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
22125        @Override
22126        public void setValue(View object, float value) {
22127            object.setScaleX(value);
22128        }
22129
22130        @Override
22131        public Float get(View object) {
22132            return object.getScaleX();
22133        }
22134    };
22135
22136    /**
22137     * A Property wrapper around the <code>scaleY</code> functionality handled by the
22138     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
22139     */
22140    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
22141        @Override
22142        public void setValue(View object, float value) {
22143            object.setScaleY(value);
22144        }
22145
22146        @Override
22147        public Float get(View object) {
22148            return object.getScaleY();
22149        }
22150    };
22151
22152    /**
22153     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
22154     * Each MeasureSpec represents a requirement for either the width or the height.
22155     * A MeasureSpec is comprised of a size and a mode. There are three possible
22156     * modes:
22157     * <dl>
22158     * <dt>UNSPECIFIED</dt>
22159     * <dd>
22160     * The parent has not imposed any constraint on the child. It can be whatever size
22161     * it wants.
22162     * </dd>
22163     *
22164     * <dt>EXACTLY</dt>
22165     * <dd>
22166     * The parent has determined an exact size for the child. The child is going to be
22167     * given those bounds regardless of how big it wants to be.
22168     * </dd>
22169     *
22170     * <dt>AT_MOST</dt>
22171     * <dd>
22172     * The child can be as large as it wants up to the specified size.
22173     * </dd>
22174     * </dl>
22175     *
22176     * MeasureSpecs are implemented as ints to reduce object allocation. This class
22177     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
22178     */
22179    public static class MeasureSpec {
22180        private static final int MODE_SHIFT = 30;
22181        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
22182
22183        /** @hide */
22184        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
22185        @Retention(RetentionPolicy.SOURCE)
22186        public @interface MeasureSpecMode {}
22187
22188        /**
22189         * Measure specification mode: The parent has not imposed any constraint
22190         * on the child. It can be whatever size it wants.
22191         */
22192        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
22193
22194        /**
22195         * Measure specification mode: The parent has determined an exact size
22196         * for the child. The child is going to be given those bounds regardless
22197         * of how big it wants to be.
22198         */
22199        public static final int EXACTLY     = 1 << MODE_SHIFT;
22200
22201        /**
22202         * Measure specification mode: The child can be as large as it wants up
22203         * to the specified size.
22204         */
22205        public static final int AT_MOST     = 2 << MODE_SHIFT;
22206
22207        /**
22208         * Creates a measure specification based on the supplied size and mode.
22209         *
22210         * The mode must always be one of the following:
22211         * <ul>
22212         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
22213         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
22214         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
22215         * </ul>
22216         *
22217         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
22218         * implementation was such that the order of arguments did not matter
22219         * and overflow in either value could impact the resulting MeasureSpec.
22220         * {@link android.widget.RelativeLayout} was affected by this bug.
22221         * Apps targeting API levels greater than 17 will get the fixed, more strict
22222         * behavior.</p>
22223         *
22224         * @param size the size of the measure specification
22225         * @param mode the mode of the measure specification
22226         * @return the measure specification based on size and mode
22227         */
22228        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
22229                                          @MeasureSpecMode int mode) {
22230            if (sUseBrokenMakeMeasureSpec) {
22231                return size + mode;
22232            } else {
22233                return (size & ~MODE_MASK) | (mode & MODE_MASK);
22234            }
22235        }
22236
22237        /**
22238         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
22239         * will automatically get a size of 0. Older apps expect this.
22240         *
22241         * @hide internal use only for compatibility with system widgets and older apps
22242         */
22243        public static int makeSafeMeasureSpec(int size, int mode) {
22244            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
22245                return 0;
22246            }
22247            return makeMeasureSpec(size, mode);
22248        }
22249
22250        /**
22251         * Extracts the mode from the supplied measure specification.
22252         *
22253         * @param measureSpec the measure specification to extract the mode from
22254         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
22255         *         {@link android.view.View.MeasureSpec#AT_MOST} or
22256         *         {@link android.view.View.MeasureSpec#EXACTLY}
22257         */
22258        @MeasureSpecMode
22259        public static int getMode(int measureSpec) {
22260            //noinspection ResourceType
22261            return (measureSpec & MODE_MASK);
22262        }
22263
22264        /**
22265         * Extracts the size from the supplied measure specification.
22266         *
22267         * @param measureSpec the measure specification to extract the size from
22268         * @return the size in pixels defined in the supplied measure specification
22269         */
22270        public static int getSize(int measureSpec) {
22271            return (measureSpec & ~MODE_MASK);
22272        }
22273
22274        static int adjust(int measureSpec, int delta) {
22275            final int mode = getMode(measureSpec);
22276            int size = getSize(measureSpec);
22277            if (mode == UNSPECIFIED) {
22278                // No need to adjust size for UNSPECIFIED mode.
22279                return makeMeasureSpec(size, UNSPECIFIED);
22280            }
22281            size += delta;
22282            if (size < 0) {
22283                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
22284                        ") spec: " + toString(measureSpec) + " delta: " + delta);
22285                size = 0;
22286            }
22287            return makeMeasureSpec(size, mode);
22288        }
22289
22290        /**
22291         * Returns a String representation of the specified measure
22292         * specification.
22293         *
22294         * @param measureSpec the measure specification to convert to a String
22295         * @return a String with the following format: "MeasureSpec: MODE SIZE"
22296         */
22297        public static String toString(int measureSpec) {
22298            int mode = getMode(measureSpec);
22299            int size = getSize(measureSpec);
22300
22301            StringBuilder sb = new StringBuilder("MeasureSpec: ");
22302
22303            if (mode == UNSPECIFIED)
22304                sb.append("UNSPECIFIED ");
22305            else if (mode == EXACTLY)
22306                sb.append("EXACTLY ");
22307            else if (mode == AT_MOST)
22308                sb.append("AT_MOST ");
22309            else
22310                sb.append(mode).append(" ");
22311
22312            sb.append(size);
22313            return sb.toString();
22314        }
22315    }
22316
22317    private final class CheckForLongPress implements Runnable {
22318        private int mOriginalWindowAttachCount;
22319        private float mX;
22320        private float mY;
22321
22322        @Override
22323        public void run() {
22324            if (isPressed() && (mParent != null)
22325                    && mOriginalWindowAttachCount == mWindowAttachCount) {
22326                if (performLongClick(mX, mY)) {
22327                    mHasPerformedLongPress = true;
22328                }
22329            }
22330        }
22331
22332        public void setAnchor(float x, float y) {
22333            mX = x;
22334            mY = y;
22335        }
22336
22337        public void rememberWindowAttachCount() {
22338            mOriginalWindowAttachCount = mWindowAttachCount;
22339        }
22340    }
22341
22342    private final class CheckForTap implements Runnable {
22343        public float x;
22344        public float y;
22345
22346        @Override
22347        public void run() {
22348            mPrivateFlags &= ~PFLAG_PREPRESSED;
22349            setPressed(true, x, y);
22350            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
22351        }
22352    }
22353
22354    private final class PerformClick implements Runnable {
22355        @Override
22356        public void run() {
22357            performClick();
22358        }
22359    }
22360
22361    /**
22362     * This method returns a ViewPropertyAnimator object, which can be used to animate
22363     * specific properties on this View.
22364     *
22365     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
22366     */
22367    public ViewPropertyAnimator animate() {
22368        if (mAnimator == null) {
22369            mAnimator = new ViewPropertyAnimator(this);
22370        }
22371        return mAnimator;
22372    }
22373
22374    /**
22375     * Sets the name of the View to be used to identify Views in Transitions.
22376     * Names should be unique in the View hierarchy.
22377     *
22378     * @param transitionName The name of the View to uniquely identify it for Transitions.
22379     */
22380    public final void setTransitionName(String transitionName) {
22381        mTransitionName = transitionName;
22382    }
22383
22384    /**
22385     * Returns the name of the View to be used to identify Views in Transitions.
22386     * Names should be unique in the View hierarchy.
22387     *
22388     * <p>This returns null if the View has not been given a name.</p>
22389     *
22390     * @return The name used of the View to be used to identify Views in Transitions or null
22391     * if no name has been given.
22392     */
22393    @ViewDebug.ExportedProperty
22394    public String getTransitionName() {
22395        return mTransitionName;
22396    }
22397
22398    /**
22399     * @hide
22400     */
22401    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
22402        // Do nothing.
22403    }
22404
22405    /**
22406     * Interface definition for a callback to be invoked when a hardware key event is
22407     * dispatched to this view. The callback will be invoked before the key event is
22408     * given to the view. This is only useful for hardware keyboards; a software input
22409     * method has no obligation to trigger this listener.
22410     */
22411    public interface OnKeyListener {
22412        /**
22413         * Called when a hardware key is dispatched to a view. This allows listeners to
22414         * get a chance to respond before the target view.
22415         * <p>Key presses in software keyboards will generally NOT trigger this method,
22416         * although some may elect to do so in some situations. Do not assume a
22417         * software input method has to be key-based; even if it is, it may use key presses
22418         * in a different way than you expect, so there is no way to reliably catch soft
22419         * input key presses.
22420         *
22421         * @param v The view the key has been dispatched to.
22422         * @param keyCode The code for the physical key that was pressed
22423         * @param event The KeyEvent object containing full information about
22424         *        the event.
22425         * @return True if the listener has consumed the event, false otherwise.
22426         */
22427        boolean onKey(View v, int keyCode, KeyEvent event);
22428    }
22429
22430    /**
22431     * Interface definition for a callback to be invoked when a touch event is
22432     * dispatched to this view. The callback will be invoked before the touch
22433     * event is given to the view.
22434     */
22435    public interface OnTouchListener {
22436        /**
22437         * Called when a touch event is dispatched to a view. This allows listeners to
22438         * get a chance to respond before the target view.
22439         *
22440         * @param v The view the touch event has been dispatched to.
22441         * @param event The MotionEvent object containing full information about
22442         *        the event.
22443         * @return True if the listener has consumed the event, false otherwise.
22444         */
22445        boolean onTouch(View v, MotionEvent event);
22446    }
22447
22448    /**
22449     * Interface definition for a callback to be invoked when a hover event is
22450     * dispatched to this view. The callback will be invoked before the hover
22451     * event is given to the view.
22452     */
22453    public interface OnHoverListener {
22454        /**
22455         * Called when a hover event is dispatched to a view. This allows listeners to
22456         * get a chance to respond before the target view.
22457         *
22458         * @param v The view the hover event has been dispatched to.
22459         * @param event The MotionEvent object containing full information about
22460         *        the event.
22461         * @return True if the listener has consumed the event, false otherwise.
22462         */
22463        boolean onHover(View v, MotionEvent event);
22464    }
22465
22466    /**
22467     * Interface definition for a callback to be invoked when a generic motion event is
22468     * dispatched to this view. The callback will be invoked before the generic motion
22469     * event is given to the view.
22470     */
22471    public interface OnGenericMotionListener {
22472        /**
22473         * Called when a generic motion event is dispatched to a view. This allows listeners to
22474         * get a chance to respond before the target view.
22475         *
22476         * @param v The view the generic motion event has been dispatched to.
22477         * @param event The MotionEvent object containing full information about
22478         *        the event.
22479         * @return True if the listener has consumed the event, false otherwise.
22480         */
22481        boolean onGenericMotion(View v, MotionEvent event);
22482    }
22483
22484    /**
22485     * Interface definition for a callback to be invoked when a view has been clicked and held.
22486     */
22487    public interface OnLongClickListener {
22488        /**
22489         * Called when a view has been clicked and held.
22490         *
22491         * @param v The view that was clicked and held.
22492         *
22493         * @return true if the callback consumed the long click, false otherwise.
22494         */
22495        boolean onLongClick(View v);
22496    }
22497
22498    /**
22499     * Interface definition for a callback to be invoked when a drag is being dispatched
22500     * to this view.  The callback will be invoked before the hosting view's own
22501     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
22502     * onDrag(event) behavior, it should return 'false' from this callback.
22503     *
22504     * <div class="special reference">
22505     * <h3>Developer Guides</h3>
22506     * <p>For a guide to implementing drag and drop features, read the
22507     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22508     * </div>
22509     */
22510    public interface OnDragListener {
22511        /**
22512         * Called when a drag event is dispatched to a view. This allows listeners
22513         * to get a chance to override base View behavior.
22514         *
22515         * @param v The View that received the drag event.
22516         * @param event The {@link android.view.DragEvent} object for the drag event.
22517         * @return {@code true} if the drag event was handled successfully, or {@code false}
22518         * if the drag event was not handled. Note that {@code false} will trigger the View
22519         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
22520         */
22521        boolean onDrag(View v, DragEvent event);
22522    }
22523
22524    /**
22525     * Interface definition for a callback to be invoked when the focus state of
22526     * a view changed.
22527     */
22528    public interface OnFocusChangeListener {
22529        /**
22530         * Called when the focus state of a view has changed.
22531         *
22532         * @param v The view whose state has changed.
22533         * @param hasFocus The new focus state of v.
22534         */
22535        void onFocusChange(View v, boolean hasFocus);
22536    }
22537
22538    /**
22539     * Interface definition for a callback to be invoked when a view is clicked.
22540     */
22541    public interface OnClickListener {
22542        /**
22543         * Called when a view has been clicked.
22544         *
22545         * @param v The view that was clicked.
22546         */
22547        void onClick(View v);
22548    }
22549
22550    /**
22551     * Interface definition for a callback to be invoked when a view is context clicked.
22552     */
22553    public interface OnContextClickListener {
22554        /**
22555         * Called when a view is context clicked.
22556         *
22557         * @param v The view that has been context clicked.
22558         * @return true if the callback consumed the context click, false otherwise.
22559         */
22560        boolean onContextClick(View v);
22561    }
22562
22563    /**
22564     * Interface definition for a callback to be invoked when the context menu
22565     * for this view is being built.
22566     */
22567    public interface OnCreateContextMenuListener {
22568        /**
22569         * Called when the context menu for this view is being built. It is not
22570         * safe to hold onto the menu after this method returns.
22571         *
22572         * @param menu The context menu that is being built
22573         * @param v The view for which the context menu is being built
22574         * @param menuInfo Extra information about the item for which the
22575         *            context menu should be shown. This information will vary
22576         *            depending on the class of v.
22577         */
22578        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
22579    }
22580
22581    /**
22582     * Interface definition for a callback to be invoked when the status bar changes
22583     * visibility.  This reports <strong>global</strong> changes to the system UI
22584     * state, not what the application is requesting.
22585     *
22586     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
22587     */
22588    public interface OnSystemUiVisibilityChangeListener {
22589        /**
22590         * Called when the status bar changes visibility because of a call to
22591         * {@link View#setSystemUiVisibility(int)}.
22592         *
22593         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22594         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
22595         * This tells you the <strong>global</strong> state of these UI visibility
22596         * flags, not what your app is currently applying.
22597         */
22598        public void onSystemUiVisibilityChange(int visibility);
22599    }
22600
22601    /**
22602     * Interface definition for a callback to be invoked when this view is attached
22603     * or detached from its window.
22604     */
22605    public interface OnAttachStateChangeListener {
22606        /**
22607         * Called when the view is attached to a window.
22608         * @param v The view that was attached
22609         */
22610        public void onViewAttachedToWindow(View v);
22611        /**
22612         * Called when the view is detached from a window.
22613         * @param v The view that was detached
22614         */
22615        public void onViewDetachedFromWindow(View v);
22616    }
22617
22618    /**
22619     * Listener for applying window insets on a view in a custom way.
22620     *
22621     * <p>Apps may choose to implement this interface if they want to apply custom policy
22622     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
22623     * is set, its
22624     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
22625     * method will be called instead of the View's own
22626     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
22627     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
22628     * the View's normal behavior as part of its own.</p>
22629     */
22630    public interface OnApplyWindowInsetsListener {
22631        /**
22632         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
22633         * on a View, this listener method will be called instead of the view's own
22634         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
22635         *
22636         * @param v The view applying window insets
22637         * @param insets The insets to apply
22638         * @return The insets supplied, minus any insets that were consumed
22639         */
22640        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
22641    }
22642
22643    private final class UnsetPressedState implements Runnable {
22644        @Override
22645        public void run() {
22646            setPressed(false);
22647        }
22648    }
22649
22650    /**
22651     * Base class for derived classes that want to save and restore their own
22652     * state in {@link android.view.View#onSaveInstanceState()}.
22653     */
22654    public static class BaseSavedState extends AbsSavedState {
22655        String mStartActivityRequestWhoSaved;
22656
22657        /**
22658         * Constructor used when reading from a parcel. Reads the state of the superclass.
22659         *
22660         * @param source parcel to read from
22661         */
22662        public BaseSavedState(Parcel source) {
22663            this(source, null);
22664        }
22665
22666        /**
22667         * Constructor used when reading from a parcel using a given class loader.
22668         * Reads the state of the superclass.
22669         *
22670         * @param source parcel to read from
22671         * @param loader ClassLoader to use for reading
22672         */
22673        public BaseSavedState(Parcel source, ClassLoader loader) {
22674            super(source, loader);
22675            mStartActivityRequestWhoSaved = source.readString();
22676        }
22677
22678        /**
22679         * Constructor called by derived classes when creating their SavedState objects
22680         *
22681         * @param superState The state of the superclass of this view
22682         */
22683        public BaseSavedState(Parcelable superState) {
22684            super(superState);
22685        }
22686
22687        @Override
22688        public void writeToParcel(Parcel out, int flags) {
22689            super.writeToParcel(out, flags);
22690            out.writeString(mStartActivityRequestWhoSaved);
22691        }
22692
22693        public static final Parcelable.Creator<BaseSavedState> CREATOR
22694                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
22695            @Override
22696            public BaseSavedState createFromParcel(Parcel in) {
22697                return new BaseSavedState(in);
22698            }
22699
22700            @Override
22701            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
22702                return new BaseSavedState(in, loader);
22703            }
22704
22705            @Override
22706            public BaseSavedState[] newArray(int size) {
22707                return new BaseSavedState[size];
22708            }
22709        };
22710    }
22711
22712    /**
22713     * A set of information given to a view when it is attached to its parent
22714     * window.
22715     */
22716    final static class AttachInfo {
22717        interface Callbacks {
22718            void playSoundEffect(int effectId);
22719            boolean performHapticFeedback(int effectId, boolean always);
22720        }
22721
22722        /**
22723         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
22724         * to a Handler. This class contains the target (View) to invalidate and
22725         * the coordinates of the dirty rectangle.
22726         *
22727         * For performance purposes, this class also implements a pool of up to
22728         * POOL_LIMIT objects that get reused. This reduces memory allocations
22729         * whenever possible.
22730         */
22731        static class InvalidateInfo {
22732            private static final int POOL_LIMIT = 10;
22733
22734            private static final SynchronizedPool<InvalidateInfo> sPool =
22735                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
22736
22737            View target;
22738
22739            int left;
22740            int top;
22741            int right;
22742            int bottom;
22743
22744            public static InvalidateInfo obtain() {
22745                InvalidateInfo instance = sPool.acquire();
22746                return (instance != null) ? instance : new InvalidateInfo();
22747            }
22748
22749            public void recycle() {
22750                target = null;
22751                sPool.release(this);
22752            }
22753        }
22754
22755        final IWindowSession mSession;
22756
22757        final IWindow mWindow;
22758
22759        final IBinder mWindowToken;
22760
22761        final Display mDisplay;
22762
22763        final Callbacks mRootCallbacks;
22764
22765        IWindowId mIWindowId;
22766        WindowId mWindowId;
22767
22768        /**
22769         * The top view of the hierarchy.
22770         */
22771        View mRootView;
22772
22773        IBinder mPanelParentWindowToken;
22774
22775        boolean mHardwareAccelerated;
22776        boolean mHardwareAccelerationRequested;
22777        ThreadedRenderer mHardwareRenderer;
22778        List<RenderNode> mPendingAnimatingRenderNodes;
22779
22780        /**
22781         * The state of the display to which the window is attached, as reported
22782         * by {@link Display#getState()}.  Note that the display state constants
22783         * declared by {@link Display} do not exactly line up with the screen state
22784         * constants declared by {@link View} (there are more display states than
22785         * screen states).
22786         */
22787        int mDisplayState = Display.STATE_UNKNOWN;
22788
22789        /**
22790         * Scale factor used by the compatibility mode
22791         */
22792        float mApplicationScale;
22793
22794        /**
22795         * Indicates whether the application is in compatibility mode
22796         */
22797        boolean mScalingRequired;
22798
22799        /**
22800         * Left position of this view's window
22801         */
22802        int mWindowLeft;
22803
22804        /**
22805         * Top position of this view's window
22806         */
22807        int mWindowTop;
22808
22809        /**
22810         * Indicates whether views need to use 32-bit drawing caches
22811         */
22812        boolean mUse32BitDrawingCache;
22813
22814        /**
22815         * For windows that are full-screen but using insets to layout inside
22816         * of the screen areas, these are the current insets to appear inside
22817         * the overscan area of the display.
22818         */
22819        final Rect mOverscanInsets = new Rect();
22820
22821        /**
22822         * For windows that are full-screen but using insets to layout inside
22823         * of the screen decorations, these are the current insets for the
22824         * content of the window.
22825         */
22826        final Rect mContentInsets = new Rect();
22827
22828        /**
22829         * For windows that are full-screen but using insets to layout inside
22830         * of the screen decorations, these are the current insets for the
22831         * actual visible parts of the window.
22832         */
22833        final Rect mVisibleInsets = new Rect();
22834
22835        /**
22836         * For windows that are full-screen but using insets to layout inside
22837         * of the screen decorations, these are the current insets for the
22838         * stable system windows.
22839         */
22840        final Rect mStableInsets = new Rect();
22841
22842        /**
22843         * For windows that include areas that are not covered by real surface these are the outsets
22844         * for real surface.
22845         */
22846        final Rect mOutsets = new Rect();
22847
22848        /**
22849         * In multi-window we force show the navigation bar. Because we don't want that the surface
22850         * size changes in this mode, we instead have a flag whether the navigation bar size should
22851         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
22852         */
22853        boolean mAlwaysConsumeNavBar;
22854
22855        /**
22856         * The internal insets given by this window.  This value is
22857         * supplied by the client (through
22858         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
22859         * be given to the window manager when changed to be used in laying
22860         * out windows behind it.
22861         */
22862        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
22863                = new ViewTreeObserver.InternalInsetsInfo();
22864
22865        /**
22866         * Set to true when mGivenInternalInsets is non-empty.
22867         */
22868        boolean mHasNonEmptyGivenInternalInsets;
22869
22870        /**
22871         * All views in the window's hierarchy that serve as scroll containers,
22872         * used to determine if the window can be resized or must be panned
22873         * to adjust for a soft input area.
22874         */
22875        final ArrayList<View> mScrollContainers = new ArrayList<View>();
22876
22877        final KeyEvent.DispatcherState mKeyDispatchState
22878                = new KeyEvent.DispatcherState();
22879
22880        /**
22881         * Indicates whether the view's window currently has the focus.
22882         */
22883        boolean mHasWindowFocus;
22884
22885        /**
22886         * The current visibility of the window.
22887         */
22888        int mWindowVisibility;
22889
22890        /**
22891         * Indicates the time at which drawing started to occur.
22892         */
22893        long mDrawingTime;
22894
22895        /**
22896         * Indicates whether or not ignoring the DIRTY_MASK flags.
22897         */
22898        boolean mIgnoreDirtyState;
22899
22900        /**
22901         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
22902         * to avoid clearing that flag prematurely.
22903         */
22904        boolean mSetIgnoreDirtyState = false;
22905
22906        /**
22907         * Indicates whether the view's window is currently in touch mode.
22908         */
22909        boolean mInTouchMode;
22910
22911        /**
22912         * Indicates whether the view has requested unbuffered input dispatching for the current
22913         * event stream.
22914         */
22915        boolean mUnbufferedDispatchRequested;
22916
22917        /**
22918         * Indicates that ViewAncestor should trigger a global layout change
22919         * the next time it performs a traversal
22920         */
22921        boolean mRecomputeGlobalAttributes;
22922
22923        /**
22924         * Always report new attributes at next traversal.
22925         */
22926        boolean mForceReportNewAttributes;
22927
22928        /**
22929         * Set during a traveral if any views want to keep the screen on.
22930         */
22931        boolean mKeepScreenOn;
22932
22933        /**
22934         * Set during a traveral if the light center needs to be updated.
22935         */
22936        boolean mNeedsUpdateLightCenter;
22937
22938        /**
22939         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
22940         */
22941        int mSystemUiVisibility;
22942
22943        /**
22944         * Hack to force certain system UI visibility flags to be cleared.
22945         */
22946        int mDisabledSystemUiVisibility;
22947
22948        /**
22949         * Last global system UI visibility reported by the window manager.
22950         */
22951        int mGlobalSystemUiVisibility = -1;
22952
22953        /**
22954         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
22955         * attached.
22956         */
22957        boolean mHasSystemUiListeners;
22958
22959        /**
22960         * Set if the window has requested to extend into the overscan region
22961         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
22962         */
22963        boolean mOverscanRequested;
22964
22965        /**
22966         * Set if the visibility of any views has changed.
22967         */
22968        boolean mViewVisibilityChanged;
22969
22970        /**
22971         * Set to true if a view has been scrolled.
22972         */
22973        boolean mViewScrollChanged;
22974
22975        /**
22976         * Set to true if high contrast mode enabled
22977         */
22978        boolean mHighContrastText;
22979
22980        /**
22981         * Set to true if a pointer event is currently being handled.
22982         */
22983        boolean mHandlingPointerEvent;
22984
22985        /**
22986         * Global to the view hierarchy used as a temporary for dealing with
22987         * x/y points in the transparent region computations.
22988         */
22989        final int[] mTransparentLocation = new int[2];
22990
22991        /**
22992         * Global to the view hierarchy used as a temporary for dealing with
22993         * x/y points in the ViewGroup.invalidateChild implementation.
22994         */
22995        final int[] mInvalidateChildLocation = new int[2];
22996
22997        /**
22998         * Global to the view hierarchy used as a temporary for dealing with
22999         * computing absolute on-screen location.
23000         */
23001        final int[] mTmpLocation = new int[2];
23002
23003        /**
23004         * Global to the view hierarchy used as a temporary for dealing with
23005         * x/y location when view is transformed.
23006         */
23007        final float[] mTmpTransformLocation = new float[2];
23008
23009        /**
23010         * The view tree observer used to dispatch global events like
23011         * layout, pre-draw, touch mode change, etc.
23012         */
23013        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
23014
23015        /**
23016         * A Canvas used by the view hierarchy to perform bitmap caching.
23017         */
23018        Canvas mCanvas;
23019
23020        /**
23021         * The view root impl.
23022         */
23023        final ViewRootImpl mViewRootImpl;
23024
23025        /**
23026         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
23027         * handler can be used to pump events in the UI events queue.
23028         */
23029        final Handler mHandler;
23030
23031        /**
23032         * Temporary for use in computing invalidate rectangles while
23033         * calling up the hierarchy.
23034         */
23035        final Rect mTmpInvalRect = new Rect();
23036
23037        /**
23038         * Temporary for use in computing hit areas with transformed views
23039         */
23040        final RectF mTmpTransformRect = new RectF();
23041
23042        /**
23043         * Temporary for use in computing hit areas with transformed views
23044         */
23045        final RectF mTmpTransformRect1 = new RectF();
23046
23047        /**
23048         * Temporary list of rectanges.
23049         */
23050        final List<RectF> mTmpRectList = new ArrayList<>();
23051
23052        /**
23053         * Temporary for use in transforming invalidation rect
23054         */
23055        final Matrix mTmpMatrix = new Matrix();
23056
23057        /**
23058         * Temporary for use in transforming invalidation rect
23059         */
23060        final Transformation mTmpTransformation = new Transformation();
23061
23062        /**
23063         * Temporary for use in querying outlines from OutlineProviders
23064         */
23065        final Outline mTmpOutline = new Outline();
23066
23067        /**
23068         * Temporary list for use in collecting focusable descendents of a view.
23069         */
23070        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
23071
23072        /**
23073         * The id of the window for accessibility purposes.
23074         */
23075        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
23076
23077        /**
23078         * Flags related to accessibility processing.
23079         *
23080         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
23081         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
23082         */
23083        int mAccessibilityFetchFlags;
23084
23085        /**
23086         * The drawable for highlighting accessibility focus.
23087         */
23088        Drawable mAccessibilityFocusDrawable;
23089
23090        /**
23091         * Show where the margins, bounds and layout bounds are for each view.
23092         */
23093        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
23094
23095        /**
23096         * Point used to compute visible regions.
23097         */
23098        final Point mPoint = new Point();
23099
23100        /**
23101         * Used to track which View originated a requestLayout() call, used when
23102         * requestLayout() is called during layout.
23103         */
23104        View mViewRequestingLayout;
23105
23106        /**
23107         * Used to track views that need (at least) a partial relayout at their current size
23108         * during the next traversal.
23109         */
23110        List<View> mPartialLayoutViews = new ArrayList<>();
23111
23112        /**
23113         * Swapped with mPartialLayoutViews during layout to avoid concurrent
23114         * modification. Lazily assigned during ViewRootImpl layout.
23115         */
23116        List<View> mEmptyPartialLayoutViews;
23117
23118        /**
23119         * Used to track the identity of the current drag operation.
23120         */
23121        IBinder mDragToken;
23122
23123        /**
23124         * The drag shadow surface for the current drag operation.
23125         */
23126        public Surface mDragSurface;
23127
23128        /**
23129         * Creates a new set of attachment information with the specified
23130         * events handler and thread.
23131         *
23132         * @param handler the events handler the view must use
23133         */
23134        AttachInfo(IWindowSession session, IWindow window, Display display,
23135                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
23136            mSession = session;
23137            mWindow = window;
23138            mWindowToken = window.asBinder();
23139            mDisplay = display;
23140            mViewRootImpl = viewRootImpl;
23141            mHandler = handler;
23142            mRootCallbacks = effectPlayer;
23143        }
23144    }
23145
23146    /**
23147     * <p>ScrollabilityCache holds various fields used by a View when scrolling
23148     * is supported. This avoids keeping too many unused fields in most
23149     * instances of View.</p>
23150     */
23151    private static class ScrollabilityCache implements Runnable {
23152
23153        /**
23154         * Scrollbars are not visible
23155         */
23156        public static final int OFF = 0;
23157
23158        /**
23159         * Scrollbars are visible
23160         */
23161        public static final int ON = 1;
23162
23163        /**
23164         * Scrollbars are fading away
23165         */
23166        public static final int FADING = 2;
23167
23168        public boolean fadeScrollBars;
23169
23170        public int fadingEdgeLength;
23171        public int scrollBarDefaultDelayBeforeFade;
23172        public int scrollBarFadeDuration;
23173
23174        public int scrollBarSize;
23175        public ScrollBarDrawable scrollBar;
23176        public float[] interpolatorValues;
23177        public View host;
23178
23179        public final Paint paint;
23180        public final Matrix matrix;
23181        public Shader shader;
23182
23183        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
23184
23185        private static final float[] OPAQUE = { 255 };
23186        private static final float[] TRANSPARENT = { 0.0f };
23187
23188        /**
23189         * When fading should start. This time moves into the future every time
23190         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
23191         */
23192        public long fadeStartTime;
23193
23194
23195        /**
23196         * The current state of the scrollbars: ON, OFF, or FADING
23197         */
23198        public int state = OFF;
23199
23200        private int mLastColor;
23201
23202        public final Rect mScrollBarBounds = new Rect();
23203
23204        public static final int NOT_DRAGGING = 0;
23205        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
23206        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
23207        public int mScrollBarDraggingState = NOT_DRAGGING;
23208
23209        public float mScrollBarDraggingPos = 0;
23210
23211        public ScrollabilityCache(ViewConfiguration configuration, View host) {
23212            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
23213            scrollBarSize = configuration.getScaledScrollBarSize();
23214            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
23215            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
23216
23217            paint = new Paint();
23218            matrix = new Matrix();
23219            // use use a height of 1, and then wack the matrix each time we
23220            // actually use it.
23221            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23222            paint.setShader(shader);
23223            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23224
23225            this.host = host;
23226        }
23227
23228        public void setFadeColor(int color) {
23229            if (color != mLastColor) {
23230                mLastColor = color;
23231
23232                if (color != 0) {
23233                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
23234                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
23235                    paint.setShader(shader);
23236                    // Restore the default transfer mode (src_over)
23237                    paint.setXfermode(null);
23238                } else {
23239                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23240                    paint.setShader(shader);
23241                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23242                }
23243            }
23244        }
23245
23246        public void run() {
23247            long now = AnimationUtils.currentAnimationTimeMillis();
23248            if (now >= fadeStartTime) {
23249
23250                // the animation fades the scrollbars out by changing
23251                // the opacity (alpha) from fully opaque to fully
23252                // transparent
23253                int nextFrame = (int) now;
23254                int framesCount = 0;
23255
23256                Interpolator interpolator = scrollBarInterpolator;
23257
23258                // Start opaque
23259                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
23260
23261                // End transparent
23262                nextFrame += scrollBarFadeDuration;
23263                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
23264
23265                state = FADING;
23266
23267                // Kick off the fade animation
23268                host.invalidate(true);
23269            }
23270        }
23271    }
23272
23273    /**
23274     * Resuable callback for sending
23275     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
23276     */
23277    private class SendViewScrolledAccessibilityEvent implements Runnable {
23278        public volatile boolean mIsPending;
23279
23280        public void run() {
23281            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
23282            mIsPending = false;
23283        }
23284    }
23285
23286    /**
23287     * <p>
23288     * This class represents a delegate that can be registered in a {@link View}
23289     * to enhance accessibility support via composition rather via inheritance.
23290     * It is specifically targeted to widget developers that extend basic View
23291     * classes i.e. classes in package android.view, that would like their
23292     * applications to be backwards compatible.
23293     * </p>
23294     * <div class="special reference">
23295     * <h3>Developer Guides</h3>
23296     * <p>For more information about making applications accessible, read the
23297     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
23298     * developer guide.</p>
23299     * </div>
23300     * <p>
23301     * A scenario in which a developer would like to use an accessibility delegate
23302     * is overriding a method introduced in a later API version then the minimal API
23303     * version supported by the application. For example, the method
23304     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
23305     * in API version 4 when the accessibility APIs were first introduced. If a
23306     * developer would like his application to run on API version 4 devices (assuming
23307     * all other APIs used by the application are version 4 or lower) and take advantage
23308     * of this method, instead of overriding the method which would break the application's
23309     * backwards compatibility, he can override the corresponding method in this
23310     * delegate and register the delegate in the target View if the API version of
23311     * the system is high enough i.e. the API version is same or higher to the API
23312     * version that introduced
23313     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
23314     * </p>
23315     * <p>
23316     * Here is an example implementation:
23317     * </p>
23318     * <code><pre><p>
23319     * if (Build.VERSION.SDK_INT >= 14) {
23320     *     // If the API version is equal of higher than the version in
23321     *     // which onInitializeAccessibilityNodeInfo was introduced we
23322     *     // register a delegate with a customized implementation.
23323     *     View view = findViewById(R.id.view_id);
23324     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
23325     *         public void onInitializeAccessibilityNodeInfo(View host,
23326     *                 AccessibilityNodeInfo info) {
23327     *             // Let the default implementation populate the info.
23328     *             super.onInitializeAccessibilityNodeInfo(host, info);
23329     *             // Set some other information.
23330     *             info.setEnabled(host.isEnabled());
23331     *         }
23332     *     });
23333     * }
23334     * </code></pre></p>
23335     * <p>
23336     * This delegate contains methods that correspond to the accessibility methods
23337     * in View. If a delegate has been specified the implementation in View hands
23338     * off handling to the corresponding method in this delegate. The default
23339     * implementation the delegate methods behaves exactly as the corresponding
23340     * method in View for the case of no accessibility delegate been set. Hence,
23341     * to customize the behavior of a View method, clients can override only the
23342     * corresponding delegate method without altering the behavior of the rest
23343     * accessibility related methods of the host view.
23344     * </p>
23345     * <p>
23346     * <strong>Note:</strong> On platform versions prior to
23347     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
23348     * views in the {@code android.widget.*} package are called <i>before</i>
23349     * host methods. This prevents certain properties such as class name from
23350     * being modified by overriding
23351     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
23352     * as any changes will be overwritten by the host class.
23353     * <p>
23354     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
23355     * methods are called <i>after</i> host methods, which all properties to be
23356     * modified without being overwritten by the host class.
23357     */
23358    public static class AccessibilityDelegate {
23359
23360        /**
23361         * Sends an accessibility event of the given type. If accessibility is not
23362         * enabled this method has no effect.
23363         * <p>
23364         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
23365         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
23366         * been set.
23367         * </p>
23368         *
23369         * @param host The View hosting the delegate.
23370         * @param eventType The type of the event to send.
23371         *
23372         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
23373         */
23374        public void sendAccessibilityEvent(View host, int eventType) {
23375            host.sendAccessibilityEventInternal(eventType);
23376        }
23377
23378        /**
23379         * Performs the specified accessibility action on the view. For
23380         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
23381         * <p>
23382         * The default implementation behaves as
23383         * {@link View#performAccessibilityAction(int, Bundle)
23384         *  View#performAccessibilityAction(int, Bundle)} for the case of
23385         *  no accessibility delegate been set.
23386         * </p>
23387         *
23388         * @param action The action to perform.
23389         * @return Whether the action was performed.
23390         *
23391         * @see View#performAccessibilityAction(int, Bundle)
23392         *      View#performAccessibilityAction(int, Bundle)
23393         */
23394        public boolean performAccessibilityAction(View host, int action, Bundle args) {
23395            return host.performAccessibilityActionInternal(action, args);
23396        }
23397
23398        /**
23399         * Sends an accessibility event. This method behaves exactly as
23400         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
23401         * empty {@link AccessibilityEvent} and does not perform a check whether
23402         * accessibility is enabled.
23403         * <p>
23404         * The default implementation behaves as
23405         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23406         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
23407         * the case of no accessibility delegate been set.
23408         * </p>
23409         *
23410         * @param host The View hosting the delegate.
23411         * @param event The event to send.
23412         *
23413         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23414         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23415         */
23416        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
23417            host.sendAccessibilityEventUncheckedInternal(event);
23418        }
23419
23420        /**
23421         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
23422         * to its children for adding their text content to the event.
23423         * <p>
23424         * The default implementation behaves as
23425         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23426         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
23427         * the case of no accessibility delegate been set.
23428         * </p>
23429         *
23430         * @param host The View hosting the delegate.
23431         * @param event The event.
23432         * @return True if the event population was completed.
23433         *
23434         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23435         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23436         */
23437        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23438            return host.dispatchPopulateAccessibilityEventInternal(event);
23439        }
23440
23441        /**
23442         * Gives a chance to the host View to populate the accessibility event with its
23443         * text content.
23444         * <p>
23445         * The default implementation behaves as
23446         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
23447         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
23448         * the case of no accessibility delegate been set.
23449         * </p>
23450         *
23451         * @param host The View hosting the delegate.
23452         * @param event The accessibility event which to populate.
23453         *
23454         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
23455         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
23456         */
23457        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23458            host.onPopulateAccessibilityEventInternal(event);
23459        }
23460
23461        /**
23462         * Initializes an {@link AccessibilityEvent} with information about the
23463         * the host View which is the event source.
23464         * <p>
23465         * The default implementation behaves as
23466         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
23467         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
23468         * the case of no accessibility delegate been set.
23469         * </p>
23470         *
23471         * @param host The View hosting the delegate.
23472         * @param event The event to initialize.
23473         *
23474         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
23475         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
23476         */
23477        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
23478            host.onInitializeAccessibilityEventInternal(event);
23479        }
23480
23481        /**
23482         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
23483         * <p>
23484         * The default implementation behaves as
23485         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23486         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
23487         * the case of no accessibility delegate been set.
23488         * </p>
23489         *
23490         * @param host The View hosting the delegate.
23491         * @param info The instance to initialize.
23492         *
23493         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23494         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23495         */
23496        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
23497            host.onInitializeAccessibilityNodeInfoInternal(info);
23498        }
23499
23500        /**
23501         * Called when a child of the host View has requested sending an
23502         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
23503         * to augment the event.
23504         * <p>
23505         * The default implementation behaves as
23506         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23507         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
23508         * the case of no accessibility delegate been set.
23509         * </p>
23510         *
23511         * @param host The View hosting the delegate.
23512         * @param child The child which requests sending the event.
23513         * @param event The event to be sent.
23514         * @return True if the event should be sent
23515         *
23516         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23517         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23518         */
23519        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
23520                AccessibilityEvent event) {
23521            return host.onRequestSendAccessibilityEventInternal(child, event);
23522        }
23523
23524        /**
23525         * Gets the provider for managing a virtual view hierarchy rooted at this View
23526         * and reported to {@link android.accessibilityservice.AccessibilityService}s
23527         * that explore the window content.
23528         * <p>
23529         * The default implementation behaves as
23530         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
23531         * the case of no accessibility delegate been set.
23532         * </p>
23533         *
23534         * @return The provider.
23535         *
23536         * @see AccessibilityNodeProvider
23537         */
23538        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
23539            return null;
23540        }
23541
23542        /**
23543         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
23544         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
23545         * This method is responsible for obtaining an accessibility node info from a
23546         * pool of reusable instances and calling
23547         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
23548         * view to initialize the former.
23549         * <p>
23550         * <strong>Note:</strong> The client is responsible for recycling the obtained
23551         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
23552         * creation.
23553         * </p>
23554         * <p>
23555         * The default implementation behaves as
23556         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
23557         * the case of no accessibility delegate been set.
23558         * </p>
23559         * @return A populated {@link AccessibilityNodeInfo}.
23560         *
23561         * @see AccessibilityNodeInfo
23562         *
23563         * @hide
23564         */
23565        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
23566            return host.createAccessibilityNodeInfoInternal();
23567        }
23568    }
23569
23570    private class MatchIdPredicate implements Predicate<View> {
23571        public int mId;
23572
23573        @Override
23574        public boolean apply(View view) {
23575            return (view.mID == mId);
23576        }
23577    }
23578
23579    private class MatchLabelForPredicate implements Predicate<View> {
23580        private int mLabeledId;
23581
23582        @Override
23583        public boolean apply(View view) {
23584            return (view.mLabelForId == mLabeledId);
23585        }
23586    }
23587
23588    private class SendViewStateChangedAccessibilityEvent implements Runnable {
23589        private int mChangeTypes = 0;
23590        private boolean mPosted;
23591        private boolean mPostedWithDelay;
23592        private long mLastEventTimeMillis;
23593
23594        @Override
23595        public void run() {
23596            mPosted = false;
23597            mPostedWithDelay = false;
23598            mLastEventTimeMillis = SystemClock.uptimeMillis();
23599            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
23600                final AccessibilityEvent event = AccessibilityEvent.obtain();
23601                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
23602                event.setContentChangeTypes(mChangeTypes);
23603                sendAccessibilityEventUnchecked(event);
23604            }
23605            mChangeTypes = 0;
23606        }
23607
23608        public void runOrPost(int changeType) {
23609            mChangeTypes |= changeType;
23610
23611            // If this is a live region or the child of a live region, collect
23612            // all events from this frame and send them on the next frame.
23613            if (inLiveRegion()) {
23614                // If we're already posted with a delay, remove that.
23615                if (mPostedWithDelay) {
23616                    removeCallbacks(this);
23617                    mPostedWithDelay = false;
23618                }
23619                // Only post if we're not already posted.
23620                if (!mPosted) {
23621                    post(this);
23622                    mPosted = true;
23623                }
23624                return;
23625            }
23626
23627            if (mPosted) {
23628                return;
23629            }
23630
23631            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
23632            final long minEventIntevalMillis =
23633                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
23634            if (timeSinceLastMillis >= minEventIntevalMillis) {
23635                removeCallbacks(this);
23636                run();
23637            } else {
23638                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
23639                mPostedWithDelay = true;
23640            }
23641        }
23642    }
23643
23644    private boolean inLiveRegion() {
23645        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23646            return true;
23647        }
23648
23649        ViewParent parent = getParent();
23650        while (parent instanceof View) {
23651            if (((View) parent).getAccessibilityLiveRegion()
23652                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23653                return true;
23654            }
23655            parent = parent.getParent();
23656        }
23657
23658        return false;
23659    }
23660
23661    /**
23662     * Dump all private flags in readable format, useful for documentation and
23663     * sanity checking.
23664     */
23665    private static void dumpFlags() {
23666        final HashMap<String, String> found = Maps.newHashMap();
23667        try {
23668            for (Field field : View.class.getDeclaredFields()) {
23669                final int modifiers = field.getModifiers();
23670                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
23671                    if (field.getType().equals(int.class)) {
23672                        final int value = field.getInt(null);
23673                        dumpFlag(found, field.getName(), value);
23674                    } else if (field.getType().equals(int[].class)) {
23675                        final int[] values = (int[]) field.get(null);
23676                        for (int i = 0; i < values.length; i++) {
23677                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
23678                        }
23679                    }
23680                }
23681            }
23682        } catch (IllegalAccessException e) {
23683            throw new RuntimeException(e);
23684        }
23685
23686        final ArrayList<String> keys = Lists.newArrayList();
23687        keys.addAll(found.keySet());
23688        Collections.sort(keys);
23689        for (String key : keys) {
23690            Log.d(VIEW_LOG_TAG, found.get(key));
23691        }
23692    }
23693
23694    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
23695        // Sort flags by prefix, then by bits, always keeping unique keys
23696        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
23697        final int prefix = name.indexOf('_');
23698        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
23699        final String output = bits + " " + name;
23700        found.put(key, output);
23701    }
23702
23703    /** {@hide} */
23704    public void encode(@NonNull ViewHierarchyEncoder stream) {
23705        stream.beginObject(this);
23706        encodeProperties(stream);
23707        stream.endObject();
23708    }
23709
23710    /** {@hide} */
23711    @CallSuper
23712    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
23713        Object resolveId = ViewDebug.resolveId(getContext(), mID);
23714        if (resolveId instanceof String) {
23715            stream.addProperty("id", (String) resolveId);
23716        } else {
23717            stream.addProperty("id", mID);
23718        }
23719
23720        stream.addProperty("misc:transformation.alpha",
23721                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
23722        stream.addProperty("misc:transitionName", getTransitionName());
23723
23724        // layout
23725        stream.addProperty("layout:left", mLeft);
23726        stream.addProperty("layout:right", mRight);
23727        stream.addProperty("layout:top", mTop);
23728        stream.addProperty("layout:bottom", mBottom);
23729        stream.addProperty("layout:width", getWidth());
23730        stream.addProperty("layout:height", getHeight());
23731        stream.addProperty("layout:layoutDirection", getLayoutDirection());
23732        stream.addProperty("layout:layoutRtl", isLayoutRtl());
23733        stream.addProperty("layout:hasTransientState", hasTransientState());
23734        stream.addProperty("layout:baseline", getBaseline());
23735
23736        // layout params
23737        ViewGroup.LayoutParams layoutParams = getLayoutParams();
23738        if (layoutParams != null) {
23739            stream.addPropertyKey("layoutParams");
23740            layoutParams.encode(stream);
23741        }
23742
23743        // scrolling
23744        stream.addProperty("scrolling:scrollX", mScrollX);
23745        stream.addProperty("scrolling:scrollY", mScrollY);
23746
23747        // padding
23748        stream.addProperty("padding:paddingLeft", mPaddingLeft);
23749        stream.addProperty("padding:paddingRight", mPaddingRight);
23750        stream.addProperty("padding:paddingTop", mPaddingTop);
23751        stream.addProperty("padding:paddingBottom", mPaddingBottom);
23752        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
23753        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
23754        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
23755        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
23756        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
23757
23758        // measurement
23759        stream.addProperty("measurement:minHeight", mMinHeight);
23760        stream.addProperty("measurement:minWidth", mMinWidth);
23761        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
23762        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
23763
23764        // drawing
23765        stream.addProperty("drawing:elevation", getElevation());
23766        stream.addProperty("drawing:translationX", getTranslationX());
23767        stream.addProperty("drawing:translationY", getTranslationY());
23768        stream.addProperty("drawing:translationZ", getTranslationZ());
23769        stream.addProperty("drawing:rotation", getRotation());
23770        stream.addProperty("drawing:rotationX", getRotationX());
23771        stream.addProperty("drawing:rotationY", getRotationY());
23772        stream.addProperty("drawing:scaleX", getScaleX());
23773        stream.addProperty("drawing:scaleY", getScaleY());
23774        stream.addProperty("drawing:pivotX", getPivotX());
23775        stream.addProperty("drawing:pivotY", getPivotY());
23776        stream.addProperty("drawing:opaque", isOpaque());
23777        stream.addProperty("drawing:alpha", getAlpha());
23778        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
23779        stream.addProperty("drawing:shadow", hasShadow());
23780        stream.addProperty("drawing:solidColor", getSolidColor());
23781        stream.addProperty("drawing:layerType", mLayerType);
23782        stream.addProperty("drawing:willNotDraw", willNotDraw());
23783        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
23784        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
23785        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
23786        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
23787
23788        // focus
23789        stream.addProperty("focus:hasFocus", hasFocus());
23790        stream.addProperty("focus:isFocused", isFocused());
23791        stream.addProperty("focus:isFocusable", isFocusable());
23792        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
23793
23794        stream.addProperty("misc:clickable", isClickable());
23795        stream.addProperty("misc:pressed", isPressed());
23796        stream.addProperty("misc:selected", isSelected());
23797        stream.addProperty("misc:touchMode", isInTouchMode());
23798        stream.addProperty("misc:hovered", isHovered());
23799        stream.addProperty("misc:activated", isActivated());
23800
23801        stream.addProperty("misc:visibility", getVisibility());
23802        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
23803        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
23804
23805        stream.addProperty("misc:enabled", isEnabled());
23806        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
23807        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
23808
23809        // theme attributes
23810        Resources.Theme theme = getContext().getTheme();
23811        if (theme != null) {
23812            stream.addPropertyKey("theme");
23813            theme.encode(stream);
23814        }
23815
23816        // view attribute information
23817        int n = mAttributes != null ? mAttributes.length : 0;
23818        stream.addProperty("meta:__attrCount__", n/2);
23819        for (int i = 0; i < n; i += 2) {
23820            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
23821        }
23822
23823        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
23824
23825        // text
23826        stream.addProperty("text:textDirection", getTextDirection());
23827        stream.addProperty("text:textAlignment", getTextAlignment());
23828
23829        // accessibility
23830        CharSequence contentDescription = getContentDescription();
23831        stream.addProperty("accessibility:contentDescription",
23832                contentDescription == null ? "" : contentDescription.toString());
23833        stream.addProperty("accessibility:labelFor", getLabelFor());
23834        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
23835    }
23836
23837    /**
23838     * Determine if this view is rendered on a round wearable device and is the main view
23839     * on the screen.
23840     */
23841    private boolean shouldDrawRoundScrollbar() {
23842        if (!mResources.getConfiguration().isScreenRound()) {
23843            return false;
23844        }
23845
23846        final View rootView = getRootView();
23847        final WindowInsets insets = getRootWindowInsets();
23848
23849        int height = getHeight();
23850        int width = getWidth();
23851        int displayHeight = rootView.getHeight();
23852        int displayWidth = rootView.getWidth();
23853
23854        if (height != displayHeight || width != displayWidth) {
23855            return false;
23856        }
23857
23858        getLocationOnScreen(mAttachInfo.mTmpLocation);
23859        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
23860                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
23861    }
23862}
23863