View.java revision 5a32c4c0b63bd35452931882a565969cf778c1f3
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.Insets;
44import android.graphics.Interpolator;
45import android.graphics.LinearGradient;
46import android.graphics.Matrix;
47import android.graphics.Outline;
48import android.graphics.Paint;
49import android.graphics.PixelFormat;
50import android.graphics.Point;
51import android.graphics.PorterDuff;
52import android.graphics.PorterDuffXfermode;
53import android.graphics.Rect;
54import android.graphics.RectF;
55import android.graphics.Region;
56import android.graphics.Shader;
57import android.graphics.drawable.ColorDrawable;
58import android.graphics.drawable.Drawable;
59import android.hardware.display.DisplayManagerGlobal;
60import android.os.Build.VERSION_CODES;
61import android.os.Bundle;
62import android.os.Handler;
63import android.os.IBinder;
64import android.os.Parcel;
65import android.os.Parcelable;
66import android.os.RemoteException;
67import android.os.SystemClock;
68import android.os.SystemProperties;
69import android.os.Trace;
70import android.text.TextUtils;
71import android.util.AttributeSet;
72import android.util.FloatProperty;
73import android.util.LayoutDirection;
74import android.util.Log;
75import android.util.LongSparseLongArray;
76import android.util.Pools.SynchronizedPool;
77import android.util.Property;
78import android.util.SparseArray;
79import android.util.StateSet;
80import android.util.SuperNotCalledException;
81import android.util.TypedValue;
82import android.view.ContextMenu.ContextMenuInfo;
83import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
84import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
85import android.view.AccessibilityIterators.TextSegmentIterator;
86import android.view.AccessibilityIterators.WordTextSegmentIterator;
87import android.view.accessibility.AccessibilityEvent;
88import android.view.accessibility.AccessibilityEventSource;
89import android.view.accessibility.AccessibilityManager;
90import android.view.accessibility.AccessibilityNodeInfo;
91import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
92import android.view.accessibility.AccessibilityNodeProvider;
93import android.view.animation.Animation;
94import android.view.animation.AnimationUtils;
95import android.view.animation.Transformation;
96import android.view.inputmethod.EditorInfo;
97import android.view.inputmethod.InputConnection;
98import android.view.inputmethod.InputMethodManager;
99import android.widget.Checkable;
100import android.widget.FrameLayout;
101import android.widget.ScrollBarDrawable;
102import static android.os.Build.VERSION_CODES.*;
103import static java.lang.Math.max;
104
105import com.android.internal.R;
106import com.android.internal.util.Predicate;
107import com.android.internal.view.menu.MenuBuilder;
108import com.android.internal.widget.ScrollBarUtils;
109import com.google.android.collect.Lists;
110import com.google.android.collect.Maps;
111
112import java.lang.NullPointerException;
113import java.lang.annotation.Retention;
114import java.lang.annotation.RetentionPolicy;
115import java.lang.ref.WeakReference;
116import java.lang.reflect.Field;
117import java.lang.reflect.InvocationTargetException;
118import java.lang.reflect.Method;
119import java.lang.reflect.Modifier;
120import java.util.ArrayList;
121import java.util.Arrays;
122import java.util.Collections;
123import java.util.HashMap;
124import java.util.List;
125import java.util.Locale;
126import java.util.Map;
127import java.util.concurrent.CopyOnWriteArrayList;
128import java.util.concurrent.atomic.AtomicInteger;
129
130/**
131 * <p>
132 * This class represents the basic building block for user interface components. A View
133 * occupies a rectangular area on the screen and is responsible for drawing and
134 * event handling. View is the base class for <em>widgets</em>, which are
135 * used to create interactive UI components (buttons, text fields, etc.). The
136 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
137 * are invisible containers that hold other Views (or other ViewGroups) and define
138 * their layout properties.
139 * </p>
140 *
141 * <div class="special reference">
142 * <h3>Developer Guides</h3>
143 * <p>For information about using this class to develop your application's user interface,
144 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
145 * </div>
146 *
147 * <a name="Using"></a>
148 * <h3>Using Views</h3>
149 * <p>
150 * All of the views in a window are arranged in a single tree. You can add views
151 * either from code or by specifying a tree of views in one or more XML layout
152 * files. There are many specialized subclasses of views that act as controls or
153 * are capable of displaying text, images, or other content.
154 * </p>
155 * <p>
156 * Once you have created a tree of views, there are typically a few types of
157 * common operations you may wish to perform:
158 * <ul>
159 * <li><strong>Set properties:</strong> for example setting the text of a
160 * {@link android.widget.TextView}. The available properties and the methods
161 * that set them will vary among the different subclasses of views. Note that
162 * properties that are known at build time can be set in the XML layout
163 * files.</li>
164 * <li><strong>Set focus:</strong> The framework will handle moving focus in
165 * response to user input. To force focus to a specific view, call
166 * {@link #requestFocus}.</li>
167 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
168 * that will be notified when something interesting happens to the view. For
169 * example, all views will let you set a listener to be notified when the view
170 * gains or loses focus. You can register such a listener using
171 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
172 * Other view subclasses offer more specialized listeners. For example, a Button
173 * exposes a listener to notify clients when the button is clicked.</li>
174 * <li><strong>Set visibility:</strong> You can hide or show views using
175 * {@link #setVisibility(int)}.</li>
176 * </ul>
177 * </p>
178 * <p><em>
179 * Note: The Android framework is responsible for measuring, laying out and
180 * drawing views. You should not call methods that perform these actions on
181 * views yourself unless you are actually implementing a
182 * {@link android.view.ViewGroup}.
183 * </em></p>
184 *
185 * <a name="Lifecycle"></a>
186 * <h3>Implementing a Custom View</h3>
187 *
188 * <p>
189 * To implement a custom view, you will usually begin by providing overrides for
190 * some of the standard methods that the framework calls on all views. You do
191 * not need to override all of these methods. In fact, you can start by just
192 * overriding {@link #onDraw(android.graphics.Canvas)}.
193 * <table border="2" width="85%" align="center" cellpadding="5">
194 *     <thead>
195 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
196 *     </thead>
197 *
198 *     <tbody>
199 *     <tr>
200 *         <td rowspan="2">Creation</td>
201 *         <td>Constructors</td>
202 *         <td>There is a form of the constructor that are called when the view
203 *         is created from code and a form that is called when the view is
204 *         inflated from a layout file. The second form should parse and apply
205 *         any attributes defined in the layout file.
206 *         </td>
207 *     </tr>
208 *     <tr>
209 *         <td><code>{@link #onFinishInflate()}</code></td>
210 *         <td>Called after a view and all of its children has been inflated
211 *         from XML.</td>
212 *     </tr>
213 *
214 *     <tr>
215 *         <td rowspan="3">Layout</td>
216 *         <td><code>{@link #onMeasure(int, int)}</code></td>
217 *         <td>Called to determine the size requirements for this view and all
218 *         of its children.
219 *         </td>
220 *     </tr>
221 *     <tr>
222 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
223 *         <td>Called when this view should assign a size and position to all
224 *         of its children.
225 *         </td>
226 *     </tr>
227 *     <tr>
228 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
229 *         <td>Called when the size of this view has changed.
230 *         </td>
231 *     </tr>
232 *
233 *     <tr>
234 *         <td>Drawing</td>
235 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
236 *         <td>Called when the view should render its content.
237 *         </td>
238 *     </tr>
239 *
240 *     <tr>
241 *         <td rowspan="4">Event processing</td>
242 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
243 *         <td>Called when a new hardware key event occurs.
244 *         </td>
245 *     </tr>
246 *     <tr>
247 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
248 *         <td>Called when a hardware key up event occurs.
249 *         </td>
250 *     </tr>
251 *     <tr>
252 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
253 *         <td>Called when a trackball motion event occurs.
254 *         </td>
255 *     </tr>
256 *     <tr>
257 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
258 *         <td>Called when a touch screen motion event occurs.
259 *         </td>
260 *     </tr>
261 *
262 *     <tr>
263 *         <td rowspan="2">Focus</td>
264 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
265 *         <td>Called when the view gains or loses focus.
266 *         </td>
267 *     </tr>
268 *
269 *     <tr>
270 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
271 *         <td>Called when the window containing the view gains or loses focus.
272 *         </td>
273 *     </tr>
274 *
275 *     <tr>
276 *         <td rowspan="3">Attaching</td>
277 *         <td><code>{@link #onAttachedToWindow()}</code></td>
278 *         <td>Called when the view is attached to a window.
279 *         </td>
280 *     </tr>
281 *
282 *     <tr>
283 *         <td><code>{@link #onDetachedFromWindow}</code></td>
284 *         <td>Called when the view is detached from its window.
285 *         </td>
286 *     </tr>
287 *
288 *     <tr>
289 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
290 *         <td>Called when the visibility of the window containing the view
291 *         has changed.
292 *         </td>
293 *     </tr>
294 *     </tbody>
295 *
296 * </table>
297 * </p>
298 *
299 * <a name="IDs"></a>
300 * <h3>IDs</h3>
301 * Views may have an integer id associated with them. These ids are typically
302 * assigned in the layout XML files, and are used to find specific views within
303 * the view tree. A common pattern is to:
304 * <ul>
305 * <li>Define a Button in the layout file and assign it a unique ID.
306 * <pre>
307 * &lt;Button
308 *     android:id="@+id/my_button"
309 *     android:layout_width="wrap_content"
310 *     android:layout_height="wrap_content"
311 *     android:text="@string/my_button_text"/&gt;
312 * </pre></li>
313 * <li>From the onCreate method of an Activity, find the Button
314 * <pre class="prettyprint">
315 *      Button myButton = (Button) findViewById(R.id.my_button);
316 * </pre></li>
317 * </ul>
318 * <p>
319 * View IDs need not be unique throughout the tree, but it is good practice to
320 * ensure that they are at least unique within the part of the tree you are
321 * searching.
322 * </p>
323 *
324 * <a name="Position"></a>
325 * <h3>Position</h3>
326 * <p>
327 * The geometry of a view is that of a rectangle. A view has a location,
328 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
329 * two dimensions, expressed as a width and a height. The unit for location
330 * and dimensions is the pixel.
331 * </p>
332 *
333 * <p>
334 * It is possible to retrieve the location of a view by invoking the methods
335 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
336 * coordinate of the rectangle representing the view. The latter returns the
337 * top, or Y, coordinate of the rectangle representing the view. These methods
338 * both return the location of the view relative to its parent. For instance,
339 * when getLeft() returns 20, that means the view is located 20 pixels to the
340 * right of the left edge of its direct parent.
341 * </p>
342 *
343 * <p>
344 * In addition, several convenience methods are offered to avoid unnecessary
345 * computations, namely {@link #getRight()} and {@link #getBottom()}.
346 * These methods return the coordinates of the right and bottom edges of the
347 * rectangle representing the view. For instance, calling {@link #getRight()}
348 * is similar to the following computation: <code>getLeft() + getWidth()</code>
349 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
350 * </p>
351 *
352 * <a name="SizePaddingMargins"></a>
353 * <h3>Size, padding and margins</h3>
354 * <p>
355 * The size of a view is expressed with a width and a height. A view actually
356 * possess two pairs of width and height values.
357 * </p>
358 *
359 * <p>
360 * The first pair is known as <em>measured width</em> and
361 * <em>measured height</em>. These dimensions define how big a view wants to be
362 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
363 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
364 * and {@link #getMeasuredHeight()}.
365 * </p>
366 *
367 * <p>
368 * The second pair is simply known as <em>width</em> and <em>height</em>, or
369 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
370 * dimensions define the actual size of the view on screen, at drawing time and
371 * after layout. These values may, but do not have to, be different from the
372 * measured width and height. The width and height can be obtained by calling
373 * {@link #getWidth()} and {@link #getHeight()}.
374 * </p>
375 *
376 * <p>
377 * To measure its dimensions, a view takes into account its padding. The padding
378 * is expressed in pixels for the left, top, right and bottom parts of the view.
379 * Padding can be used to offset the content of the view by a specific amount of
380 * pixels. For instance, a left padding of 2 will push the view's content by
381 * 2 pixels to the right of the left edge. Padding can be set using the
382 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
383 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
384 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
385 * {@link #getPaddingEnd()}.
386 * </p>
387 *
388 * <p>
389 * Even though a view can define a padding, it does not provide any support for
390 * margins. However, view groups provide such a support. Refer to
391 * {@link android.view.ViewGroup} and
392 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
393 * </p>
394 *
395 * <a name="Layout"></a>
396 * <h3>Layout</h3>
397 * <p>
398 * Layout is a two pass process: a measure pass and a layout pass. The measuring
399 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
400 * of the view tree. Each view pushes dimension specifications down the tree
401 * during the recursion. At the end of the measure pass, every view has stored
402 * its measurements. The second pass happens in
403 * {@link #layout(int,int,int,int)} and is also top-down. During
404 * this pass each parent is responsible for positioning all of its children
405 * using the sizes computed in the measure pass.
406 * </p>
407 *
408 * <p>
409 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
410 * {@link #getMeasuredHeight()} values must be set, along with those for all of
411 * that view's descendants. A view's measured width and measured height values
412 * must respect the constraints imposed by the view's parents. This guarantees
413 * that at the end of the measure pass, all parents accept all of their
414 * children's measurements. A parent view may call measure() more than once on
415 * its children. For example, the parent may measure each child once with
416 * unspecified dimensions to find out how big they want to be, then call
417 * measure() on them again with actual numbers if the sum of all the children's
418 * unconstrained sizes is too big or too small.
419 * </p>
420 *
421 * <p>
422 * The measure pass uses two classes to communicate dimensions. The
423 * {@link MeasureSpec} class is used by views to tell their parents how they
424 * want to be measured and positioned. The base LayoutParams class just
425 * describes how big the view wants to be for both width and height. For each
426 * dimension, it can specify one of:
427 * <ul>
428 * <li> an exact number
429 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
430 * (minus padding)
431 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
432 * enclose its content (plus padding).
433 * </ul>
434 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
435 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
436 * an X and Y value.
437 * </p>
438 *
439 * <p>
440 * MeasureSpecs are used to push requirements down the tree from parent to
441 * child. A MeasureSpec can be in one of three modes:
442 * <ul>
443 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
444 * of a child view. For example, a LinearLayout may call measure() on its child
445 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
446 * tall the child view wants to be given a width of 240 pixels.
447 * <li>EXACTLY: This is used by the parent to impose an exact size on the
448 * child. The child must use this size, and guarantee that all of its
449 * descendants will fit within this size.
450 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
451 * child. The child must guarantee that it and all of its descendants will fit
452 * within this size.
453 * </ul>
454 * </p>
455 *
456 * <p>
457 * To initiate a layout, call {@link #requestLayout}. This method is typically
458 * called by a view on itself when it believes that is can no longer fit within
459 * its current bounds.
460 * </p>
461 *
462 * <a name="Drawing"></a>
463 * <h3>Drawing</h3>
464 * <p>
465 * Drawing is handled by walking the tree and recording the drawing commands of
466 * any View that needs to update. After this, the drawing commands of the
467 * entire tree are issued to screen, clipped to the newly damaged area.
468 * </p>
469 *
470 * <p>
471 * The tree is largely recorded and drawn in order, with parents drawn before
472 * (i.e., behind) their children, with siblings drawn in the order they appear
473 * in the tree. If you set a background drawable for a View, then the View will
474 * draw it before calling back to its <code>onDraw()</code> method. The child
475 * drawing order can be overridden with
476 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
477 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
478 * </p>
479 *
480 * <p>
481 * To force a view to draw, call {@link #invalidate()}.
482 * </p>
483 *
484 * <a name="EventHandlingThreading"></a>
485 * <h3>Event Handling and Threading</h3>
486 * <p>
487 * The basic cycle of a view is as follows:
488 * <ol>
489 * <li>An event comes in and is dispatched to the appropriate view. The view
490 * handles the event and notifies any listeners.</li>
491 * <li>If in the course of processing the event, the view's bounds may need
492 * to be changed, the view will call {@link #requestLayout()}.</li>
493 * <li>Similarly, if in the course of processing the event the view's appearance
494 * may need to be changed, the view will call {@link #invalidate()}.</li>
495 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
496 * the framework will take care of measuring, laying out, and drawing the tree
497 * as appropriate.</li>
498 * </ol>
499 * </p>
500 *
501 * <p><em>Note: The entire view tree is single threaded. You must always be on
502 * the UI thread when calling any method on any view.</em>
503 * If you are doing work on other threads and want to update the state of a view
504 * from that thread, you should use a {@link Handler}.
505 * </p>
506 *
507 * <a name="FocusHandling"></a>
508 * <h3>Focus Handling</h3>
509 * <p>
510 * The framework will handle routine focus movement in response to user input.
511 * This includes changing the focus as views are removed or hidden, or as new
512 * views become available. Views indicate their willingness to take focus
513 * through the {@link #isFocusable} method. To change whether a view can take
514 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
515 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
516 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
517 * </p>
518 * <p>
519 * Focus movement is based on an algorithm which finds the nearest neighbor in a
520 * given direction. In rare cases, the default algorithm may not match the
521 * intended behavior of the developer. In these situations, you can provide
522 * explicit overrides by using these XML attributes in the layout file:
523 * <pre>
524 * nextFocusDown
525 * nextFocusLeft
526 * nextFocusRight
527 * nextFocusUp
528 * </pre>
529 * </p>
530 *
531 *
532 * <p>
533 * To get a particular view to take focus, call {@link #requestFocus()}.
534 * </p>
535 *
536 * <a name="TouchMode"></a>
537 * <h3>Touch Mode</h3>
538 * <p>
539 * When a user is navigating a user interface via directional keys such as a D-pad, it is
540 * necessary to give focus to actionable items such as buttons so the user can see
541 * what will take input.  If the device has touch capabilities, however, and the user
542 * begins interacting with the interface by touching it, it is no longer necessary to
543 * always highlight, or give focus to, a particular view.  This motivates a mode
544 * for interaction named 'touch mode'.
545 * </p>
546 * <p>
547 * For a touch capable device, once the user touches the screen, the device
548 * will enter touch mode.  From this point onward, only views for which
549 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
550 * Other views that are touchable, like buttons, will not take focus when touched; they will
551 * only fire the on click listeners.
552 * </p>
553 * <p>
554 * Any time a user hits a directional key, such as a D-pad direction, the view device will
555 * exit touch mode, and find a view to take focus, so that the user may resume interacting
556 * with the user interface without touching the screen again.
557 * </p>
558 * <p>
559 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
560 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
561 * </p>
562 *
563 * <a name="Scrolling"></a>
564 * <h3>Scrolling</h3>
565 * <p>
566 * The framework provides basic support for views that wish to internally
567 * scroll their content. This includes keeping track of the X and Y scroll
568 * offset as well as mechanisms for drawing scrollbars. See
569 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
570 * {@link #awakenScrollBars()} for more details.
571 * </p>
572 *
573 * <a name="Tags"></a>
574 * <h3>Tags</h3>
575 * <p>
576 * Unlike IDs, tags are not used to identify views. Tags are essentially an
577 * extra piece of information that can be associated with a view. They are most
578 * often used as a convenience to store data related to views in the views
579 * themselves rather than by putting them in a separate structure.
580 * </p>
581 * <p>
582 * Tags may be specified with character sequence values in layout XML as either
583 * a single tag using the {@link android.R.styleable#View_tag android:tag}
584 * attribute or multiple tags using the {@code <tag>} child element:
585 * <pre>
586 *     &ltView ...
587 *           android:tag="@string/mytag_value" /&gt;
588 *     &ltView ...&gt;
589 *         &lttag android:id="@+id/mytag"
590 *              android:value="@string/mytag_value" /&gt;
591 *     &lt/View>
592 * </pre>
593 * </p>
594 * <p>
595 * Tags may also be specified with arbitrary objects from code using
596 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
597 * </p>
598 *
599 * <a name="Themes"></a>
600 * <h3>Themes</h3>
601 * <p>
602 * By default, Views are created using the theme of the Context object supplied
603 * to their constructor; however, a different theme may be specified by using
604 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
605 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
606 * code.
607 * </p>
608 * <p>
609 * When the {@link android.R.styleable#View_theme android:theme} attribute is
610 * used in XML, the specified theme is applied on top of the inflation
611 * context's theme (see {@link LayoutInflater}) and used for the view itself as
612 * well as any child elements.
613 * </p>
614 * <p>
615 * In the following example, both views will be created using the Material dark
616 * color scheme; however, because an overlay theme is used which only defines a
617 * subset of attributes, the value of
618 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
619 * the inflation context's theme (e.g. the Activity theme) will be preserved.
620 * <pre>
621 *     &ltLinearLayout
622 *             ...
623 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
624 *         &ltView ...&gt;
625 *     &lt/LinearLayout&gt;
626 * </pre>
627 * </p>
628 *
629 * <a name="Properties"></a>
630 * <h3>Properties</h3>
631 * <p>
632 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
633 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
634 * available both in the {@link Property} form as well as in similarly-named setter/getter
635 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
636 * be used to set persistent state associated with these rendering-related properties on the view.
637 * The properties and methods can also be used in conjunction with
638 * {@link android.animation.Animator Animator}-based animations, described more in the
639 * <a href="#Animation">Animation</a> section.
640 * </p>
641 *
642 * <a name="Animation"></a>
643 * <h3>Animation</h3>
644 * <p>
645 * Starting with Android 3.0, the preferred way of animating views is to use the
646 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
647 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
648 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
649 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
650 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
651 * makes animating these View properties particularly easy and efficient.
652 * </p>
653 * <p>
654 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
655 * You can attach an {@link Animation} object to a view using
656 * {@link #setAnimation(Animation)} or
657 * {@link #startAnimation(Animation)}. The animation can alter the scale,
658 * rotation, translation and alpha of a view over time. If the animation is
659 * attached to a view that has children, the animation will affect the entire
660 * subtree rooted by that node. When an animation is started, the framework will
661 * take care of redrawing the appropriate views until the animation completes.
662 * </p>
663 *
664 * <a name="Security"></a>
665 * <h3>Security</h3>
666 * <p>
667 * Sometimes it is essential that an application be able to verify that an action
668 * is being performed with the full knowledge and consent of the user, such as
669 * granting a permission request, making a purchase or clicking on an advertisement.
670 * Unfortunately, a malicious application could try to spoof the user into
671 * performing these actions, unaware, by concealing the intended purpose of the view.
672 * As a remedy, the framework offers a touch filtering mechanism that can be used to
673 * improve the security of views that provide access to sensitive functionality.
674 * </p><p>
675 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
676 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
677 * will discard touches that are received whenever the view's window is obscured by
678 * another visible window.  As a result, the view will not receive touches whenever a
679 * toast, dialog or other window appears above the view's window.
680 * </p><p>
681 * For more fine-grained control over security, consider overriding the
682 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
683 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
684 * </p>
685 *
686 * @attr ref android.R.styleable#View_alpha
687 * @attr ref android.R.styleable#View_background
688 * @attr ref android.R.styleable#View_clickable
689 * @attr ref android.R.styleable#View_contentDescription
690 * @attr ref android.R.styleable#View_drawingCacheQuality
691 * @attr ref android.R.styleable#View_duplicateParentState
692 * @attr ref android.R.styleable#View_id
693 * @attr ref android.R.styleable#View_requiresFadingEdge
694 * @attr ref android.R.styleable#View_fadeScrollbars
695 * @attr ref android.R.styleable#View_fadingEdgeLength
696 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
697 * @attr ref android.R.styleable#View_fitsSystemWindows
698 * @attr ref android.R.styleable#View_isScrollContainer
699 * @attr ref android.R.styleable#View_focusable
700 * @attr ref android.R.styleable#View_focusableInTouchMode
701 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
702 * @attr ref android.R.styleable#View_keepScreenOn
703 * @attr ref android.R.styleable#View_layerType
704 * @attr ref android.R.styleable#View_layoutDirection
705 * @attr ref android.R.styleable#View_longClickable
706 * @attr ref android.R.styleable#View_minHeight
707 * @attr ref android.R.styleable#View_minWidth
708 * @attr ref android.R.styleable#View_nextFocusDown
709 * @attr ref android.R.styleable#View_nextFocusLeft
710 * @attr ref android.R.styleable#View_nextFocusRight
711 * @attr ref android.R.styleable#View_nextFocusUp
712 * @attr ref android.R.styleable#View_onClick
713 * @attr ref android.R.styleable#View_padding
714 * @attr ref android.R.styleable#View_paddingBottom
715 * @attr ref android.R.styleable#View_paddingLeft
716 * @attr ref android.R.styleable#View_paddingRight
717 * @attr ref android.R.styleable#View_paddingTop
718 * @attr ref android.R.styleable#View_paddingStart
719 * @attr ref android.R.styleable#View_paddingEnd
720 * @attr ref android.R.styleable#View_saveEnabled
721 * @attr ref android.R.styleable#View_rotation
722 * @attr ref android.R.styleable#View_rotationX
723 * @attr ref android.R.styleable#View_rotationY
724 * @attr ref android.R.styleable#View_scaleX
725 * @attr ref android.R.styleable#View_scaleY
726 * @attr ref android.R.styleable#View_scrollX
727 * @attr ref android.R.styleable#View_scrollY
728 * @attr ref android.R.styleable#View_scrollbarSize
729 * @attr ref android.R.styleable#View_scrollbarStyle
730 * @attr ref android.R.styleable#View_scrollbars
731 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
732 * @attr ref android.R.styleable#View_scrollbarFadeDuration
733 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
734 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
735 * @attr ref android.R.styleable#View_scrollbarThumbVertical
736 * @attr ref android.R.styleable#View_scrollbarTrackVertical
737 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
738 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
739 * @attr ref android.R.styleable#View_stateListAnimator
740 * @attr ref android.R.styleable#View_transitionName
741 * @attr ref android.R.styleable#View_soundEffectsEnabled
742 * @attr ref android.R.styleable#View_tag
743 * @attr ref android.R.styleable#View_textAlignment
744 * @attr ref android.R.styleable#View_textDirection
745 * @attr ref android.R.styleable#View_transformPivotX
746 * @attr ref android.R.styleable#View_transformPivotY
747 * @attr ref android.R.styleable#View_translationX
748 * @attr ref android.R.styleable#View_translationY
749 * @attr ref android.R.styleable#View_translationZ
750 * @attr ref android.R.styleable#View_visibility
751 * @attr ref android.R.styleable#View_theme
752 *
753 * @see android.view.ViewGroup
754 */
755@UiThread
756public class View implements Drawable.Callback, KeyEvent.Callback,
757        AccessibilityEventSource {
758    private static final boolean DBG = false;
759
760    /**
761     * The logging tag used by this class with android.util.Log.
762     */
763    protected static final String VIEW_LOG_TAG = "View";
764
765    /**
766     * When set to true, apps will draw debugging information about their layouts.
767     *
768     * @hide
769     */
770    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
771
772    /**
773     * When set to true, this view will save its attribute data.
774     *
775     * @hide
776     */
777    public static boolean mDebugViewAttributes = false;
778
779    /**
780     * Used to mark a View that has no ID.
781     */
782    public static final int NO_ID = -1;
783
784    /**
785     * Signals that compatibility booleans have been initialized according to
786     * target SDK versions.
787     */
788    private static boolean sCompatibilityDone = false;
789
790    /**
791     * Use the old (broken) way of building MeasureSpecs.
792     */
793    private static boolean sUseBrokenMakeMeasureSpec = false;
794
795    /**
796     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
797     */
798    static boolean sUseZeroUnspecifiedMeasureSpec = false;
799
800    /**
801     * Ignore any optimizations using the measure cache.
802     */
803    private static boolean sIgnoreMeasureCache = false;
804
805    /**
806     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
807     */
808    private static boolean sAlwaysRemeasureExactly = false;
809
810    /**
811     * Relax constraints around whether setLayoutParams() must be called after
812     * modifying the layout params.
813     */
814    private static boolean sLayoutParamsAlwaysChanged = false;
815
816    /**
817     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
818     * without throwing
819     */
820    static boolean sTextureViewIgnoresDrawableSetters = false;
821
822    /**
823     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
824     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
825     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
826     * check is implemented for backwards compatibility.
827     *
828     * {@hide}
829     */
830    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
831
832    /**
833     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
834     * calling setFlags.
835     */
836    private static final int NOT_FOCUSABLE = 0x00000000;
837
838    /**
839     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
840     * setFlags.
841     */
842    private static final int FOCUSABLE = 0x00000001;
843
844    /**
845     * Mask for use with setFlags indicating bits used for focus.
846     */
847    private static final int FOCUSABLE_MASK = 0x00000001;
848
849    /**
850     * This view will adjust its padding to fit sytem windows (e.g. status bar)
851     */
852    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
853
854    /** @hide */
855    @IntDef({VISIBLE, INVISIBLE, GONE})
856    @Retention(RetentionPolicy.SOURCE)
857    public @interface Visibility {}
858
859    /**
860     * This view is visible.
861     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
862     * android:visibility}.
863     */
864    public static final int VISIBLE = 0x00000000;
865
866    /**
867     * This view is invisible, but it still takes up space for layout purposes.
868     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
869     * android:visibility}.
870     */
871    public static final int INVISIBLE = 0x00000004;
872
873    /**
874     * This view is invisible, and it doesn't take any space for layout
875     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
876     * android:visibility}.
877     */
878    public static final int GONE = 0x00000008;
879
880    /**
881     * Mask for use with setFlags indicating bits used for visibility.
882     * {@hide}
883     */
884    static final int VISIBILITY_MASK = 0x0000000C;
885
886    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
887
888    /**
889     * This view is enabled. Interpretation varies by subclass.
890     * Use with ENABLED_MASK when calling setFlags.
891     * {@hide}
892     */
893    static final int ENABLED = 0x00000000;
894
895    /**
896     * This view is disabled. Interpretation varies by subclass.
897     * Use with ENABLED_MASK when calling setFlags.
898     * {@hide}
899     */
900    static final int DISABLED = 0x00000020;
901
902   /**
903    * Mask for use with setFlags indicating bits used for indicating whether
904    * this view is enabled
905    * {@hide}
906    */
907    static final int ENABLED_MASK = 0x00000020;
908
909    /**
910     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
911     * called and further optimizations will be performed. It is okay to have
912     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
913     * {@hide}
914     */
915    static final int WILL_NOT_DRAW = 0x00000080;
916
917    /**
918     * Mask for use with setFlags indicating bits used for indicating whether
919     * this view is will draw
920     * {@hide}
921     */
922    static final int DRAW_MASK = 0x00000080;
923
924    /**
925     * <p>This view doesn't show scrollbars.</p>
926     * {@hide}
927     */
928    static final int SCROLLBARS_NONE = 0x00000000;
929
930    /**
931     * <p>This view shows horizontal scrollbars.</p>
932     * {@hide}
933     */
934    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
935
936    /**
937     * <p>This view shows vertical scrollbars.</p>
938     * {@hide}
939     */
940    static final int SCROLLBARS_VERTICAL = 0x00000200;
941
942    /**
943     * <p>Mask for use with setFlags indicating bits used for indicating which
944     * scrollbars are enabled.</p>
945     * {@hide}
946     */
947    static final int SCROLLBARS_MASK = 0x00000300;
948
949    /**
950     * Indicates that the view should filter touches when its window is obscured.
951     * Refer to the class comments for more information about this security feature.
952     * {@hide}
953     */
954    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
955
956    /**
957     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
958     * that they are optional and should be skipped if the window has
959     * requested system UI flags that ignore those insets for layout.
960     */
961    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
962
963    /**
964     * <p>This view doesn't show fading edges.</p>
965     * {@hide}
966     */
967    static final int FADING_EDGE_NONE = 0x00000000;
968
969    /**
970     * <p>This view shows horizontal fading edges.</p>
971     * {@hide}
972     */
973    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
974
975    /**
976     * <p>This view shows vertical fading edges.</p>
977     * {@hide}
978     */
979    static final int FADING_EDGE_VERTICAL = 0x00002000;
980
981    /**
982     * <p>Mask for use with setFlags indicating bits used for indicating which
983     * fading edges are enabled.</p>
984     * {@hide}
985     */
986    static final int FADING_EDGE_MASK = 0x00003000;
987
988    /**
989     * <p>Indicates this view can be clicked. When clickable, a View reacts
990     * to clicks by notifying the OnClickListener.<p>
991     * {@hide}
992     */
993    static final int CLICKABLE = 0x00004000;
994
995    /**
996     * <p>Indicates this view is caching its drawing into a bitmap.</p>
997     * {@hide}
998     */
999    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1000
1001    /**
1002     * <p>Indicates that no icicle should be saved for this view.<p>
1003     * {@hide}
1004     */
1005    static final int SAVE_DISABLED = 0x000010000;
1006
1007    /**
1008     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1009     * property.</p>
1010     * {@hide}
1011     */
1012    static final int SAVE_DISABLED_MASK = 0x000010000;
1013
1014    /**
1015     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1016     * {@hide}
1017     */
1018    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1019
1020    /**
1021     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1022     * {@hide}
1023     */
1024    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1025
1026    /** @hide */
1027    @Retention(RetentionPolicy.SOURCE)
1028    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1029    public @interface DrawingCacheQuality {}
1030
1031    /**
1032     * <p>Enables low quality mode for the drawing cache.</p>
1033     */
1034    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1035
1036    /**
1037     * <p>Enables high quality mode for the drawing cache.</p>
1038     */
1039    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1040
1041    /**
1042     * <p>Enables automatic quality mode for the drawing cache.</p>
1043     */
1044    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1045
1046    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1047            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1048    };
1049
1050    /**
1051     * <p>Mask for use with setFlags indicating bits used for the cache
1052     * quality property.</p>
1053     * {@hide}
1054     */
1055    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1056
1057    /**
1058     * <p>
1059     * Indicates this view can be long clicked. When long clickable, a View
1060     * reacts to long clicks by notifying the OnLongClickListener or showing a
1061     * context menu.
1062     * </p>
1063     * {@hide}
1064     */
1065    static final int LONG_CLICKABLE = 0x00200000;
1066
1067    /**
1068     * <p>Indicates that this view gets its drawable states from its direct parent
1069     * and ignores its original internal states.</p>
1070     *
1071     * @hide
1072     */
1073    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1074
1075    /**
1076     * <p>
1077     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1078     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1079     * OnContextClickListener.
1080     * </p>
1081     * {@hide}
1082     */
1083    static final int CONTEXT_CLICKABLE = 0x00800000;
1084
1085
1086    /** @hide */
1087    @IntDef({
1088        SCROLLBARS_INSIDE_OVERLAY,
1089        SCROLLBARS_INSIDE_INSET,
1090        SCROLLBARS_OUTSIDE_OVERLAY,
1091        SCROLLBARS_OUTSIDE_INSET
1092    })
1093    @Retention(RetentionPolicy.SOURCE)
1094    public @interface ScrollBarStyle {}
1095
1096    /**
1097     * The scrollbar style to display the scrollbars inside the content area,
1098     * without increasing the padding. The scrollbars will be overlaid with
1099     * translucency on the view's content.
1100     */
1101    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1102
1103    /**
1104     * The scrollbar style to display the scrollbars inside the padded area,
1105     * increasing the padding of the view. The scrollbars will not overlap the
1106     * content area of the view.
1107     */
1108    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1109
1110    /**
1111     * The scrollbar style to display the scrollbars at the edge of the view,
1112     * without increasing the padding. The scrollbars will be overlaid with
1113     * translucency.
1114     */
1115    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1116
1117    /**
1118     * The scrollbar style to display the scrollbars at the edge of the view,
1119     * increasing the padding of the view. The scrollbars will only overlap the
1120     * background, if any.
1121     */
1122    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1123
1124    /**
1125     * Mask to check if the scrollbar style is overlay or inset.
1126     * {@hide}
1127     */
1128    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1129
1130    /**
1131     * Mask to check if the scrollbar style is inside or outside.
1132     * {@hide}
1133     */
1134    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1135
1136    /**
1137     * Mask for scrollbar style.
1138     * {@hide}
1139     */
1140    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1141
1142    /**
1143     * View flag indicating that the screen should remain on while the
1144     * window containing this view is visible to the user.  This effectively
1145     * takes care of automatically setting the WindowManager's
1146     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1147     */
1148    public static final int KEEP_SCREEN_ON = 0x04000000;
1149
1150    /**
1151     * View flag indicating whether this view should have sound effects enabled
1152     * for events such as clicking and touching.
1153     */
1154    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1155
1156    /**
1157     * View flag indicating whether this view should have haptic feedback
1158     * enabled for events such as long presses.
1159     */
1160    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1161
1162    /**
1163     * <p>Indicates that the view hierarchy should stop saving state when
1164     * it reaches this view.  If state saving is initiated immediately at
1165     * the view, it will be allowed.
1166     * {@hide}
1167     */
1168    static final int PARENT_SAVE_DISABLED = 0x20000000;
1169
1170    /**
1171     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1172     * {@hide}
1173     */
1174    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1175
1176    /** @hide */
1177    @IntDef(flag = true,
1178            value = {
1179                FOCUSABLES_ALL,
1180                FOCUSABLES_TOUCH_MODE
1181            })
1182    @Retention(RetentionPolicy.SOURCE)
1183    public @interface FocusableMode {}
1184
1185    /**
1186     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1187     * should add all focusable Views regardless if they are focusable in touch mode.
1188     */
1189    public static final int FOCUSABLES_ALL = 0x00000000;
1190
1191    /**
1192     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1193     * should add only Views focusable in touch mode.
1194     */
1195    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1196
1197    /** @hide */
1198    @IntDef({
1199            FOCUS_BACKWARD,
1200            FOCUS_FORWARD,
1201            FOCUS_LEFT,
1202            FOCUS_UP,
1203            FOCUS_RIGHT,
1204            FOCUS_DOWN
1205    })
1206    @Retention(RetentionPolicy.SOURCE)
1207    public @interface FocusDirection {}
1208
1209    /** @hide */
1210    @IntDef({
1211            FOCUS_LEFT,
1212            FOCUS_UP,
1213            FOCUS_RIGHT,
1214            FOCUS_DOWN
1215    })
1216    @Retention(RetentionPolicy.SOURCE)
1217    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1218
1219    /**
1220     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1221     * item.
1222     */
1223    public static final int FOCUS_BACKWARD = 0x00000001;
1224
1225    /**
1226     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1227     * item.
1228     */
1229    public static final int FOCUS_FORWARD = 0x00000002;
1230
1231    /**
1232     * Use with {@link #focusSearch(int)}. Move focus to the left.
1233     */
1234    public static final int FOCUS_LEFT = 0x00000011;
1235
1236    /**
1237     * Use with {@link #focusSearch(int)}. Move focus up.
1238     */
1239    public static final int FOCUS_UP = 0x00000021;
1240
1241    /**
1242     * Use with {@link #focusSearch(int)}. Move focus to the right.
1243     */
1244    public static final int FOCUS_RIGHT = 0x00000042;
1245
1246    /**
1247     * Use with {@link #focusSearch(int)}. Move focus down.
1248     */
1249    public static final int FOCUS_DOWN = 0x00000082;
1250
1251    /**
1252     * Bits of {@link #getMeasuredWidthAndState()} and
1253     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1254     */
1255    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1256
1257    /**
1258     * Bits of {@link #getMeasuredWidthAndState()} and
1259     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1260     */
1261    public static final int MEASURED_STATE_MASK = 0xff000000;
1262
1263    /**
1264     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1265     * for functions that combine both width and height into a single int,
1266     * such as {@link #getMeasuredState()} and the childState argument of
1267     * {@link #resolveSizeAndState(int, int, int)}.
1268     */
1269    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1270
1271    /**
1272     * Bit of {@link #getMeasuredWidthAndState()} and
1273     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1274     * is smaller that the space the view would like to have.
1275     */
1276    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1277
1278    /**
1279     * Base View state sets
1280     */
1281    // Singles
1282    /**
1283     * Indicates the view has no states set. 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[] EMPTY_STATE_SET;
1291    /**
1292     * Indicates the view is enabled. 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[] ENABLED_STATE_SET;
1300    /**
1301     * Indicates the view is focused. 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[] FOCUSED_STATE_SET;
1309    /**
1310     * Indicates the view is selected. 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[] SELECTED_STATE_SET;
1318    /**
1319     * Indicates the view is pressed. 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[] PRESSED_STATE_SET;
1327    /**
1328     * Indicates the view's window has focus. States are used with
1329     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1330     * view depending on its state.
1331     *
1332     * @see android.graphics.drawable.Drawable
1333     * @see #getDrawableState()
1334     */
1335    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1336    // Doubles
1337    /**
1338     * Indicates the view is enabled and has the focus.
1339     *
1340     * @see #ENABLED_STATE_SET
1341     * @see #FOCUSED_STATE_SET
1342     */
1343    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1344    /**
1345     * Indicates the view is enabled and selected.
1346     *
1347     * @see #ENABLED_STATE_SET
1348     * @see #SELECTED_STATE_SET
1349     */
1350    protected static final int[] ENABLED_SELECTED_STATE_SET;
1351    /**
1352     * Indicates the view is enabled and that its window has focus.
1353     *
1354     * @see #ENABLED_STATE_SET
1355     * @see #WINDOW_FOCUSED_STATE_SET
1356     */
1357    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1358    /**
1359     * Indicates the view is focused and selected.
1360     *
1361     * @see #FOCUSED_STATE_SET
1362     * @see #SELECTED_STATE_SET
1363     */
1364    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1365    /**
1366     * Indicates the view has the focus and that its window has the focus.
1367     *
1368     * @see #FOCUSED_STATE_SET
1369     * @see #WINDOW_FOCUSED_STATE_SET
1370     */
1371    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1372    /**
1373     * Indicates the view is selected and that its window has the focus.
1374     *
1375     * @see #SELECTED_STATE_SET
1376     * @see #WINDOW_FOCUSED_STATE_SET
1377     */
1378    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1379    // Triples
1380    /**
1381     * Indicates the view is enabled, focused and selected.
1382     *
1383     * @see #ENABLED_STATE_SET
1384     * @see #FOCUSED_STATE_SET
1385     * @see #SELECTED_STATE_SET
1386     */
1387    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1388    /**
1389     * Indicates the view is enabled, focused and its window has the focus.
1390     *
1391     * @see #ENABLED_STATE_SET
1392     * @see #FOCUSED_STATE_SET
1393     * @see #WINDOW_FOCUSED_STATE_SET
1394     */
1395    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1396    /**
1397     * Indicates the view is enabled, selected and its window has the focus.
1398     *
1399     * @see #ENABLED_STATE_SET
1400     * @see #SELECTED_STATE_SET
1401     * @see #WINDOW_FOCUSED_STATE_SET
1402     */
1403    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1404    /**
1405     * Indicates the view is focused, selected and its window has the focus.
1406     *
1407     * @see #FOCUSED_STATE_SET
1408     * @see #SELECTED_STATE_SET
1409     * @see #WINDOW_FOCUSED_STATE_SET
1410     */
1411    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1412    /**
1413     * Indicates the view is enabled, focused, selected and its window
1414     * has the focus.
1415     *
1416     * @see #ENABLED_STATE_SET
1417     * @see #FOCUSED_STATE_SET
1418     * @see #SELECTED_STATE_SET
1419     * @see #WINDOW_FOCUSED_STATE_SET
1420     */
1421    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1422    /**
1423     * Indicates the view is pressed and its window has the focus.
1424     *
1425     * @see #PRESSED_STATE_SET
1426     * @see #WINDOW_FOCUSED_STATE_SET
1427     */
1428    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1429    /**
1430     * Indicates the view is pressed and selected.
1431     *
1432     * @see #PRESSED_STATE_SET
1433     * @see #SELECTED_STATE_SET
1434     */
1435    protected static final int[] PRESSED_SELECTED_STATE_SET;
1436    /**
1437     * Indicates the view is pressed, selected and its window has the focus.
1438     *
1439     * @see #PRESSED_STATE_SET
1440     * @see #SELECTED_STATE_SET
1441     * @see #WINDOW_FOCUSED_STATE_SET
1442     */
1443    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1444    /**
1445     * Indicates the view is pressed and focused.
1446     *
1447     * @see #PRESSED_STATE_SET
1448     * @see #FOCUSED_STATE_SET
1449     */
1450    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1451    /**
1452     * Indicates the view is pressed, focused and its window has the focus.
1453     *
1454     * @see #PRESSED_STATE_SET
1455     * @see #FOCUSED_STATE_SET
1456     * @see #WINDOW_FOCUSED_STATE_SET
1457     */
1458    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1459    /**
1460     * Indicates the view is pressed, focused and selected.
1461     *
1462     * @see #PRESSED_STATE_SET
1463     * @see #SELECTED_STATE_SET
1464     * @see #FOCUSED_STATE_SET
1465     */
1466    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1467    /**
1468     * Indicates the view is pressed, focused, selected and its window has the focus.
1469     *
1470     * @see #PRESSED_STATE_SET
1471     * @see #FOCUSED_STATE_SET
1472     * @see #SELECTED_STATE_SET
1473     * @see #WINDOW_FOCUSED_STATE_SET
1474     */
1475    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1476    /**
1477     * Indicates the view is pressed and enabled.
1478     *
1479     * @see #PRESSED_STATE_SET
1480     * @see #ENABLED_STATE_SET
1481     */
1482    protected static final int[] PRESSED_ENABLED_STATE_SET;
1483    /**
1484     * Indicates the view is pressed, enabled and its window has the focus.
1485     *
1486     * @see #PRESSED_STATE_SET
1487     * @see #ENABLED_STATE_SET
1488     * @see #WINDOW_FOCUSED_STATE_SET
1489     */
1490    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1491    /**
1492     * Indicates the view is pressed, enabled and selected.
1493     *
1494     * @see #PRESSED_STATE_SET
1495     * @see #ENABLED_STATE_SET
1496     * @see #SELECTED_STATE_SET
1497     */
1498    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1499    /**
1500     * Indicates the view is pressed, enabled, selected and its window has the
1501     * focus.
1502     *
1503     * @see #PRESSED_STATE_SET
1504     * @see #ENABLED_STATE_SET
1505     * @see #SELECTED_STATE_SET
1506     * @see #WINDOW_FOCUSED_STATE_SET
1507     */
1508    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1509    /**
1510     * Indicates the view is pressed, enabled and focused.
1511     *
1512     * @see #PRESSED_STATE_SET
1513     * @see #ENABLED_STATE_SET
1514     * @see #FOCUSED_STATE_SET
1515     */
1516    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1517    /**
1518     * Indicates the view is pressed, enabled, focused and its window has the
1519     * focus.
1520     *
1521     * @see #PRESSED_STATE_SET
1522     * @see #ENABLED_STATE_SET
1523     * @see #FOCUSED_STATE_SET
1524     * @see #WINDOW_FOCUSED_STATE_SET
1525     */
1526    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1527    /**
1528     * Indicates the view is pressed, enabled, focused and selected.
1529     *
1530     * @see #PRESSED_STATE_SET
1531     * @see #ENABLED_STATE_SET
1532     * @see #SELECTED_STATE_SET
1533     * @see #FOCUSED_STATE_SET
1534     */
1535    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1536    /**
1537     * Indicates the view is pressed, enabled, focused, selected and its window
1538     * has the focus.
1539     *
1540     * @see #PRESSED_STATE_SET
1541     * @see #ENABLED_STATE_SET
1542     * @see #SELECTED_STATE_SET
1543     * @see #FOCUSED_STATE_SET
1544     * @see #WINDOW_FOCUSED_STATE_SET
1545     */
1546    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1547
1548    static {
1549        EMPTY_STATE_SET = StateSet.get(0);
1550
1551        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1552
1553        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1554        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1555                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1556
1557        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1558        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1559                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1560        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1561                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1562        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1563                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1564                        | StateSet.VIEW_STATE_FOCUSED);
1565
1566        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1567        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1568                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1569        ENABLED_SELECTED_STATE_SET = StateSet.get(
1570                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1571        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1572                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1573                        | StateSet.VIEW_STATE_ENABLED);
1574        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1575                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1576        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1577                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1578                        | StateSet.VIEW_STATE_ENABLED);
1579        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1580                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1581                        | StateSet.VIEW_STATE_ENABLED);
1582        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1583                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1584                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1585
1586        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1587        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1588                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1589        PRESSED_SELECTED_STATE_SET = StateSet.get(
1590                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1591        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1592                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1593                        | StateSet.VIEW_STATE_PRESSED);
1594        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1595                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1596        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1597                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1598                        | StateSet.VIEW_STATE_PRESSED);
1599        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1600                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1601                        | StateSet.VIEW_STATE_PRESSED);
1602        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1603                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1604                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1605        PRESSED_ENABLED_STATE_SET = StateSet.get(
1606                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1607        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1608                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1609                        | StateSet.VIEW_STATE_PRESSED);
1610        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1611                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1612                        | StateSet.VIEW_STATE_PRESSED);
1613        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1614                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1615                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1616        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1617                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1618                        | StateSet.VIEW_STATE_PRESSED);
1619        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1620                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1621                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1622        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1623                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1624                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1625        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1626                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1627                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1628                        | StateSet.VIEW_STATE_PRESSED);
1629    }
1630
1631    /**
1632     * Accessibility event types that are dispatched for text population.
1633     */
1634    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1635            AccessibilityEvent.TYPE_VIEW_CLICKED
1636            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1637            | AccessibilityEvent.TYPE_VIEW_SELECTED
1638            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1639            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1640            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1641            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1642            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1643            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1644            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1645            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1646
1647    /**
1648     * Temporary Rect currently for use in setBackground().  This will probably
1649     * be extended in the future to hold our own class with more than just
1650     * a Rect. :)
1651     */
1652    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1653
1654    /**
1655     * Map used to store views' tags.
1656     */
1657    private SparseArray<Object> mKeyedTags;
1658
1659    /**
1660     * The next available accessibility id.
1661     */
1662    private static int sNextAccessibilityViewId;
1663
1664    /**
1665     * The animation currently associated with this view.
1666     * @hide
1667     */
1668    protected Animation mCurrentAnimation = null;
1669
1670    /**
1671     * Width as measured during measure pass.
1672     * {@hide}
1673     */
1674    @ViewDebug.ExportedProperty(category = "measurement")
1675    int mMeasuredWidth;
1676
1677    /**
1678     * Height as measured during measure pass.
1679     * {@hide}
1680     */
1681    @ViewDebug.ExportedProperty(category = "measurement")
1682    int mMeasuredHeight;
1683
1684    /**
1685     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1686     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1687     * its display list. This flag, used only when hw accelerated, allows us to clear the
1688     * flag while retaining this information until it's needed (at getDisplayList() time and
1689     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1690     *
1691     * {@hide}
1692     */
1693    boolean mRecreateDisplayList = false;
1694
1695    /**
1696     * The view's identifier.
1697     * {@hide}
1698     *
1699     * @see #setId(int)
1700     * @see #getId()
1701     */
1702    @IdRes
1703    @ViewDebug.ExportedProperty(resolveId = true)
1704    int mID = NO_ID;
1705
1706    /**
1707     * The stable ID of this view for accessibility purposes.
1708     */
1709    int mAccessibilityViewId = NO_ID;
1710
1711    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1712
1713    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1714
1715    /**
1716     * The view's tag.
1717     * {@hide}
1718     *
1719     * @see #setTag(Object)
1720     * @see #getTag()
1721     */
1722    protected Object mTag = null;
1723
1724    // for mPrivateFlags:
1725    /** {@hide} */
1726    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1727    /** {@hide} */
1728    static final int PFLAG_FOCUSED                     = 0x00000002;
1729    /** {@hide} */
1730    static final int PFLAG_SELECTED                    = 0x00000004;
1731    /** {@hide} */
1732    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1733    /** {@hide} */
1734    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1735    /** {@hide} */
1736    static final int PFLAG_DRAWN                       = 0x00000020;
1737    /**
1738     * When this flag is set, this view is running an animation on behalf of its
1739     * children and should therefore not cancel invalidate requests, even if they
1740     * lie outside of this view's bounds.
1741     *
1742     * {@hide}
1743     */
1744    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1745    /** {@hide} */
1746    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1747    /** {@hide} */
1748    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1749    /** {@hide} */
1750    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1751    /** {@hide} */
1752    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1753    /** {@hide} */
1754    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1755    /** {@hide} */
1756    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1757
1758    private static final int PFLAG_PRESSED             = 0x00004000;
1759
1760    /** {@hide} */
1761    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1762    /**
1763     * Flag used to indicate that this view should be drawn once more (and only once
1764     * more) after its animation has completed.
1765     * {@hide}
1766     */
1767    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1768
1769    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1770
1771    /**
1772     * Indicates that the View returned true when onSetAlpha() was called and that
1773     * the alpha must be restored.
1774     * {@hide}
1775     */
1776    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1777
1778    /**
1779     * Set by {@link #setScrollContainer(boolean)}.
1780     */
1781    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1782
1783    /**
1784     * Set by {@link #setScrollContainer(boolean)}.
1785     */
1786    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1787
1788    /**
1789     * View flag indicating whether this view was invalidated (fully or partially.)
1790     *
1791     * @hide
1792     */
1793    static final int PFLAG_DIRTY                       = 0x00200000;
1794
1795    /**
1796     * View flag indicating whether this view was invalidated by an opaque
1797     * invalidate request.
1798     *
1799     * @hide
1800     */
1801    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1802
1803    /**
1804     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1805     *
1806     * @hide
1807     */
1808    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1809
1810    /**
1811     * Indicates whether the background is opaque.
1812     *
1813     * @hide
1814     */
1815    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1816
1817    /**
1818     * Indicates whether the scrollbars are opaque.
1819     *
1820     * @hide
1821     */
1822    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1823
1824    /**
1825     * Indicates whether the view is opaque.
1826     *
1827     * @hide
1828     */
1829    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1830
1831    /**
1832     * Indicates a prepressed state;
1833     * the short time between ACTION_DOWN and recognizing
1834     * a 'real' press. Prepressed is used to recognize quick taps
1835     * even when they are shorter than ViewConfiguration.getTapTimeout().
1836     *
1837     * @hide
1838     */
1839    private static final int PFLAG_PREPRESSED          = 0x02000000;
1840
1841    /**
1842     * Indicates whether the view is temporarily detached.
1843     *
1844     * @hide
1845     */
1846    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1847
1848    /**
1849     * Indicates that we should awaken scroll bars once attached
1850     *
1851     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1852     * during window attachment and it is no longer needed. Feel free to repurpose it.
1853     *
1854     * @hide
1855     */
1856    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1857
1858    /**
1859     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1860     * @hide
1861     */
1862    private static final int PFLAG_HOVERED             = 0x10000000;
1863
1864    /**
1865     * no longer needed, should be reused
1866     */
1867    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1868
1869    /** {@hide} */
1870    static final int PFLAG_ACTIVATED                   = 0x40000000;
1871
1872    /**
1873     * Indicates that this view was specifically invalidated, not just dirtied because some
1874     * child view was invalidated. The flag is used to determine when we need to recreate
1875     * a view's display list (as opposed to just returning a reference to its existing
1876     * display list).
1877     *
1878     * @hide
1879     */
1880    static final int PFLAG_INVALIDATED                 = 0x80000000;
1881
1882    /**
1883     * Masks for mPrivateFlags2, as generated by dumpFlags():
1884     *
1885     * |-------|-------|-------|-------|
1886     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1887     *                                1  PFLAG2_DRAG_HOVERED
1888     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1889     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1890     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1891     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1892     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1893     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1894     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1895     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1896     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1897     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1898     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1899     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1900     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1901     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1902     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1903     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1904     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1905     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1906     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1907     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1908     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1909     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1910     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1911     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1912     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1913     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1914     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1915     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1916     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1917     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1918     *    1                              PFLAG2_PADDING_RESOLVED
1919     *   1                               PFLAG2_DRAWABLE_RESOLVED
1920     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1921     * |-------|-------|-------|-------|
1922     */
1923
1924    /**
1925     * Indicates that this view has reported that it can accept the current drag's content.
1926     * Cleared when the drag operation concludes.
1927     * @hide
1928     */
1929    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1930
1931    /**
1932     * Indicates that this view is currently directly under the drag location in a
1933     * drag-and-drop operation involving content that it can accept.  Cleared when
1934     * the drag exits the view, or when the drag operation concludes.
1935     * @hide
1936     */
1937    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1938
1939    /** @hide */
1940    @IntDef({
1941        LAYOUT_DIRECTION_LTR,
1942        LAYOUT_DIRECTION_RTL,
1943        LAYOUT_DIRECTION_INHERIT,
1944        LAYOUT_DIRECTION_LOCALE
1945    })
1946    @Retention(RetentionPolicy.SOURCE)
1947    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1948    public @interface LayoutDir {}
1949
1950    /** @hide */
1951    @IntDef({
1952        LAYOUT_DIRECTION_LTR,
1953        LAYOUT_DIRECTION_RTL
1954    })
1955    @Retention(RetentionPolicy.SOURCE)
1956    public @interface ResolvedLayoutDir {}
1957
1958    /**
1959     * A flag to indicate that the layout direction of this view has not been defined yet.
1960     * @hide
1961     */
1962    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1963
1964    /**
1965     * Horizontal layout direction of this view is from Left to Right.
1966     * Use with {@link #setLayoutDirection}.
1967     */
1968    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1969
1970    /**
1971     * Horizontal layout direction of this view is from Right to Left.
1972     * Use with {@link #setLayoutDirection}.
1973     */
1974    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1975
1976    /**
1977     * Horizontal layout direction of this view is inherited from its parent.
1978     * Use with {@link #setLayoutDirection}.
1979     */
1980    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1981
1982    /**
1983     * Horizontal layout direction of this view is from deduced from the default language
1984     * script for the locale. Use with {@link #setLayoutDirection}.
1985     */
1986    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1987
1988    /**
1989     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1990     * @hide
1991     */
1992    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1993
1994    /**
1995     * Mask for use with private flags indicating bits used for horizontal layout direction.
1996     * @hide
1997     */
1998    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1999
2000    /**
2001     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2002     * right-to-left direction.
2003     * @hide
2004     */
2005    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2006
2007    /**
2008     * Indicates whether the view horizontal layout direction has been resolved.
2009     * @hide
2010     */
2011    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2012
2013    /**
2014     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2015     * @hide
2016     */
2017    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2018            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2019
2020    /*
2021     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2022     * flag value.
2023     * @hide
2024     */
2025    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2026            LAYOUT_DIRECTION_LTR,
2027            LAYOUT_DIRECTION_RTL,
2028            LAYOUT_DIRECTION_INHERIT,
2029            LAYOUT_DIRECTION_LOCALE
2030    };
2031
2032    /**
2033     * Default horizontal layout direction.
2034     */
2035    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2036
2037    /**
2038     * Default horizontal layout direction.
2039     * @hide
2040     */
2041    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2042
2043    /**
2044     * Text direction is inherited through {@link ViewGroup}
2045     */
2046    public static final int TEXT_DIRECTION_INHERIT = 0;
2047
2048    /**
2049     * Text direction is using "first strong algorithm". The first strong directional character
2050     * determines the paragraph direction. If there is no strong directional character, the
2051     * paragraph direction is the view's resolved layout direction.
2052     */
2053    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2054
2055    /**
2056     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2057     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2058     * If there are neither, the paragraph direction is the view's resolved layout direction.
2059     */
2060    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2061
2062    /**
2063     * Text direction is forced to LTR.
2064     */
2065    public static final int TEXT_DIRECTION_LTR = 3;
2066
2067    /**
2068     * Text direction is forced to RTL.
2069     */
2070    public static final int TEXT_DIRECTION_RTL = 4;
2071
2072    /**
2073     * Text direction is coming from the system Locale.
2074     */
2075    public static final int TEXT_DIRECTION_LOCALE = 5;
2076
2077    /**
2078     * Text direction is using "first strong algorithm". The first strong directional character
2079     * determines the paragraph direction. If there is no strong directional character, the
2080     * paragraph direction is LTR.
2081     */
2082    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2083
2084    /**
2085     * Text direction is using "first strong algorithm". The first strong directional character
2086     * determines the paragraph direction. If there is no strong directional character, the
2087     * paragraph direction is RTL.
2088     */
2089    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2090
2091    /**
2092     * Default text direction is inherited
2093     */
2094    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2095
2096    /**
2097     * Default resolved text direction
2098     * @hide
2099     */
2100    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2101
2102    /**
2103     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2104     * @hide
2105     */
2106    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2107
2108    /**
2109     * Mask for use with private flags indicating bits used for text direction.
2110     * @hide
2111     */
2112    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2113            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2114
2115    /**
2116     * Array of text direction flags for mapping attribute "textDirection" to correct
2117     * flag value.
2118     * @hide
2119     */
2120    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2121            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2122            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2123            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2124            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2125            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2126            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2127            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2128            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2129    };
2130
2131    /**
2132     * Indicates whether the view text direction has been resolved.
2133     * @hide
2134     */
2135    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2136            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2137
2138    /**
2139     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2140     * @hide
2141     */
2142    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2143
2144    /**
2145     * Mask for use with private flags indicating bits used for resolved text direction.
2146     * @hide
2147     */
2148    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2149            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2150
2151    /**
2152     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2153     * @hide
2154     */
2155    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2156            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2157
2158    /** @hide */
2159    @IntDef({
2160        TEXT_ALIGNMENT_INHERIT,
2161        TEXT_ALIGNMENT_GRAVITY,
2162        TEXT_ALIGNMENT_CENTER,
2163        TEXT_ALIGNMENT_TEXT_START,
2164        TEXT_ALIGNMENT_TEXT_END,
2165        TEXT_ALIGNMENT_VIEW_START,
2166        TEXT_ALIGNMENT_VIEW_END
2167    })
2168    @Retention(RetentionPolicy.SOURCE)
2169    public @interface TextAlignment {}
2170
2171    /**
2172     * Default text alignment. The text alignment of this View is inherited from its parent.
2173     * Use with {@link #setTextAlignment(int)}
2174     */
2175    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2176
2177    /**
2178     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2179     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2180     *
2181     * Use with {@link #setTextAlignment(int)}
2182     */
2183    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2184
2185    /**
2186     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2187     *
2188     * Use with {@link #setTextAlignment(int)}
2189     */
2190    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2191
2192    /**
2193     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2194     *
2195     * Use with {@link #setTextAlignment(int)}
2196     */
2197    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2198
2199    /**
2200     * Center the paragraph, e.g. ALIGN_CENTER.
2201     *
2202     * Use with {@link #setTextAlignment(int)}
2203     */
2204    public static final int TEXT_ALIGNMENT_CENTER = 4;
2205
2206    /**
2207     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2208     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2209     *
2210     * Use with {@link #setTextAlignment(int)}
2211     */
2212    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2213
2214    /**
2215     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2216     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2217     *
2218     * Use with {@link #setTextAlignment(int)}
2219     */
2220    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2221
2222    /**
2223     * Default text alignment is inherited
2224     */
2225    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2226
2227    /**
2228     * Default resolved text alignment
2229     * @hide
2230     */
2231    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2232
2233    /**
2234      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2235      * @hide
2236      */
2237    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2238
2239    /**
2240      * Mask for use with private flags indicating bits used for text alignment.
2241      * @hide
2242      */
2243    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2244
2245    /**
2246     * Array of text direction flags for mapping attribute "textAlignment" to correct
2247     * flag value.
2248     * @hide
2249     */
2250    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2251            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2252            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2253            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2254            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2255            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2256            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2257            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2258    };
2259
2260    /**
2261     * Indicates whether the view text alignment has been resolved.
2262     * @hide
2263     */
2264    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2265
2266    /**
2267     * Bit shift to get the resolved text alignment.
2268     * @hide
2269     */
2270    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2271
2272    /**
2273     * Mask for use with private flags indicating bits used for text alignment.
2274     * @hide
2275     */
2276    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2277            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2278
2279    /**
2280     * Indicates whether if the view text alignment has been resolved to gravity
2281     */
2282    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2283            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2284
2285    // Accessiblity constants for mPrivateFlags2
2286
2287    /**
2288     * Shift for the bits in {@link #mPrivateFlags2} related to the
2289     * "importantForAccessibility" attribute.
2290     */
2291    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2292
2293    /**
2294     * Automatically determine whether a view is important for accessibility.
2295     */
2296    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2297
2298    /**
2299     * The view is important for accessibility.
2300     */
2301    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2302
2303    /**
2304     * The view is not important for accessibility.
2305     */
2306    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2307
2308    /**
2309     * The view is not important for accessibility, nor are any of its
2310     * descendant views.
2311     */
2312    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2313
2314    /**
2315     * The default whether the view is important for accessibility.
2316     */
2317    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2318
2319    /**
2320     * Mask for obtainig the bits which specify how to determine
2321     * whether a view is important for accessibility.
2322     */
2323    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2324        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2325        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2326        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2327
2328    /**
2329     * Shift for the bits in {@link #mPrivateFlags2} related to the
2330     * "accessibilityLiveRegion" attribute.
2331     */
2332    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2333
2334    /**
2335     * Live region mode specifying that accessibility services should not
2336     * automatically announce changes to this view. This is the default live
2337     * region mode for most views.
2338     * <p>
2339     * Use with {@link #setAccessibilityLiveRegion(int)}.
2340     */
2341    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2342
2343    /**
2344     * Live region mode specifying that accessibility services should announce
2345     * changes to this view.
2346     * <p>
2347     * Use with {@link #setAccessibilityLiveRegion(int)}.
2348     */
2349    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2350
2351    /**
2352     * Live region mode specifying that accessibility services should interrupt
2353     * ongoing speech to immediately announce changes to this view.
2354     * <p>
2355     * Use with {@link #setAccessibilityLiveRegion(int)}.
2356     */
2357    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2358
2359    /**
2360     * The default whether the view is important for accessibility.
2361     */
2362    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2363
2364    /**
2365     * Mask for obtaining the bits which specify a view's accessibility live
2366     * region mode.
2367     */
2368    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2369            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2370            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2371
2372    /**
2373     * Flag indicating whether a view has accessibility focus.
2374     */
2375    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2376
2377    /**
2378     * Flag whether the accessibility state of the subtree rooted at this view changed.
2379     */
2380    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2381
2382    /**
2383     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2384     * is used to check whether later changes to the view's transform should invalidate the
2385     * view to force the quickReject test to run again.
2386     */
2387    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2388
2389    /**
2390     * Flag indicating that start/end padding has been resolved into left/right padding
2391     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2392     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2393     * during measurement. In some special cases this is required such as when an adapter-based
2394     * view measures prospective children without attaching them to a window.
2395     */
2396    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2397
2398    /**
2399     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2400     */
2401    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2402
2403    /**
2404     * Indicates that the view is tracking some sort of transient state
2405     * that the app should not need to be aware of, but that the framework
2406     * should take special care to preserve.
2407     */
2408    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2409
2410    /**
2411     * Group of bits indicating that RTL properties resolution is done.
2412     */
2413    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2414            PFLAG2_TEXT_DIRECTION_RESOLVED |
2415            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2416            PFLAG2_PADDING_RESOLVED |
2417            PFLAG2_DRAWABLE_RESOLVED;
2418
2419    // There are a couple of flags left in mPrivateFlags2
2420
2421    /* End of masks for mPrivateFlags2 */
2422
2423    /**
2424     * Masks for mPrivateFlags3, as generated by dumpFlags():
2425     *
2426     * |-------|-------|-------|-------|
2427     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2428     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2429     *                               1   PFLAG3_IS_LAID_OUT
2430     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2431     *                             1     PFLAG3_CALLED_SUPER
2432     *                            1      PFLAG3_APPLYING_INSETS
2433     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2434     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2435     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2436     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2437     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2438     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2439     *                     1             PFLAG3_SCROLL_INDICATOR_START
2440     *                    1              PFLAG3_SCROLL_INDICATOR_END
2441     *                   1               PFLAG3_ASSIST_BLOCKED
2442     *           xxxxxxxx                * NO LONGER NEEDED, SHOULD BE REUSED *
2443     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2444     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2445     *        1                          PFLAG3_TEMPORARY_DETACH
2446     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2447     * |-------|-------|-------|-------|
2448     */
2449
2450    /**
2451     * Flag indicating that view has a transform animation set on it. This is used to track whether
2452     * an animation is cleared between successive frames, in order to tell the associated
2453     * DisplayList to clear its animation matrix.
2454     */
2455    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2456
2457    /**
2458     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2459     * animation is cleared between successive frames, in order to tell the associated
2460     * DisplayList to restore its alpha value.
2461     */
2462    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2463
2464    /**
2465     * Flag indicating that the view has been through at least one layout since it
2466     * was last attached to a window.
2467     */
2468    static final int PFLAG3_IS_LAID_OUT = 0x4;
2469
2470    /**
2471     * Flag indicating that a call to measure() was skipped and should be done
2472     * instead when layout() is invoked.
2473     */
2474    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2475
2476    /**
2477     * Flag indicating that an overridden method correctly called down to
2478     * the superclass implementation as required by the API spec.
2479     */
2480    static final int PFLAG3_CALLED_SUPER = 0x10;
2481
2482    /**
2483     * Flag indicating that we're in the process of applying window insets.
2484     */
2485    static final int PFLAG3_APPLYING_INSETS = 0x20;
2486
2487    /**
2488     * Flag indicating that we're in the process of fitting system windows using the old method.
2489     */
2490    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2491
2492    /**
2493     * Flag indicating that nested scrolling is enabled for this view.
2494     * The view will optionally cooperate with views up its parent chain to allow for
2495     * integrated nested scrolling along the same axis.
2496     */
2497    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2498
2499    /**
2500     * Flag indicating that the bottom scroll indicator should be displayed
2501     * when this view can scroll up.
2502     */
2503    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2504
2505    /**
2506     * Flag indicating that the bottom scroll indicator should be displayed
2507     * when this view can scroll down.
2508     */
2509    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2510
2511    /**
2512     * Flag indicating that the left scroll indicator should be displayed
2513     * when this view can scroll left.
2514     */
2515    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2516
2517    /**
2518     * Flag indicating that the right scroll indicator should be displayed
2519     * when this view can scroll right.
2520     */
2521    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2522
2523    /**
2524     * Flag indicating that the start scroll indicator should be displayed
2525     * when this view can scroll in the start direction.
2526     */
2527    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2528
2529    /**
2530     * Flag indicating that the end scroll indicator should be displayed
2531     * when this view can scroll in the end direction.
2532     */
2533    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2534
2535    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2536
2537    static final int SCROLL_INDICATORS_NONE = 0x0000;
2538
2539    /**
2540     * Mask for use with setFlags indicating bits used for indicating which
2541     * scroll indicators are enabled.
2542     */
2543    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2544            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2545            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2546            | PFLAG3_SCROLL_INDICATOR_END;
2547
2548    /**
2549     * Left-shift required to translate between public scroll indicator flags
2550     * and internal PFLAGS3 flags. When used as a right-shift, translates
2551     * PFLAGS3 flags to public flags.
2552     */
2553    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2554
2555    /** @hide */
2556    @Retention(RetentionPolicy.SOURCE)
2557    @IntDef(flag = true,
2558            value = {
2559                    SCROLL_INDICATOR_TOP,
2560                    SCROLL_INDICATOR_BOTTOM,
2561                    SCROLL_INDICATOR_LEFT,
2562                    SCROLL_INDICATOR_RIGHT,
2563                    SCROLL_INDICATOR_START,
2564                    SCROLL_INDICATOR_END,
2565            })
2566    public @interface ScrollIndicators {}
2567
2568    /**
2569     * Scroll indicator direction for the top edge of the view.
2570     *
2571     * @see #setScrollIndicators(int)
2572     * @see #setScrollIndicators(int, int)
2573     * @see #getScrollIndicators()
2574     */
2575    public static final int SCROLL_INDICATOR_TOP =
2576            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2577
2578    /**
2579     * Scroll indicator direction for the bottom edge of the view.
2580     *
2581     * @see #setScrollIndicators(int)
2582     * @see #setScrollIndicators(int, int)
2583     * @see #getScrollIndicators()
2584     */
2585    public static final int SCROLL_INDICATOR_BOTTOM =
2586            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2587
2588    /**
2589     * Scroll indicator direction for the left edge of the view.
2590     *
2591     * @see #setScrollIndicators(int)
2592     * @see #setScrollIndicators(int, int)
2593     * @see #getScrollIndicators()
2594     */
2595    public static final int SCROLL_INDICATOR_LEFT =
2596            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2597
2598    /**
2599     * Scroll indicator direction for the right edge of the view.
2600     *
2601     * @see #setScrollIndicators(int)
2602     * @see #setScrollIndicators(int, int)
2603     * @see #getScrollIndicators()
2604     */
2605    public static final int SCROLL_INDICATOR_RIGHT =
2606            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2607
2608    /**
2609     * Scroll indicator direction for the starting edge of the view.
2610     * <p>
2611     * Resolved according to the view's layout direction, see
2612     * {@link #getLayoutDirection()} for more information.
2613     *
2614     * @see #setScrollIndicators(int)
2615     * @see #setScrollIndicators(int, int)
2616     * @see #getScrollIndicators()
2617     */
2618    public static final int SCROLL_INDICATOR_START =
2619            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2620
2621    /**
2622     * Scroll indicator direction for the ending edge of the view.
2623     * <p>
2624     * Resolved according to the view's layout direction, see
2625     * {@link #getLayoutDirection()} for more information.
2626     *
2627     * @see #setScrollIndicators(int)
2628     * @see #setScrollIndicators(int, int)
2629     * @see #getScrollIndicators()
2630     */
2631    public static final int SCROLL_INDICATOR_END =
2632            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2633
2634    /**
2635     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2636     * into this view.<p>
2637     */
2638    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2639
2640    /**
2641     * Whether this view has rendered elements that overlap (see {@link
2642     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2643     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2644     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2645     * determined by whatever {@link #hasOverlappingRendering()} returns.
2646     */
2647    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2648
2649    /**
2650     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2651     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2652     */
2653    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2654
2655    /**
2656     * Flag indicating that the view is temporarily detached from the parent view.
2657     *
2658     * @see #onStartTemporaryDetach()
2659     * @see #onFinishTemporaryDetach()
2660     */
2661    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
2662
2663    /**
2664     * Flag indicating that the view does not wish to be revealed within its parent
2665     * hierarchy when it gains focus. Expressed in the negative since the historical
2666     * default behavior is to reveal on focus; this flag suppresses that behavior.
2667     *
2668     * @see #setRevealOnFocusHint(boolean)
2669     * @see #getRevealOnFocusHint()
2670     */
2671    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
2672
2673    /* End of masks for mPrivateFlags3 */
2674
2675    /**
2676     * Always allow a user to over-scroll this view, provided it is a
2677     * view that can scroll.
2678     *
2679     * @see #getOverScrollMode()
2680     * @see #setOverScrollMode(int)
2681     */
2682    public static final int OVER_SCROLL_ALWAYS = 0;
2683
2684    /**
2685     * Allow a user to over-scroll this view only if the content is large
2686     * enough to meaningfully scroll, provided it is a view that can scroll.
2687     *
2688     * @see #getOverScrollMode()
2689     * @see #setOverScrollMode(int)
2690     */
2691    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2692
2693    /**
2694     * Never allow a user to over-scroll this view.
2695     *
2696     * @see #getOverScrollMode()
2697     * @see #setOverScrollMode(int)
2698     */
2699    public static final int OVER_SCROLL_NEVER = 2;
2700
2701    /**
2702     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2703     * requested the system UI (status bar) to be visible (the default).
2704     *
2705     * @see #setSystemUiVisibility(int)
2706     */
2707    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2708
2709    /**
2710     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2711     * system UI to enter an unobtrusive "low profile" mode.
2712     *
2713     * <p>This is for use in games, book readers, video players, or any other
2714     * "immersive" application where the usual system chrome is deemed too distracting.
2715     *
2716     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2717     *
2718     * @see #setSystemUiVisibility(int)
2719     */
2720    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2721
2722    /**
2723     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2724     * system navigation be temporarily hidden.
2725     *
2726     * <p>This is an even less obtrusive state than that called for by
2727     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2728     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2729     * those to disappear. This is useful (in conjunction with the
2730     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2731     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2732     * window flags) for displaying content using every last pixel on the display.
2733     *
2734     * <p>There is a limitation: because navigation controls are so important, the least user
2735     * interaction will cause them to reappear immediately.  When this happens, both
2736     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2737     * so that both elements reappear at the same time.
2738     *
2739     * @see #setSystemUiVisibility(int)
2740     */
2741    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2742
2743    /**
2744     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2745     * into the normal fullscreen mode so that its content can take over the screen
2746     * while still allowing the user to interact with the application.
2747     *
2748     * <p>This has the same visual effect as
2749     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2750     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2751     * meaning that non-critical screen decorations (such as the status bar) will be
2752     * hidden while the user is in the View's window, focusing the experience on
2753     * that content.  Unlike the window flag, if you are using ActionBar in
2754     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2755     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2756     * hide the action bar.
2757     *
2758     * <p>This approach to going fullscreen is best used over the window flag when
2759     * it is a transient state -- that is, the application does this at certain
2760     * points in its user interaction where it wants to allow the user to focus
2761     * on content, but not as a continuous state.  For situations where the application
2762     * would like to simply stay full screen the entire time (such as a game that
2763     * wants to take over the screen), the
2764     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2765     * is usually a better approach.  The state set here will be removed by the system
2766     * in various situations (such as the user moving to another application) like
2767     * the other system UI states.
2768     *
2769     * <p>When using this flag, the application should provide some easy facility
2770     * for the user to go out of it.  A common example would be in an e-book
2771     * reader, where tapping on the screen brings back whatever screen and UI
2772     * decorations that had been hidden while the user was immersed in reading
2773     * the book.
2774     *
2775     * @see #setSystemUiVisibility(int)
2776     */
2777    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2778
2779    /**
2780     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2781     * flags, we would like a stable view of the content insets given to
2782     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2783     * will always represent the worst case that the application can expect
2784     * as a continuous state.  In the stock Android UI this is the space for
2785     * the system bar, nav bar, and status bar, but not more transient elements
2786     * such as an input method.
2787     *
2788     * The stable layout your UI sees is based on the system UI modes you can
2789     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2790     * then you will get a stable layout for changes of the
2791     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2792     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2793     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2794     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2795     * with a stable layout.  (Note that you should avoid using
2796     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2797     *
2798     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2799     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2800     * then a hidden status bar will be considered a "stable" state for purposes
2801     * here.  This allows your UI to continually hide the status bar, while still
2802     * using the system UI flags to hide the action bar while still retaining
2803     * a stable layout.  Note that changing the window fullscreen flag will never
2804     * provide a stable layout for a clean transition.
2805     *
2806     * <p>If you are using ActionBar in
2807     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2808     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2809     * insets it adds to those given to the application.
2810     */
2811    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2812
2813    /**
2814     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2815     * to be laid out as if it has requested
2816     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2817     * allows it to avoid artifacts when switching in and out of that mode, at
2818     * the expense that some of its user interface may be covered by screen
2819     * decorations when they are shown.  You can perform layout of your inner
2820     * UI elements to account for the navigation system UI through the
2821     * {@link #fitSystemWindows(Rect)} method.
2822     */
2823    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2824
2825    /**
2826     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2827     * to be laid out as if it has requested
2828     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2829     * allows it to avoid artifacts when switching in and out of that mode, at
2830     * the expense that some of its user interface may be covered by screen
2831     * decorations when they are shown.  You can perform layout of your inner
2832     * UI elements to account for non-fullscreen system UI through the
2833     * {@link #fitSystemWindows(Rect)} method.
2834     */
2835    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2836
2837    /**
2838     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2839     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2840     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2841     * user interaction.
2842     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2843     * has an effect when used in combination with that flag.</p>
2844     */
2845    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2846
2847    /**
2848     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2849     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2850     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2851     * experience while also hiding the system bars.  If this flag is not set,
2852     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2853     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2854     * if the user swipes from the top of the screen.
2855     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2856     * system gestures, such as swiping from the top of the screen.  These transient system bars
2857     * will overlay app’s content, may have some degree of transparency, and will automatically
2858     * hide after a short timeout.
2859     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2860     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2861     * with one or both of those flags.</p>
2862     */
2863    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2864
2865    /**
2866     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2867     * is compatible with light status bar backgrounds.
2868     *
2869     * <p>For this to take effect, the window must request
2870     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2871     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2872     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2873     *         FLAG_TRANSLUCENT_STATUS}.
2874     *
2875     * @see android.R.attr#windowLightStatusBar
2876     */
2877    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2878
2879    /**
2880     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2881     */
2882    @Deprecated
2883    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2884
2885    /**
2886     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2887     */
2888    @Deprecated
2889    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2890
2891    /**
2892     * @hide
2893     *
2894     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2895     * out of the public fields to keep the undefined bits out of the developer's way.
2896     *
2897     * Flag to make the status bar not expandable.  Unless you also
2898     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2899     */
2900    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2901
2902    /**
2903     * @hide
2904     *
2905     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2906     * out of the public fields to keep the undefined bits out of the developer's way.
2907     *
2908     * Flag to hide notification icons and scrolling ticker text.
2909     */
2910    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2911
2912    /**
2913     * @hide
2914     *
2915     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2916     * out of the public fields to keep the undefined bits out of the developer's way.
2917     *
2918     * Flag to disable incoming notification alerts.  This will not block
2919     * icons, but it will block sound, vibrating and other visual or aural notifications.
2920     */
2921    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2922
2923    /**
2924     * @hide
2925     *
2926     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2927     * out of the public fields to keep the undefined bits out of the developer's way.
2928     *
2929     * Flag to hide only the scrolling ticker.  Note that
2930     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2931     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2932     */
2933    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2934
2935    /**
2936     * @hide
2937     *
2938     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2939     * out of the public fields to keep the undefined bits out of the developer's way.
2940     *
2941     * Flag to hide the center system info area.
2942     */
2943    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2944
2945    /**
2946     * @hide
2947     *
2948     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2949     * out of the public fields to keep the undefined bits out of the developer's way.
2950     *
2951     * Flag to hide only the home button.  Don't use this
2952     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2953     */
2954    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2955
2956    /**
2957     * @hide
2958     *
2959     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2960     * out of the public fields to keep the undefined bits out of the developer's way.
2961     *
2962     * Flag to hide only the back button. Don't use this
2963     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2964     */
2965    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2966
2967    /**
2968     * @hide
2969     *
2970     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2971     * out of the public fields to keep the undefined bits out of the developer's way.
2972     *
2973     * Flag to hide only the clock.  You might use this if your activity has
2974     * its own clock making the status bar's clock redundant.
2975     */
2976    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2977
2978    /**
2979     * @hide
2980     *
2981     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2982     * out of the public fields to keep the undefined bits out of the developer's way.
2983     *
2984     * Flag to hide only the recent apps button. Don't use this
2985     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2986     */
2987    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2988
2989    /**
2990     * @hide
2991     *
2992     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2993     * out of the public fields to keep the undefined bits out of the developer's way.
2994     *
2995     * Flag to disable the global search gesture. Don't use this
2996     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2997     */
2998    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2999
3000    /**
3001     * @hide
3002     *
3003     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3004     * out of the public fields to keep the undefined bits out of the developer's way.
3005     *
3006     * Flag to specify that the status bar is displayed in transient mode.
3007     */
3008    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3009
3010    /**
3011     * @hide
3012     *
3013     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3014     * out of the public fields to keep the undefined bits out of the developer's way.
3015     *
3016     * Flag to specify that the navigation bar is displayed in transient mode.
3017     */
3018    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3019
3020    /**
3021     * @hide
3022     *
3023     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3024     * out of the public fields to keep the undefined bits out of the developer's way.
3025     *
3026     * Flag to specify that the hidden status bar would like to be shown.
3027     */
3028    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3029
3030    /**
3031     * @hide
3032     *
3033     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3034     * out of the public fields to keep the undefined bits out of the developer's way.
3035     *
3036     * Flag to specify that the hidden navigation bar would like to be shown.
3037     */
3038    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3039
3040    /**
3041     * @hide
3042     *
3043     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3044     * out of the public fields to keep the undefined bits out of the developer's way.
3045     *
3046     * Flag to specify that the status bar is displayed in translucent mode.
3047     */
3048    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3049
3050    /**
3051     * @hide
3052     *
3053     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3054     * out of the public fields to keep the undefined bits out of the developer's way.
3055     *
3056     * Flag to specify that the navigation bar is displayed in translucent mode.
3057     */
3058    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3059
3060    /**
3061     * @hide
3062     *
3063     * Whether Recents is visible or not.
3064     */
3065    public static final int RECENT_APPS_VISIBLE = 0x00004000;
3066
3067    /**
3068     * @hide
3069     *
3070     * Whether the TV's picture-in-picture is visible or not.
3071     */
3072    public static final int TV_PICTURE_IN_PICTURE_VISIBLE = 0x00010000;
3073
3074    /**
3075     * @hide
3076     *
3077     * Makes navigation bar transparent (but not the status bar).
3078     */
3079    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3080
3081    /**
3082     * @hide
3083     *
3084     * Makes status bar transparent (but not the navigation bar).
3085     */
3086    public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
3087
3088    /**
3089     * @hide
3090     *
3091     * Makes both status bar and navigation bar transparent.
3092     */
3093    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3094            | STATUS_BAR_TRANSPARENT;
3095
3096    /**
3097     * @hide
3098     */
3099    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3100
3101    /**
3102     * These are the system UI flags that can be cleared by events outside
3103     * of an application.  Currently this is just the ability to tap on the
3104     * screen while hiding the navigation bar to have it return.
3105     * @hide
3106     */
3107    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3108            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3109            | SYSTEM_UI_FLAG_FULLSCREEN;
3110
3111    /**
3112     * Flags that can impact the layout in relation to system UI.
3113     */
3114    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3115            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3116            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3117
3118    /** @hide */
3119    @IntDef(flag = true,
3120            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3121    @Retention(RetentionPolicy.SOURCE)
3122    public @interface FindViewFlags {}
3123
3124    /**
3125     * Find views that render the specified text.
3126     *
3127     * @see #findViewsWithText(ArrayList, CharSequence, int)
3128     */
3129    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3130
3131    /**
3132     * Find find views that contain the specified content description.
3133     *
3134     * @see #findViewsWithText(ArrayList, CharSequence, int)
3135     */
3136    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3137
3138    /**
3139     * Find views that contain {@link AccessibilityNodeProvider}. Such
3140     * a View is a root of virtual view hierarchy and may contain the searched
3141     * text. If this flag is set Views with providers are automatically
3142     * added and it is a responsibility of the client to call the APIs of
3143     * the provider to determine whether the virtual tree rooted at this View
3144     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3145     * representing the virtual views with this text.
3146     *
3147     * @see #findViewsWithText(ArrayList, CharSequence, int)
3148     *
3149     * @hide
3150     */
3151    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3152
3153    /**
3154     * The undefined cursor position.
3155     *
3156     * @hide
3157     */
3158    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3159
3160    /**
3161     * Indicates that the screen has changed state and is now off.
3162     *
3163     * @see #onScreenStateChanged(int)
3164     */
3165    public static final int SCREEN_STATE_OFF = 0x0;
3166
3167    /**
3168     * Indicates that the screen has changed state and is now on.
3169     *
3170     * @see #onScreenStateChanged(int)
3171     */
3172    public static final int SCREEN_STATE_ON = 0x1;
3173
3174    /**
3175     * Indicates no axis of view scrolling.
3176     */
3177    public static final int SCROLL_AXIS_NONE = 0;
3178
3179    /**
3180     * Indicates scrolling along the horizontal axis.
3181     */
3182    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3183
3184    /**
3185     * Indicates scrolling along the vertical axis.
3186     */
3187    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3188
3189    /**
3190     * Controls the over-scroll mode for this view.
3191     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3192     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3193     * and {@link #OVER_SCROLL_NEVER}.
3194     */
3195    private int mOverScrollMode;
3196
3197    /**
3198     * The parent this view is attached to.
3199     * {@hide}
3200     *
3201     * @see #getParent()
3202     */
3203    protected ViewParent mParent;
3204
3205    /**
3206     * {@hide}
3207     */
3208    AttachInfo mAttachInfo;
3209
3210    /**
3211     * {@hide}
3212     */
3213    @ViewDebug.ExportedProperty(flagMapping = {
3214        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3215                name = "FORCE_LAYOUT"),
3216        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3217                name = "LAYOUT_REQUIRED"),
3218        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3219            name = "DRAWING_CACHE_INVALID", outputIf = false),
3220        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3221        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3222        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3223        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3224    }, formatToHexString = true)
3225    int mPrivateFlags;
3226    int mPrivateFlags2;
3227    int mPrivateFlags3;
3228
3229    /**
3230     * This view's request for the visibility of the status bar.
3231     * @hide
3232     */
3233    @ViewDebug.ExportedProperty(flagMapping = {
3234        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3235                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3236                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3237        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3238                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3239                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3240        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3241                                equals = SYSTEM_UI_FLAG_VISIBLE,
3242                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3243    }, formatToHexString = true)
3244    int mSystemUiVisibility;
3245
3246    /**
3247     * Reference count for transient state.
3248     * @see #setHasTransientState(boolean)
3249     */
3250    int mTransientStateCount = 0;
3251
3252    /**
3253     * Count of how many windows this view has been attached to.
3254     */
3255    int mWindowAttachCount;
3256
3257    /**
3258     * The layout parameters associated with this view and used by the parent
3259     * {@link android.view.ViewGroup} to determine how this view should be
3260     * laid out.
3261     * {@hide}
3262     */
3263    protected ViewGroup.LayoutParams mLayoutParams;
3264
3265    /**
3266     * The view flags hold various views states.
3267     * {@hide}
3268     */
3269    @ViewDebug.ExportedProperty(formatToHexString = true)
3270    int mViewFlags;
3271
3272    static class TransformationInfo {
3273        /**
3274         * The transform matrix for the View. This transform is calculated internally
3275         * based on the translation, rotation, and scale properties.
3276         *
3277         * Do *not* use this variable directly; instead call getMatrix(), which will
3278         * load the value from the View's RenderNode.
3279         */
3280        private final Matrix mMatrix = new Matrix();
3281
3282        /**
3283         * The inverse transform matrix for the View. This transform is calculated
3284         * internally based on the translation, rotation, and scale properties.
3285         *
3286         * Do *not* use this variable directly; instead call getInverseMatrix(),
3287         * which will load the value from the View's RenderNode.
3288         */
3289        private Matrix mInverseMatrix;
3290
3291        /**
3292         * The opacity of the View. This is a value from 0 to 1, where 0 means
3293         * completely transparent and 1 means completely opaque.
3294         */
3295        @ViewDebug.ExportedProperty
3296        float mAlpha = 1f;
3297
3298        /**
3299         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3300         * property only used by transitions, which is composited with the other alpha
3301         * values to calculate the final visual alpha value.
3302         */
3303        float mTransitionAlpha = 1f;
3304    }
3305
3306    TransformationInfo mTransformationInfo;
3307
3308    /**
3309     * Current clip bounds. to which all drawing of this view are constrained.
3310     */
3311    Rect mClipBounds = null;
3312
3313    private boolean mLastIsOpaque;
3314
3315    /**
3316     * The distance in pixels from the left edge of this view's parent
3317     * to the left edge of this view.
3318     * {@hide}
3319     */
3320    @ViewDebug.ExportedProperty(category = "layout")
3321    protected int mLeft;
3322    /**
3323     * The distance in pixels from the left edge of this view's parent
3324     * to the right edge of this view.
3325     * {@hide}
3326     */
3327    @ViewDebug.ExportedProperty(category = "layout")
3328    protected int mRight;
3329    /**
3330     * The distance in pixels from the top edge of this view's parent
3331     * to the top edge of this view.
3332     * {@hide}
3333     */
3334    @ViewDebug.ExportedProperty(category = "layout")
3335    protected int mTop;
3336    /**
3337     * The distance in pixels from the top edge of this view's parent
3338     * to the bottom edge of this view.
3339     * {@hide}
3340     */
3341    @ViewDebug.ExportedProperty(category = "layout")
3342    protected int mBottom;
3343
3344    /**
3345     * The offset, in pixels, by which the content of this view is scrolled
3346     * horizontally.
3347     * {@hide}
3348     */
3349    @ViewDebug.ExportedProperty(category = "scrolling")
3350    protected int mScrollX;
3351    /**
3352     * The offset, in pixels, by which the content of this view is scrolled
3353     * vertically.
3354     * {@hide}
3355     */
3356    @ViewDebug.ExportedProperty(category = "scrolling")
3357    protected int mScrollY;
3358
3359    /**
3360     * The left padding in pixels, that is the distance in pixels between the
3361     * left edge of this view and the left edge of its content.
3362     * {@hide}
3363     */
3364    @ViewDebug.ExportedProperty(category = "padding")
3365    protected int mPaddingLeft = 0;
3366    /**
3367     * The right padding in pixels, that is the distance in pixels between the
3368     * right edge of this view and the right edge of its content.
3369     * {@hide}
3370     */
3371    @ViewDebug.ExportedProperty(category = "padding")
3372    protected int mPaddingRight = 0;
3373    /**
3374     * The top padding in pixels, that is the distance in pixels between the
3375     * top edge of this view and the top edge of its content.
3376     * {@hide}
3377     */
3378    @ViewDebug.ExportedProperty(category = "padding")
3379    protected int mPaddingTop;
3380    /**
3381     * The bottom padding in pixels, that is the distance in pixels between the
3382     * bottom edge of this view and the bottom edge of its content.
3383     * {@hide}
3384     */
3385    @ViewDebug.ExportedProperty(category = "padding")
3386    protected int mPaddingBottom;
3387
3388    /**
3389     * The layout insets in pixels, that is the distance in pixels between the
3390     * visible edges of this view its bounds.
3391     */
3392    private Insets mLayoutInsets;
3393
3394    /**
3395     * Briefly describes the view and is primarily used for accessibility support.
3396     */
3397    private CharSequence mContentDescription;
3398
3399    /**
3400     * Specifies the id of a view for which this view serves as a label for
3401     * accessibility purposes.
3402     */
3403    private int mLabelForId = View.NO_ID;
3404
3405    /**
3406     * Predicate for matching labeled view id with its label for
3407     * accessibility purposes.
3408     */
3409    private MatchLabelForPredicate mMatchLabelForPredicate;
3410
3411    /**
3412     * Specifies a view before which this one is visited in accessibility traversal.
3413     */
3414    private int mAccessibilityTraversalBeforeId = NO_ID;
3415
3416    /**
3417     * Specifies a view after which this one is visited in accessibility traversal.
3418     */
3419    private int mAccessibilityTraversalAfterId = NO_ID;
3420
3421    /**
3422     * Predicate for matching a view by its id.
3423     */
3424    private MatchIdPredicate mMatchIdPredicate;
3425
3426    /**
3427     * Cache the paddingRight set by the user to append to the scrollbar's size.
3428     *
3429     * @hide
3430     */
3431    @ViewDebug.ExportedProperty(category = "padding")
3432    protected int mUserPaddingRight;
3433
3434    /**
3435     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3436     *
3437     * @hide
3438     */
3439    @ViewDebug.ExportedProperty(category = "padding")
3440    protected int mUserPaddingBottom;
3441
3442    /**
3443     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3444     *
3445     * @hide
3446     */
3447    @ViewDebug.ExportedProperty(category = "padding")
3448    protected int mUserPaddingLeft;
3449
3450    /**
3451     * Cache the paddingStart set by the user to append to the scrollbar's size.
3452     *
3453     */
3454    @ViewDebug.ExportedProperty(category = "padding")
3455    int mUserPaddingStart;
3456
3457    /**
3458     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3459     *
3460     */
3461    @ViewDebug.ExportedProperty(category = "padding")
3462    int mUserPaddingEnd;
3463
3464    /**
3465     * Cache initial left padding.
3466     *
3467     * @hide
3468     */
3469    int mUserPaddingLeftInitial;
3470
3471    /**
3472     * Cache initial right padding.
3473     *
3474     * @hide
3475     */
3476    int mUserPaddingRightInitial;
3477
3478    /**
3479     * Default undefined padding
3480     */
3481    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3482
3483    /**
3484     * Cache if a left padding has been defined
3485     */
3486    private boolean mLeftPaddingDefined = false;
3487
3488    /**
3489     * Cache if a right padding has been defined
3490     */
3491    private boolean mRightPaddingDefined = false;
3492
3493    /**
3494     * @hide
3495     */
3496    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3497    /**
3498     * @hide
3499     */
3500    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3501
3502    private LongSparseLongArray mMeasureCache;
3503
3504    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3505    private Drawable mBackground;
3506    private TintInfo mBackgroundTint;
3507
3508    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3509    private ForegroundInfo mForegroundInfo;
3510
3511    private Drawable mScrollIndicatorDrawable;
3512
3513    /**
3514     * RenderNode used for backgrounds.
3515     * <p>
3516     * When non-null and valid, this is expected to contain an up-to-date copy
3517     * of the background drawable. It is cleared on temporary detach, and reset
3518     * on cleanup.
3519     */
3520    private RenderNode mBackgroundRenderNode;
3521
3522    private int mBackgroundResource;
3523    private boolean mBackgroundSizeChanged;
3524
3525    private String mTransitionName;
3526
3527    static class TintInfo {
3528        ColorStateList mTintList;
3529        PorterDuff.Mode mTintMode;
3530        boolean mHasTintMode;
3531        boolean mHasTintList;
3532    }
3533
3534    private static class ForegroundInfo {
3535        private Drawable mDrawable;
3536        private TintInfo mTintInfo;
3537        private int mGravity = Gravity.FILL;
3538        private boolean mInsidePadding = true;
3539        private boolean mBoundsChanged = true;
3540        private final Rect mSelfBounds = new Rect();
3541        private final Rect mOverlayBounds = new Rect();
3542    }
3543
3544    static class ListenerInfo {
3545        /**
3546         * Listener used to dispatch focus change events.
3547         * This field should be made private, so it is hidden from the SDK.
3548         * {@hide}
3549         */
3550        protected OnFocusChangeListener mOnFocusChangeListener;
3551
3552        /**
3553         * Listeners for layout change events.
3554         */
3555        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3556
3557        protected OnScrollChangeListener mOnScrollChangeListener;
3558
3559        /**
3560         * Listeners for attach events.
3561         */
3562        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3563
3564        /**
3565         * Listener used to dispatch click events.
3566         * This field should be made private, so it is hidden from the SDK.
3567         * {@hide}
3568         */
3569        public OnClickListener mOnClickListener;
3570
3571        /**
3572         * Listener used to dispatch long click events.
3573         * This field should be made private, so it is hidden from the SDK.
3574         * {@hide}
3575         */
3576        protected OnLongClickListener mOnLongClickListener;
3577
3578        /**
3579         * Listener used to dispatch context click events. This field should be made private, so it
3580         * is hidden from the SDK.
3581         * {@hide}
3582         */
3583        protected OnContextClickListener mOnContextClickListener;
3584
3585        /**
3586         * Listener used to build the context menu.
3587         * This field should be made private, so it is hidden from the SDK.
3588         * {@hide}
3589         */
3590        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3591
3592        private OnKeyListener mOnKeyListener;
3593
3594        private OnTouchListener mOnTouchListener;
3595
3596        private OnHoverListener mOnHoverListener;
3597
3598        private OnGenericMotionListener mOnGenericMotionListener;
3599
3600        private OnDragListener mOnDragListener;
3601
3602        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3603
3604        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3605    }
3606
3607    ListenerInfo mListenerInfo;
3608
3609    // Temporary values used to hold (x,y) coordinates when delegating from the
3610    // two-arg performLongClick() method to the legacy no-arg version.
3611    private float mLongClickX = Float.NaN;
3612    private float mLongClickY = Float.NaN;
3613
3614    /**
3615     * The application environment this view lives in.
3616     * This field should be made private, so it is hidden from the SDK.
3617     * {@hide}
3618     */
3619    @ViewDebug.ExportedProperty(deepExport = true)
3620    protected Context mContext;
3621
3622    private final Resources mResources;
3623
3624    private ScrollabilityCache mScrollCache;
3625
3626    private int[] mDrawableState = null;
3627
3628    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3629
3630    /**
3631     * Animator that automatically runs based on state changes.
3632     */
3633    private StateListAnimator mStateListAnimator;
3634
3635    /**
3636     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3637     * the user may specify which view to go to next.
3638     */
3639    private int mNextFocusLeftId = View.NO_ID;
3640
3641    /**
3642     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3643     * the user may specify which view to go to next.
3644     */
3645    private int mNextFocusRightId = View.NO_ID;
3646
3647    /**
3648     * When this view has focus and the next focus is {@link #FOCUS_UP},
3649     * the user may specify which view to go to next.
3650     */
3651    private int mNextFocusUpId = View.NO_ID;
3652
3653    /**
3654     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3655     * the user may specify which view to go to next.
3656     */
3657    private int mNextFocusDownId = View.NO_ID;
3658
3659    /**
3660     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3661     * the user may specify which view to go to next.
3662     */
3663    int mNextFocusForwardId = View.NO_ID;
3664
3665    private CheckForLongPress mPendingCheckForLongPress;
3666    private CheckForTap mPendingCheckForTap = null;
3667    private PerformClick mPerformClick;
3668    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3669
3670    private UnsetPressedState mUnsetPressedState;
3671
3672    /**
3673     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3674     * up event while a long press is invoked as soon as the long press duration is reached, so
3675     * a long press could be performed before the tap is checked, in which case the tap's action
3676     * should not be invoked.
3677     */
3678    private boolean mHasPerformedLongPress;
3679
3680    /**
3681     * Whether a context click button is currently pressed down. This is true when the stylus is
3682     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3683     * pressed. This is false once the button is released or if the stylus has been lifted.
3684     */
3685    private boolean mInContextButtonPress;
3686
3687    /**
3688     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3689     * true after a stylus button press has occured, when the next up event should not be recognized
3690     * as a tap.
3691     */
3692    private boolean mIgnoreNextUpEvent;
3693
3694    /**
3695     * The minimum height of the view. We'll try our best to have the height
3696     * of this view to at least this amount.
3697     */
3698    @ViewDebug.ExportedProperty(category = "measurement")
3699    private int mMinHeight;
3700
3701    /**
3702     * The minimum width of the view. We'll try our best to have the width
3703     * of this view to at least this amount.
3704     */
3705    @ViewDebug.ExportedProperty(category = "measurement")
3706    private int mMinWidth;
3707
3708    /**
3709     * The delegate to handle touch events that are physically in this view
3710     * but should be handled by another view.
3711     */
3712    private TouchDelegate mTouchDelegate = null;
3713
3714    /**
3715     * Solid color to use as a background when creating the drawing cache. Enables
3716     * the cache to use 16 bit bitmaps instead of 32 bit.
3717     */
3718    private int mDrawingCacheBackgroundColor = 0;
3719
3720    /**
3721     * Special tree observer used when mAttachInfo is null.
3722     */
3723    private ViewTreeObserver mFloatingTreeObserver;
3724
3725    /**
3726     * Cache the touch slop from the context that created the view.
3727     */
3728    private int mTouchSlop;
3729
3730    /**
3731     * Object that handles automatic animation of view properties.
3732     */
3733    private ViewPropertyAnimator mAnimator = null;
3734
3735    /**
3736     * List of registered FrameMetricsObservers.
3737     */
3738    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
3739
3740    /**
3741     * Flag indicating that a drag can cross window boundaries.  When
3742     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3743     * with this flag set, all visible applications with targetSdkVersion >=
3744     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
3745     * in the drag operation and receive the dragged content.
3746     *
3747     * <p>If this is the only flag set, then the drag recipient will only have access to text data
3748     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3749     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
3750     */
3751    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3752
3753    /**
3754     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3755     * request read access to the content URI(s) contained in the {@link ClipData} object.
3756     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3757     */
3758    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3759
3760    /**
3761     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3762     * request write access to the content URI(s) contained in the {@link ClipData} object.
3763     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3764     */
3765    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3766
3767    /**
3768     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3769     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3770     * reboots until explicitly revoked with
3771     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3772     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3773     */
3774    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3775            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3776
3777    /**
3778     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3779     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3780     * match against the original granted URI.
3781     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3782     */
3783    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3784            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3785
3786    /**
3787     * Flag indicating that the drag shadow will be opaque.  When
3788     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3789     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3790     */
3791    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3792
3793    /**
3794     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3795     */
3796    private float mVerticalScrollFactor;
3797
3798    /**
3799     * Position of the vertical scroll bar.
3800     */
3801    private int mVerticalScrollbarPosition;
3802
3803    /**
3804     * Position the scroll bar at the default position as determined by the system.
3805     */
3806    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3807
3808    /**
3809     * Position the scroll bar along the left edge.
3810     */
3811    public static final int SCROLLBAR_POSITION_LEFT = 1;
3812
3813    /**
3814     * Position the scroll bar along the right edge.
3815     */
3816    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3817
3818    /**
3819     * Indicates that the view does not have a layer.
3820     *
3821     * @see #getLayerType()
3822     * @see #setLayerType(int, android.graphics.Paint)
3823     * @see #LAYER_TYPE_SOFTWARE
3824     * @see #LAYER_TYPE_HARDWARE
3825     */
3826    public static final int LAYER_TYPE_NONE = 0;
3827
3828    /**
3829     * <p>Indicates that the view has a software layer. A software layer is backed
3830     * by a bitmap and causes the view to be rendered using Android's software
3831     * rendering pipeline, even if hardware acceleration is enabled.</p>
3832     *
3833     * <p>Software layers have various usages:</p>
3834     * <p>When the application is not using hardware acceleration, a software layer
3835     * is useful to apply a specific color filter and/or blending mode and/or
3836     * translucency to a view and all its children.</p>
3837     * <p>When the application is using hardware acceleration, a software layer
3838     * is useful to render drawing primitives not supported by the hardware
3839     * accelerated pipeline. It can also be used to cache a complex view tree
3840     * into a texture and reduce the complexity of drawing operations. For instance,
3841     * when animating a complex view tree with a translation, a software layer can
3842     * be used to render the view tree only once.</p>
3843     * <p>Software layers should be avoided when the affected view tree updates
3844     * often. Every update will require to re-render the software layer, which can
3845     * potentially be slow (particularly when hardware acceleration is turned on
3846     * since the layer will have to be uploaded into a hardware texture after every
3847     * update.)</p>
3848     *
3849     * @see #getLayerType()
3850     * @see #setLayerType(int, android.graphics.Paint)
3851     * @see #LAYER_TYPE_NONE
3852     * @see #LAYER_TYPE_HARDWARE
3853     */
3854    public static final int LAYER_TYPE_SOFTWARE = 1;
3855
3856    /**
3857     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3858     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3859     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3860     * rendering pipeline, but only if hardware acceleration is turned on for the
3861     * view hierarchy. When hardware acceleration is turned off, hardware layers
3862     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3863     *
3864     * <p>A hardware layer is useful to apply a specific color filter and/or
3865     * blending mode and/or translucency to a view and all its children.</p>
3866     * <p>A hardware layer can be used to cache a complex view tree into a
3867     * texture and reduce the complexity of drawing operations. For instance,
3868     * when animating a complex view tree with a translation, a hardware layer can
3869     * be used to render the view tree only once.</p>
3870     * <p>A hardware layer can also be used to increase the rendering quality when
3871     * rotation transformations are applied on a view. It can also be used to
3872     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3873     *
3874     * @see #getLayerType()
3875     * @see #setLayerType(int, android.graphics.Paint)
3876     * @see #LAYER_TYPE_NONE
3877     * @see #LAYER_TYPE_SOFTWARE
3878     */
3879    public static final int LAYER_TYPE_HARDWARE = 2;
3880
3881    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3882            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3883            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3884            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3885    })
3886    int mLayerType = LAYER_TYPE_NONE;
3887    Paint mLayerPaint;
3888
3889    /**
3890     * Set to true when drawing cache is enabled and cannot be created.
3891     *
3892     * @hide
3893     */
3894    public boolean mCachingFailed;
3895    private Bitmap mDrawingCache;
3896    private Bitmap mUnscaledDrawingCache;
3897
3898    /**
3899     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3900     * <p>
3901     * When non-null and valid, this is expected to contain an up-to-date copy
3902     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3903     * cleanup.
3904     */
3905    final RenderNode mRenderNode;
3906
3907    /**
3908     * Set to true when the view is sending hover accessibility events because it
3909     * is the innermost hovered view.
3910     */
3911    private boolean mSendingHoverAccessibilityEvents;
3912
3913    /**
3914     * Delegate for injecting accessibility functionality.
3915     */
3916    AccessibilityDelegate mAccessibilityDelegate;
3917
3918    /**
3919     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3920     * and add/remove objects to/from the overlay directly through the Overlay methods.
3921     */
3922    ViewOverlay mOverlay;
3923
3924    /**
3925     * The currently active parent view for receiving delegated nested scrolling events.
3926     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3927     * by {@link #stopNestedScroll()} at the same point where we clear
3928     * requestDisallowInterceptTouchEvent.
3929     */
3930    private ViewParent mNestedScrollingParent;
3931
3932    /**
3933     * Consistency verifier for debugging purposes.
3934     * @hide
3935     */
3936    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3937            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3938                    new InputEventConsistencyVerifier(this, 0) : null;
3939
3940    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3941
3942    private int[] mTempNestedScrollConsumed;
3943
3944    /**
3945     * An overlay is going to draw this View instead of being drawn as part of this
3946     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3947     * when this view is invalidated.
3948     */
3949    GhostView mGhostView;
3950
3951    /**
3952     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3953     * @hide
3954     */
3955    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3956    public String[] mAttributes;
3957
3958    /**
3959     * Maps a Resource id to its name.
3960     */
3961    private static SparseArray<String> mAttributeMap;
3962
3963    /**
3964     * Queue of pending runnables. Used to postpone calls to post() until this
3965     * view is attached and has a handler.
3966     */
3967    private HandlerActionQueue mRunQueue;
3968
3969    /**
3970     * The pointer icon when the mouse hovers on this view. The default is null.
3971     */
3972    private PointerIcon mPointerIcon;
3973
3974    /**
3975     * @hide
3976     */
3977    String mStartActivityRequestWho;
3978
3979    @Nullable
3980    private RoundScrollbarRenderer mRoundScrollbarRenderer;
3981
3982    /**
3983     * Simple constructor to use when creating a view from code.
3984     *
3985     * @param context The Context the view is running in, through which it can
3986     *        access the current theme, resources, etc.
3987     */
3988    public View(Context context) {
3989        mContext = context;
3990        mResources = context != null ? context.getResources() : null;
3991        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3992        // Set some flags defaults
3993        mPrivateFlags2 =
3994                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3995                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3996                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3997                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3998                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3999                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4000        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4001        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4002        mUserPaddingStart = UNDEFINED_PADDING;
4003        mUserPaddingEnd = UNDEFINED_PADDING;
4004        mRenderNode = RenderNode.create(getClass().getName(), this);
4005
4006        if (!sCompatibilityDone && context != null) {
4007            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4008
4009            // Older apps may need this compatibility hack for measurement.
4010            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
4011
4012            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4013            // of whether a layout was requested on that View.
4014            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
4015
4016            Canvas.sCompatibilityRestore = targetSdkVersion < M;
4017
4018            // In M and newer, our widgets can pass a "hint" value in the size
4019            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4020            // know what the expected parent size is going to be, so e.g. list items can size
4021            // themselves at 1/3 the size of their container. It breaks older apps though,
4022            // specifically apps that use some popular open source libraries.
4023            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
4024
4025            // Old versions of the platform would give different results from
4026            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4027            // modes, so we always need to run an additional EXACTLY pass.
4028            sAlwaysRemeasureExactly = targetSdkVersion <= M;
4029
4030            // Prior to N, layout params could change without requiring a
4031            // subsequent call to setLayoutParams() and they would usually
4032            // work. Partial layout breaks this assumption.
4033            sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
4034
4035            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4036            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4037            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
4038
4039            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4040            // in apps so we target check it to avoid breaking existing apps.
4041            sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N;
4042
4043            sCompatibilityDone = true;
4044        }
4045    }
4046
4047    /**
4048     * Constructor that is called when inflating a view from XML. This is called
4049     * when a view is being constructed from an XML file, supplying attributes
4050     * that were specified in the XML file. This version uses a default style of
4051     * 0, so the only attribute values applied are those in the Context's Theme
4052     * and the given AttributeSet.
4053     *
4054     * <p>
4055     * The method onFinishInflate() will be called after all children have been
4056     * added.
4057     *
4058     * @param context The Context the view is running in, through which it can
4059     *        access the current theme, resources, etc.
4060     * @param attrs The attributes of the XML tag that is inflating the view.
4061     * @see #View(Context, AttributeSet, int)
4062     */
4063    public View(Context context, @Nullable AttributeSet attrs) {
4064        this(context, attrs, 0);
4065    }
4066
4067    /**
4068     * Perform inflation from XML and apply a class-specific base style from a
4069     * theme attribute. This constructor of View allows subclasses to use their
4070     * own base style when they are inflating. For example, a Button class's
4071     * constructor would call this version of the super class constructor and
4072     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4073     * allows the theme's button style to modify all of the base view attributes
4074     * (in particular its background) as well as the Button class's attributes.
4075     *
4076     * @param context The Context the view is running in, through which it can
4077     *        access the current theme, resources, etc.
4078     * @param attrs The attributes of the XML tag that is inflating the view.
4079     * @param defStyleAttr An attribute in the current theme that contains a
4080     *        reference to a style resource that supplies default values for
4081     *        the view. Can be 0 to not look for defaults.
4082     * @see #View(Context, AttributeSet)
4083     */
4084    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4085        this(context, attrs, defStyleAttr, 0);
4086    }
4087
4088    /**
4089     * Perform inflation from XML and apply a class-specific base style from a
4090     * theme attribute or style resource. This constructor of View allows
4091     * subclasses to use their own base style when they are inflating.
4092     * <p>
4093     * When determining the final value of a particular attribute, there are
4094     * four inputs that come into play:
4095     * <ol>
4096     * <li>Any attribute values in the given AttributeSet.
4097     * <li>The style resource specified in the AttributeSet (named "style").
4098     * <li>The default style specified by <var>defStyleAttr</var>.
4099     * <li>The default style specified by <var>defStyleRes</var>.
4100     * <li>The base values in this theme.
4101     * </ol>
4102     * <p>
4103     * Each of these inputs is considered in-order, with the first listed taking
4104     * precedence over the following ones. In other words, if in the
4105     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4106     * , then the button's text will <em>always</em> be black, regardless of
4107     * what is specified in any of the styles.
4108     *
4109     * @param context The Context the view is running in, through which it can
4110     *        access the current theme, resources, etc.
4111     * @param attrs The attributes of the XML tag that is inflating the view.
4112     * @param defStyleAttr An attribute in the current theme that contains a
4113     *        reference to a style resource that supplies default values for
4114     *        the view. Can be 0 to not look for defaults.
4115     * @param defStyleRes A resource identifier of a style resource that
4116     *        supplies default values for the view, used only if
4117     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4118     *        to not look for defaults.
4119     * @see #View(Context, AttributeSet, int)
4120     */
4121    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4122        this(context);
4123
4124        final TypedArray a = context.obtainStyledAttributes(
4125                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4126
4127        if (mDebugViewAttributes) {
4128            saveAttributeData(attrs, a);
4129        }
4130
4131        Drawable background = null;
4132
4133        int leftPadding = -1;
4134        int topPadding = -1;
4135        int rightPadding = -1;
4136        int bottomPadding = -1;
4137        int startPadding = UNDEFINED_PADDING;
4138        int endPadding = UNDEFINED_PADDING;
4139
4140        int padding = -1;
4141
4142        int viewFlagValues = 0;
4143        int viewFlagMasks = 0;
4144
4145        boolean setScrollContainer = false;
4146
4147        int x = 0;
4148        int y = 0;
4149
4150        float tx = 0;
4151        float ty = 0;
4152        float tz = 0;
4153        float elevation = 0;
4154        float rotation = 0;
4155        float rotationX = 0;
4156        float rotationY = 0;
4157        float sx = 1f;
4158        float sy = 1f;
4159        boolean transformSet = false;
4160
4161        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4162        int overScrollMode = mOverScrollMode;
4163        boolean initializeScrollbars = false;
4164        boolean initializeScrollIndicators = false;
4165
4166        boolean startPaddingDefined = false;
4167        boolean endPaddingDefined = false;
4168        boolean leftPaddingDefined = false;
4169        boolean rightPaddingDefined = false;
4170
4171        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4172
4173        final int N = a.getIndexCount();
4174        for (int i = 0; i < N; i++) {
4175            int attr = a.getIndex(i);
4176            switch (attr) {
4177                case com.android.internal.R.styleable.View_background:
4178                    background = a.getDrawable(attr);
4179                    break;
4180                case com.android.internal.R.styleable.View_padding:
4181                    padding = a.getDimensionPixelSize(attr, -1);
4182                    mUserPaddingLeftInitial = padding;
4183                    mUserPaddingRightInitial = padding;
4184                    leftPaddingDefined = true;
4185                    rightPaddingDefined = true;
4186                    break;
4187                 case com.android.internal.R.styleable.View_paddingLeft:
4188                    leftPadding = a.getDimensionPixelSize(attr, -1);
4189                    mUserPaddingLeftInitial = leftPadding;
4190                    leftPaddingDefined = true;
4191                    break;
4192                case com.android.internal.R.styleable.View_paddingTop:
4193                    topPadding = a.getDimensionPixelSize(attr, -1);
4194                    break;
4195                case com.android.internal.R.styleable.View_paddingRight:
4196                    rightPadding = a.getDimensionPixelSize(attr, -1);
4197                    mUserPaddingRightInitial = rightPadding;
4198                    rightPaddingDefined = true;
4199                    break;
4200                case com.android.internal.R.styleable.View_paddingBottom:
4201                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4202                    break;
4203                case com.android.internal.R.styleable.View_paddingStart:
4204                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4205                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4206                    break;
4207                case com.android.internal.R.styleable.View_paddingEnd:
4208                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4209                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4210                    break;
4211                case com.android.internal.R.styleable.View_scrollX:
4212                    x = a.getDimensionPixelOffset(attr, 0);
4213                    break;
4214                case com.android.internal.R.styleable.View_scrollY:
4215                    y = a.getDimensionPixelOffset(attr, 0);
4216                    break;
4217                case com.android.internal.R.styleable.View_alpha:
4218                    setAlpha(a.getFloat(attr, 1f));
4219                    break;
4220                case com.android.internal.R.styleable.View_transformPivotX:
4221                    setPivotX(a.getDimension(attr, 0));
4222                    break;
4223                case com.android.internal.R.styleable.View_transformPivotY:
4224                    setPivotY(a.getDimension(attr, 0));
4225                    break;
4226                case com.android.internal.R.styleable.View_translationX:
4227                    tx = a.getDimension(attr, 0);
4228                    transformSet = true;
4229                    break;
4230                case com.android.internal.R.styleable.View_translationY:
4231                    ty = a.getDimension(attr, 0);
4232                    transformSet = true;
4233                    break;
4234                case com.android.internal.R.styleable.View_translationZ:
4235                    tz = a.getDimension(attr, 0);
4236                    transformSet = true;
4237                    break;
4238                case com.android.internal.R.styleable.View_elevation:
4239                    elevation = a.getDimension(attr, 0);
4240                    transformSet = true;
4241                    break;
4242                case com.android.internal.R.styleable.View_rotation:
4243                    rotation = a.getFloat(attr, 0);
4244                    transformSet = true;
4245                    break;
4246                case com.android.internal.R.styleable.View_rotationX:
4247                    rotationX = a.getFloat(attr, 0);
4248                    transformSet = true;
4249                    break;
4250                case com.android.internal.R.styleable.View_rotationY:
4251                    rotationY = a.getFloat(attr, 0);
4252                    transformSet = true;
4253                    break;
4254                case com.android.internal.R.styleable.View_scaleX:
4255                    sx = a.getFloat(attr, 1f);
4256                    transformSet = true;
4257                    break;
4258                case com.android.internal.R.styleable.View_scaleY:
4259                    sy = a.getFloat(attr, 1f);
4260                    transformSet = true;
4261                    break;
4262                case com.android.internal.R.styleable.View_id:
4263                    mID = a.getResourceId(attr, NO_ID);
4264                    break;
4265                case com.android.internal.R.styleable.View_tag:
4266                    mTag = a.getText(attr);
4267                    break;
4268                case com.android.internal.R.styleable.View_fitsSystemWindows:
4269                    if (a.getBoolean(attr, false)) {
4270                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4271                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4272                    }
4273                    break;
4274                case com.android.internal.R.styleable.View_focusable:
4275                    if (a.getBoolean(attr, false)) {
4276                        viewFlagValues |= FOCUSABLE;
4277                        viewFlagMasks |= FOCUSABLE_MASK;
4278                    }
4279                    break;
4280                case com.android.internal.R.styleable.View_focusableInTouchMode:
4281                    if (a.getBoolean(attr, false)) {
4282                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4283                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4284                    }
4285                    break;
4286                case com.android.internal.R.styleable.View_clickable:
4287                    if (a.getBoolean(attr, false)) {
4288                        viewFlagValues |= CLICKABLE;
4289                        viewFlagMasks |= CLICKABLE;
4290                    }
4291                    break;
4292                case com.android.internal.R.styleable.View_longClickable:
4293                    if (a.getBoolean(attr, false)) {
4294                        viewFlagValues |= LONG_CLICKABLE;
4295                        viewFlagMasks |= LONG_CLICKABLE;
4296                    }
4297                    break;
4298                case com.android.internal.R.styleable.View_contextClickable:
4299                    if (a.getBoolean(attr, false)) {
4300                        viewFlagValues |= CONTEXT_CLICKABLE;
4301                        viewFlagMasks |= CONTEXT_CLICKABLE;
4302                    }
4303                    break;
4304                case com.android.internal.R.styleable.View_saveEnabled:
4305                    if (!a.getBoolean(attr, true)) {
4306                        viewFlagValues |= SAVE_DISABLED;
4307                        viewFlagMasks |= SAVE_DISABLED_MASK;
4308                    }
4309                    break;
4310                case com.android.internal.R.styleable.View_duplicateParentState:
4311                    if (a.getBoolean(attr, false)) {
4312                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4313                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4314                    }
4315                    break;
4316                case com.android.internal.R.styleable.View_visibility:
4317                    final int visibility = a.getInt(attr, 0);
4318                    if (visibility != 0) {
4319                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4320                        viewFlagMasks |= VISIBILITY_MASK;
4321                    }
4322                    break;
4323                case com.android.internal.R.styleable.View_layoutDirection:
4324                    // Clear any layout direction flags (included resolved bits) already set
4325                    mPrivateFlags2 &=
4326                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4327                    // Set the layout direction flags depending on the value of the attribute
4328                    final int layoutDirection = a.getInt(attr, -1);
4329                    final int value = (layoutDirection != -1) ?
4330                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4331                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4332                    break;
4333                case com.android.internal.R.styleable.View_drawingCacheQuality:
4334                    final int cacheQuality = a.getInt(attr, 0);
4335                    if (cacheQuality != 0) {
4336                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4337                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4338                    }
4339                    break;
4340                case com.android.internal.R.styleable.View_contentDescription:
4341                    setContentDescription(a.getString(attr));
4342                    break;
4343                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4344                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4345                    break;
4346                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4347                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4348                    break;
4349                case com.android.internal.R.styleable.View_labelFor:
4350                    setLabelFor(a.getResourceId(attr, NO_ID));
4351                    break;
4352                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4353                    if (!a.getBoolean(attr, true)) {
4354                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4355                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4356                    }
4357                    break;
4358                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4359                    if (!a.getBoolean(attr, true)) {
4360                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4361                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4362                    }
4363                    break;
4364                case R.styleable.View_scrollbars:
4365                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4366                    if (scrollbars != SCROLLBARS_NONE) {
4367                        viewFlagValues |= scrollbars;
4368                        viewFlagMasks |= SCROLLBARS_MASK;
4369                        initializeScrollbars = true;
4370                    }
4371                    break;
4372                //noinspection deprecation
4373                case R.styleable.View_fadingEdge:
4374                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4375                        // Ignore the attribute starting with ICS
4376                        break;
4377                    }
4378                    // With builds < ICS, fall through and apply fading edges
4379                case R.styleable.View_requiresFadingEdge:
4380                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4381                    if (fadingEdge != FADING_EDGE_NONE) {
4382                        viewFlagValues |= fadingEdge;
4383                        viewFlagMasks |= FADING_EDGE_MASK;
4384                        initializeFadingEdgeInternal(a);
4385                    }
4386                    break;
4387                case R.styleable.View_scrollbarStyle:
4388                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4389                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4390                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4391                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4392                    }
4393                    break;
4394                case R.styleable.View_isScrollContainer:
4395                    setScrollContainer = true;
4396                    if (a.getBoolean(attr, false)) {
4397                        setScrollContainer(true);
4398                    }
4399                    break;
4400                case com.android.internal.R.styleable.View_keepScreenOn:
4401                    if (a.getBoolean(attr, false)) {
4402                        viewFlagValues |= KEEP_SCREEN_ON;
4403                        viewFlagMasks |= KEEP_SCREEN_ON;
4404                    }
4405                    break;
4406                case R.styleable.View_filterTouchesWhenObscured:
4407                    if (a.getBoolean(attr, false)) {
4408                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4409                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4410                    }
4411                    break;
4412                case R.styleable.View_nextFocusLeft:
4413                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4414                    break;
4415                case R.styleable.View_nextFocusRight:
4416                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4417                    break;
4418                case R.styleable.View_nextFocusUp:
4419                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4420                    break;
4421                case R.styleable.View_nextFocusDown:
4422                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4423                    break;
4424                case R.styleable.View_nextFocusForward:
4425                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4426                    break;
4427                case R.styleable.View_minWidth:
4428                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4429                    break;
4430                case R.styleable.View_minHeight:
4431                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4432                    break;
4433                case R.styleable.View_onClick:
4434                    if (context.isRestricted()) {
4435                        throw new IllegalStateException("The android:onClick attribute cannot "
4436                                + "be used within a restricted context");
4437                    }
4438
4439                    final String handlerName = a.getString(attr);
4440                    if (handlerName != null) {
4441                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4442                    }
4443                    break;
4444                case R.styleable.View_overScrollMode:
4445                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4446                    break;
4447                case R.styleable.View_verticalScrollbarPosition:
4448                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4449                    break;
4450                case R.styleable.View_layerType:
4451                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4452                    break;
4453                case R.styleable.View_textDirection:
4454                    // Clear any text direction flag already set
4455                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4456                    // Set the text direction flags depending on the value of the attribute
4457                    final int textDirection = a.getInt(attr, -1);
4458                    if (textDirection != -1) {
4459                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4460                    }
4461                    break;
4462                case R.styleable.View_textAlignment:
4463                    // Clear any text alignment flag already set
4464                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4465                    // Set the text alignment flag depending on the value of the attribute
4466                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4467                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4468                    break;
4469                case R.styleable.View_importantForAccessibility:
4470                    setImportantForAccessibility(a.getInt(attr,
4471                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4472                    break;
4473                case R.styleable.View_accessibilityLiveRegion:
4474                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4475                    break;
4476                case R.styleable.View_transitionName:
4477                    setTransitionName(a.getString(attr));
4478                    break;
4479                case R.styleable.View_nestedScrollingEnabled:
4480                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4481                    break;
4482                case R.styleable.View_stateListAnimator:
4483                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4484                            a.getResourceId(attr, 0)));
4485                    break;
4486                case R.styleable.View_backgroundTint:
4487                    // This will get applied later during setBackground().
4488                    if (mBackgroundTint == null) {
4489                        mBackgroundTint = new TintInfo();
4490                    }
4491                    mBackgroundTint.mTintList = a.getColorStateList(
4492                            R.styleable.View_backgroundTint);
4493                    mBackgroundTint.mHasTintList = true;
4494                    break;
4495                case R.styleable.View_backgroundTintMode:
4496                    // This will get applied later during setBackground().
4497                    if (mBackgroundTint == null) {
4498                        mBackgroundTint = new TintInfo();
4499                    }
4500                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4501                            R.styleable.View_backgroundTintMode, -1), null);
4502                    mBackgroundTint.mHasTintMode = true;
4503                    break;
4504                case R.styleable.View_outlineProvider:
4505                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4506                            PROVIDER_BACKGROUND));
4507                    break;
4508                case R.styleable.View_foreground:
4509                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4510                        setForeground(a.getDrawable(attr));
4511                    }
4512                    break;
4513                case R.styleable.View_foregroundGravity:
4514                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4515                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4516                    }
4517                    break;
4518                case R.styleable.View_foregroundTintMode:
4519                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4520                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4521                    }
4522                    break;
4523                case R.styleable.View_foregroundTint:
4524                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4525                        setForegroundTintList(a.getColorStateList(attr));
4526                    }
4527                    break;
4528                case R.styleable.View_foregroundInsidePadding:
4529                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4530                        if (mForegroundInfo == null) {
4531                            mForegroundInfo = new ForegroundInfo();
4532                        }
4533                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4534                                mForegroundInfo.mInsidePadding);
4535                    }
4536                    break;
4537                case R.styleable.View_scrollIndicators:
4538                    final int scrollIndicators =
4539                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4540                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4541                    if (scrollIndicators != 0) {
4542                        mPrivateFlags3 |= scrollIndicators;
4543                        initializeScrollIndicators = true;
4544                    }
4545                    break;
4546                case R.styleable.View_pointerIcon:
4547                    final int resourceId = a.getResourceId(attr, 0);
4548                    if (resourceId != 0) {
4549                        setPointerIcon(PointerIcon.load(
4550                                context.getResources(), resourceId));
4551                    } else {
4552                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4553                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4554                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
4555                        }
4556                    }
4557                    break;
4558                case R.styleable.View_forceHasOverlappingRendering:
4559                    if (a.peekValue(attr) != null) {
4560                        forceHasOverlappingRendering(a.getBoolean(attr, true));
4561                    }
4562                    break;
4563
4564            }
4565        }
4566
4567        setOverScrollMode(overScrollMode);
4568
4569        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4570        // the resolved layout direction). Those cached values will be used later during padding
4571        // resolution.
4572        mUserPaddingStart = startPadding;
4573        mUserPaddingEnd = endPadding;
4574
4575        if (background != null) {
4576            setBackground(background);
4577        }
4578
4579        // setBackground above will record that padding is currently provided by the background.
4580        // If we have padding specified via xml, record that here instead and use it.
4581        mLeftPaddingDefined = leftPaddingDefined;
4582        mRightPaddingDefined = rightPaddingDefined;
4583
4584        if (padding >= 0) {
4585            leftPadding = padding;
4586            topPadding = padding;
4587            rightPadding = padding;
4588            bottomPadding = padding;
4589            mUserPaddingLeftInitial = padding;
4590            mUserPaddingRightInitial = padding;
4591        }
4592
4593        if (isRtlCompatibilityMode()) {
4594            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4595            // left / right padding are used if defined (meaning here nothing to do). If they are not
4596            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4597            // start / end and resolve them as left / right (layout direction is not taken into account).
4598            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4599            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4600            // defined.
4601            if (!mLeftPaddingDefined && startPaddingDefined) {
4602                leftPadding = startPadding;
4603            }
4604            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4605            if (!mRightPaddingDefined && endPaddingDefined) {
4606                rightPadding = endPadding;
4607            }
4608            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4609        } else {
4610            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4611            // values defined. Otherwise, left /right values are used.
4612            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4613            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4614            // defined.
4615            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4616
4617            if (mLeftPaddingDefined && !hasRelativePadding) {
4618                mUserPaddingLeftInitial = leftPadding;
4619            }
4620            if (mRightPaddingDefined && !hasRelativePadding) {
4621                mUserPaddingRightInitial = rightPadding;
4622            }
4623        }
4624
4625        internalSetPadding(
4626                mUserPaddingLeftInitial,
4627                topPadding >= 0 ? topPadding : mPaddingTop,
4628                mUserPaddingRightInitial,
4629                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4630
4631        if (viewFlagMasks != 0) {
4632            setFlags(viewFlagValues, viewFlagMasks);
4633        }
4634
4635        if (initializeScrollbars) {
4636            initializeScrollbarsInternal(a);
4637        }
4638
4639        if (initializeScrollIndicators) {
4640            initializeScrollIndicatorsInternal();
4641        }
4642
4643        a.recycle();
4644
4645        // Needs to be called after mViewFlags is set
4646        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4647            recomputePadding();
4648        }
4649
4650        if (x != 0 || y != 0) {
4651            scrollTo(x, y);
4652        }
4653
4654        if (transformSet) {
4655            setTranslationX(tx);
4656            setTranslationY(ty);
4657            setTranslationZ(tz);
4658            setElevation(elevation);
4659            setRotation(rotation);
4660            setRotationX(rotationX);
4661            setRotationY(rotationY);
4662            setScaleX(sx);
4663            setScaleY(sy);
4664        }
4665
4666        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4667            setScrollContainer(true);
4668        }
4669
4670        computeOpaqueFlags();
4671    }
4672
4673    /**
4674     * An implementation of OnClickListener that attempts to lazily load a
4675     * named click handling method from a parent or ancestor context.
4676     */
4677    private static class DeclaredOnClickListener implements OnClickListener {
4678        private final View mHostView;
4679        private final String mMethodName;
4680
4681        private Method mResolvedMethod;
4682        private Context mResolvedContext;
4683
4684        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4685            mHostView = hostView;
4686            mMethodName = methodName;
4687        }
4688
4689        @Override
4690        public void onClick(@NonNull View v) {
4691            if (mResolvedMethod == null) {
4692                resolveMethod(mHostView.getContext(), mMethodName);
4693            }
4694
4695            try {
4696                mResolvedMethod.invoke(mResolvedContext, v);
4697            } catch (IllegalAccessException e) {
4698                throw new IllegalStateException(
4699                        "Could not execute non-public method for android:onClick", e);
4700            } catch (InvocationTargetException e) {
4701                throw new IllegalStateException(
4702                        "Could not execute method for android:onClick", e);
4703            }
4704        }
4705
4706        @NonNull
4707        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4708            while (context != null) {
4709                try {
4710                    if (!context.isRestricted()) {
4711                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4712                        if (method != null) {
4713                            mResolvedMethod = method;
4714                            mResolvedContext = context;
4715                            return;
4716                        }
4717                    }
4718                } catch (NoSuchMethodException e) {
4719                    // Failed to find method, keep searching up the hierarchy.
4720                }
4721
4722                if (context instanceof ContextWrapper) {
4723                    context = ((ContextWrapper) context).getBaseContext();
4724                } else {
4725                    // Can't search up the hierarchy, null out and fail.
4726                    context = null;
4727                }
4728            }
4729
4730            final int id = mHostView.getId();
4731            final String idText = id == NO_ID ? "" : " with id '"
4732                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4733            throw new IllegalStateException("Could not find method " + mMethodName
4734                    + "(View) in a parent or ancestor Context for android:onClick "
4735                    + "attribute defined on view " + mHostView.getClass() + idText);
4736        }
4737    }
4738
4739    /**
4740     * Non-public constructor for use in testing
4741     */
4742    View() {
4743        mResources = null;
4744        mRenderNode = RenderNode.create(getClass().getName(), this);
4745    }
4746
4747    private static SparseArray<String> getAttributeMap() {
4748        if (mAttributeMap == null) {
4749            mAttributeMap = new SparseArray<>();
4750        }
4751        return mAttributeMap;
4752    }
4753
4754    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4755        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4756        final int indexCount = t.getIndexCount();
4757        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4758
4759        int i = 0;
4760
4761        // Store raw XML attributes.
4762        for (int j = 0; j < attrsCount; ++j) {
4763            attributes[i] = attrs.getAttributeName(j);
4764            attributes[i + 1] = attrs.getAttributeValue(j);
4765            i += 2;
4766        }
4767
4768        // Store resolved styleable attributes.
4769        final Resources res = t.getResources();
4770        final SparseArray<String> attributeMap = getAttributeMap();
4771        for (int j = 0; j < indexCount; ++j) {
4772            final int index = t.getIndex(j);
4773            if (!t.hasValueOrEmpty(index)) {
4774                // Value is undefined. Skip it.
4775                continue;
4776            }
4777
4778            final int resourceId = t.getResourceId(index, 0);
4779            if (resourceId == 0) {
4780                // Value is not a reference. Skip it.
4781                continue;
4782            }
4783
4784            String resourceName = attributeMap.get(resourceId);
4785            if (resourceName == null) {
4786                try {
4787                    resourceName = res.getResourceName(resourceId);
4788                } catch (Resources.NotFoundException e) {
4789                    resourceName = "0x" + Integer.toHexString(resourceId);
4790                }
4791                attributeMap.put(resourceId, resourceName);
4792            }
4793
4794            attributes[i] = resourceName;
4795            attributes[i + 1] = t.getString(index);
4796            i += 2;
4797        }
4798
4799        // Trim to fit contents.
4800        final String[] trimmed = new String[i];
4801        System.arraycopy(attributes, 0, trimmed, 0, i);
4802        mAttributes = trimmed;
4803    }
4804
4805    public String toString() {
4806        StringBuilder out = new StringBuilder(128);
4807        out.append(getClass().getName());
4808        out.append('{');
4809        out.append(Integer.toHexString(System.identityHashCode(this)));
4810        out.append(' ');
4811        switch (mViewFlags&VISIBILITY_MASK) {
4812            case VISIBLE: out.append('V'); break;
4813            case INVISIBLE: out.append('I'); break;
4814            case GONE: out.append('G'); break;
4815            default: out.append('.'); break;
4816        }
4817        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4818        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4819        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4820        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4821        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4822        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4823        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4824        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4825        out.append(' ');
4826        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4827        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4828        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4829        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4830            out.append('p');
4831        } else {
4832            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4833        }
4834        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4835        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4836        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4837        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4838        out.append(' ');
4839        out.append(mLeft);
4840        out.append(',');
4841        out.append(mTop);
4842        out.append('-');
4843        out.append(mRight);
4844        out.append(',');
4845        out.append(mBottom);
4846        final int id = getId();
4847        if (id != NO_ID) {
4848            out.append(" #");
4849            out.append(Integer.toHexString(id));
4850            final Resources r = mResources;
4851            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4852                try {
4853                    String pkgname;
4854                    switch (id&0xff000000) {
4855                        case 0x7f000000:
4856                            pkgname="app";
4857                            break;
4858                        case 0x01000000:
4859                            pkgname="android";
4860                            break;
4861                        default:
4862                            pkgname = r.getResourcePackageName(id);
4863                            break;
4864                    }
4865                    String typename = r.getResourceTypeName(id);
4866                    String entryname = r.getResourceEntryName(id);
4867                    out.append(" ");
4868                    out.append(pkgname);
4869                    out.append(":");
4870                    out.append(typename);
4871                    out.append("/");
4872                    out.append(entryname);
4873                } catch (Resources.NotFoundException e) {
4874                }
4875            }
4876        }
4877        out.append("}");
4878        return out.toString();
4879    }
4880
4881    /**
4882     * <p>
4883     * Initializes the fading edges from a given set of styled attributes. This
4884     * method should be called by subclasses that need fading edges and when an
4885     * instance of these subclasses is created programmatically rather than
4886     * being inflated from XML. This method is automatically called when the XML
4887     * is inflated.
4888     * </p>
4889     *
4890     * @param a the styled attributes set to initialize the fading edges from
4891     *
4892     * @removed
4893     */
4894    protected void initializeFadingEdge(TypedArray a) {
4895        // This method probably shouldn't have been included in the SDK to begin with.
4896        // It relies on 'a' having been initialized using an attribute filter array that is
4897        // not publicly available to the SDK. The old method has been renamed
4898        // to initializeFadingEdgeInternal and hidden for framework use only;
4899        // this one initializes using defaults to make it safe to call for apps.
4900
4901        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4902
4903        initializeFadingEdgeInternal(arr);
4904
4905        arr.recycle();
4906    }
4907
4908    /**
4909     * <p>
4910     * Initializes the fading edges from a given set of styled attributes. This
4911     * method should be called by subclasses that need fading edges and when an
4912     * instance of these subclasses is created programmatically rather than
4913     * being inflated from XML. This method is automatically called when the XML
4914     * is inflated.
4915     * </p>
4916     *
4917     * @param a the styled attributes set to initialize the fading edges from
4918     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4919     */
4920    protected void initializeFadingEdgeInternal(TypedArray a) {
4921        initScrollCache();
4922
4923        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4924                R.styleable.View_fadingEdgeLength,
4925                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4926    }
4927
4928    /**
4929     * Returns the size of the vertical faded edges used to indicate that more
4930     * content in this view is visible.
4931     *
4932     * @return The size in pixels of the vertical faded edge or 0 if vertical
4933     *         faded edges are not enabled for this view.
4934     * @attr ref android.R.styleable#View_fadingEdgeLength
4935     */
4936    public int getVerticalFadingEdgeLength() {
4937        if (isVerticalFadingEdgeEnabled()) {
4938            ScrollabilityCache cache = mScrollCache;
4939            if (cache != null) {
4940                return cache.fadingEdgeLength;
4941            }
4942        }
4943        return 0;
4944    }
4945
4946    /**
4947     * Set the size of the faded edge used to indicate that more content in this
4948     * view is available.  Will not change whether the fading edge is enabled; use
4949     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4950     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4951     * for the vertical or horizontal fading edges.
4952     *
4953     * @param length The size in pixels of the faded edge used to indicate that more
4954     *        content in this view is visible.
4955     */
4956    public void setFadingEdgeLength(int length) {
4957        initScrollCache();
4958        mScrollCache.fadingEdgeLength = length;
4959    }
4960
4961    /**
4962     * Returns the size of the horizontal faded edges used to indicate that more
4963     * content in this view is visible.
4964     *
4965     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4966     *         faded edges are not enabled for this view.
4967     * @attr ref android.R.styleable#View_fadingEdgeLength
4968     */
4969    public int getHorizontalFadingEdgeLength() {
4970        if (isHorizontalFadingEdgeEnabled()) {
4971            ScrollabilityCache cache = mScrollCache;
4972            if (cache != null) {
4973                return cache.fadingEdgeLength;
4974            }
4975        }
4976        return 0;
4977    }
4978
4979    /**
4980     * Returns the width of the vertical scrollbar.
4981     *
4982     * @return The width in pixels of the vertical scrollbar or 0 if there
4983     *         is no vertical scrollbar.
4984     */
4985    public int getVerticalScrollbarWidth() {
4986        ScrollabilityCache cache = mScrollCache;
4987        if (cache != null) {
4988            ScrollBarDrawable scrollBar = cache.scrollBar;
4989            if (scrollBar != null) {
4990                int size = scrollBar.getSize(true);
4991                if (size <= 0) {
4992                    size = cache.scrollBarSize;
4993                }
4994                return size;
4995            }
4996            return 0;
4997        }
4998        return 0;
4999    }
5000
5001    /**
5002     * Returns the height of the horizontal scrollbar.
5003     *
5004     * @return The height in pixels of the horizontal scrollbar or 0 if
5005     *         there is no horizontal scrollbar.
5006     */
5007    protected int getHorizontalScrollbarHeight() {
5008        ScrollabilityCache cache = mScrollCache;
5009        if (cache != null) {
5010            ScrollBarDrawable scrollBar = cache.scrollBar;
5011            if (scrollBar != null) {
5012                int size = scrollBar.getSize(false);
5013                if (size <= 0) {
5014                    size = cache.scrollBarSize;
5015                }
5016                return size;
5017            }
5018            return 0;
5019        }
5020        return 0;
5021    }
5022
5023    /**
5024     * <p>
5025     * Initializes the scrollbars from a given set of styled attributes. This
5026     * method should be called by subclasses that need scrollbars and when an
5027     * instance of these subclasses is created programmatically rather than
5028     * being inflated from XML. This method is automatically called when the XML
5029     * is inflated.
5030     * </p>
5031     *
5032     * @param a the styled attributes set to initialize the scrollbars from
5033     *
5034     * @removed
5035     */
5036    protected void initializeScrollbars(TypedArray a) {
5037        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5038        // using the View filter array which is not available to the SDK. As such, internal
5039        // framework usage now uses initializeScrollbarsInternal and we grab a default
5040        // TypedArray with the right filter instead here.
5041        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5042
5043        initializeScrollbarsInternal(arr);
5044
5045        // We ignored the method parameter. Recycle the one we actually did use.
5046        arr.recycle();
5047    }
5048
5049    /**
5050     * <p>
5051     * Initializes the scrollbars from a given set of styled attributes. This
5052     * method should be called by subclasses that need scrollbars and when an
5053     * instance of these subclasses is created programmatically rather than
5054     * being inflated from XML. This method is automatically called when the XML
5055     * is inflated.
5056     * </p>
5057     *
5058     * @param a the styled attributes set to initialize the scrollbars from
5059     * @hide
5060     */
5061    protected void initializeScrollbarsInternal(TypedArray a) {
5062        initScrollCache();
5063
5064        final ScrollabilityCache scrollabilityCache = mScrollCache;
5065
5066        if (scrollabilityCache.scrollBar == null) {
5067            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5068            scrollabilityCache.scrollBar.setState(getDrawableState());
5069            scrollabilityCache.scrollBar.setCallback(this);
5070        }
5071
5072        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5073
5074        if (!fadeScrollbars) {
5075            scrollabilityCache.state = ScrollabilityCache.ON;
5076        }
5077        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5078
5079
5080        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5081                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5082                        .getScrollBarFadeDuration());
5083        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5084                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5085                ViewConfiguration.getScrollDefaultDelay());
5086
5087
5088        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5089                com.android.internal.R.styleable.View_scrollbarSize,
5090                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5091
5092        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5093        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5094
5095        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5096        if (thumb != null) {
5097            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5098        }
5099
5100        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5101                false);
5102        if (alwaysDraw) {
5103            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5104        }
5105
5106        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5107        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5108
5109        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5110        if (thumb != null) {
5111            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5112        }
5113
5114        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5115                false);
5116        if (alwaysDraw) {
5117            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5118        }
5119
5120        // Apply layout direction to the new Drawables if needed
5121        final int layoutDirection = getLayoutDirection();
5122        if (track != null) {
5123            track.setLayoutDirection(layoutDirection);
5124        }
5125        if (thumb != null) {
5126            thumb.setLayoutDirection(layoutDirection);
5127        }
5128
5129        // Re-apply user/background padding so that scrollbar(s) get added
5130        resolvePadding();
5131    }
5132
5133    private void initializeScrollIndicatorsInternal() {
5134        // Some day maybe we'll break this into top/left/start/etc. and let the
5135        // client control it. Until then, you can have any scroll indicator you
5136        // want as long as it's a 1dp foreground-colored rectangle.
5137        if (mScrollIndicatorDrawable == null) {
5138            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5139        }
5140    }
5141
5142    /**
5143     * <p>
5144     * Initalizes the scrollability cache if necessary.
5145     * </p>
5146     */
5147    private void initScrollCache() {
5148        if (mScrollCache == null) {
5149            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5150        }
5151    }
5152
5153    private ScrollabilityCache getScrollCache() {
5154        initScrollCache();
5155        return mScrollCache;
5156    }
5157
5158    /**
5159     * Set the position of the vertical scroll bar. Should be one of
5160     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5161     * {@link #SCROLLBAR_POSITION_RIGHT}.
5162     *
5163     * @param position Where the vertical scroll bar should be positioned.
5164     */
5165    public void setVerticalScrollbarPosition(int position) {
5166        if (mVerticalScrollbarPosition != position) {
5167            mVerticalScrollbarPosition = position;
5168            computeOpaqueFlags();
5169            resolvePadding();
5170        }
5171    }
5172
5173    /**
5174     * @return The position where the vertical scroll bar will show, if applicable.
5175     * @see #setVerticalScrollbarPosition(int)
5176     */
5177    public int getVerticalScrollbarPosition() {
5178        return mVerticalScrollbarPosition;
5179    }
5180
5181    boolean isOnScrollbar(float x, float y) {
5182        if (mScrollCache == null) {
5183            return false;
5184        }
5185        x += getScrollX();
5186        y += getScrollY();
5187        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5188            final Rect bounds = mScrollCache.mScrollBarBounds;
5189            getVerticalScrollBarBounds(bounds);
5190            if (bounds.contains((int)x, (int)y)) {
5191                return true;
5192            }
5193        }
5194        if (isHorizontalScrollBarEnabled()) {
5195            final Rect bounds = mScrollCache.mScrollBarBounds;
5196            getHorizontalScrollBarBounds(bounds);
5197            if (bounds.contains((int)x, (int)y)) {
5198                return true;
5199            }
5200        }
5201        return false;
5202    }
5203
5204    boolean isOnScrollbarThumb(float x, float y) {
5205        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5206    }
5207
5208    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5209        if (mScrollCache == null) {
5210            return false;
5211        }
5212        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5213            x += getScrollX();
5214            y += getScrollY();
5215            final Rect bounds = mScrollCache.mScrollBarBounds;
5216            getVerticalScrollBarBounds(bounds);
5217            final int range = computeVerticalScrollRange();
5218            final int offset = computeVerticalScrollOffset();
5219            final int extent = computeVerticalScrollExtent();
5220            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5221                    extent, range);
5222            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5223                    extent, range, offset);
5224            final int thumbTop = bounds.top + thumbOffset;
5225            if (x >= bounds.left && x <= bounds.right && y >= thumbTop
5226                    && y <= thumbTop + thumbLength) {
5227                return true;
5228            }
5229        }
5230        return false;
5231    }
5232
5233    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5234        if (mScrollCache == null) {
5235            return false;
5236        }
5237        if (isHorizontalScrollBarEnabled()) {
5238            x += getScrollX();
5239            y += getScrollY();
5240            final Rect bounds = mScrollCache.mScrollBarBounds;
5241            getHorizontalScrollBarBounds(bounds);
5242            final int range = computeHorizontalScrollRange();
5243            final int offset = computeHorizontalScrollOffset();
5244            final int extent = computeHorizontalScrollExtent();
5245            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5246                    extent, range);
5247            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5248                    extent, range, offset);
5249            final int thumbLeft = bounds.left + thumbOffset;
5250            if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
5251                    && y <= bounds.bottom) {
5252                return true;
5253            }
5254        }
5255        return false;
5256    }
5257
5258    boolean isDraggingScrollBar() {
5259        return mScrollCache != null
5260                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5261    }
5262
5263    /**
5264     * Sets the state of all scroll indicators.
5265     * <p>
5266     * See {@link #setScrollIndicators(int, int)} for usage information.
5267     *
5268     * @param indicators a bitmask of indicators that should be enabled, or
5269     *                   {@code 0} to disable all indicators
5270     * @see #setScrollIndicators(int, int)
5271     * @see #getScrollIndicators()
5272     * @attr ref android.R.styleable#View_scrollIndicators
5273     */
5274    public void setScrollIndicators(@ScrollIndicators int indicators) {
5275        setScrollIndicators(indicators,
5276                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5277    }
5278
5279    /**
5280     * Sets the state of the scroll indicators specified by the mask. To change
5281     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5282     * <p>
5283     * When a scroll indicator is enabled, it will be displayed if the view
5284     * can scroll in the direction of the indicator.
5285     * <p>
5286     * Multiple indicator types may be enabled or disabled by passing the
5287     * logical OR of the desired types. If multiple types are specified, they
5288     * will all be set to the same enabled state.
5289     * <p>
5290     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5291     *
5292     * @param indicators the indicator direction, or the logical OR of multiple
5293     *             indicator directions. One or more of:
5294     *             <ul>
5295     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5296     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5297     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5298     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5299     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5300     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5301     *             </ul>
5302     * @see #setScrollIndicators(int)
5303     * @see #getScrollIndicators()
5304     * @attr ref android.R.styleable#View_scrollIndicators
5305     */
5306    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5307        // Shift and sanitize mask.
5308        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5309        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5310
5311        // Shift and mask indicators.
5312        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5313        indicators &= mask;
5314
5315        // Merge with non-masked flags.
5316        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5317
5318        if (mPrivateFlags3 != updatedFlags) {
5319            mPrivateFlags3 = updatedFlags;
5320
5321            if (indicators != 0) {
5322                initializeScrollIndicatorsInternal();
5323            }
5324            invalidate();
5325        }
5326    }
5327
5328    /**
5329     * Returns a bitmask representing the enabled scroll indicators.
5330     * <p>
5331     * For example, if the top and left scroll indicators are enabled and all
5332     * other indicators are disabled, the return value will be
5333     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5334     * <p>
5335     * To check whether the bottom scroll indicator is enabled, use the value
5336     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5337     *
5338     * @return a bitmask representing the enabled scroll indicators
5339     */
5340    @ScrollIndicators
5341    public int getScrollIndicators() {
5342        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5343                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5344    }
5345
5346    ListenerInfo getListenerInfo() {
5347        if (mListenerInfo != null) {
5348            return mListenerInfo;
5349        }
5350        mListenerInfo = new ListenerInfo();
5351        return mListenerInfo;
5352    }
5353
5354    /**
5355     * Register a callback to be invoked when the scroll X or Y positions of
5356     * this view change.
5357     * <p>
5358     * <b>Note:</b> Some views handle scrolling independently from View and may
5359     * have their own separate listeners for scroll-type events. For example,
5360     * {@link android.widget.ListView ListView} allows clients to register an
5361     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5362     * to listen for changes in list scroll position.
5363     *
5364     * @param l The listener to notify when the scroll X or Y position changes.
5365     * @see android.view.View#getScrollX()
5366     * @see android.view.View#getScrollY()
5367     */
5368    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5369        getListenerInfo().mOnScrollChangeListener = l;
5370    }
5371
5372    /**
5373     * Register a callback to be invoked when focus of this view changed.
5374     *
5375     * @param l The callback that will run.
5376     */
5377    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5378        getListenerInfo().mOnFocusChangeListener = l;
5379    }
5380
5381    /**
5382     * Add a listener that will be called when the bounds of the view change due to
5383     * layout processing.
5384     *
5385     * @param listener The listener that will be called when layout bounds change.
5386     */
5387    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5388        ListenerInfo li = getListenerInfo();
5389        if (li.mOnLayoutChangeListeners == null) {
5390            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5391        }
5392        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5393            li.mOnLayoutChangeListeners.add(listener);
5394        }
5395    }
5396
5397    /**
5398     * Remove a listener for layout changes.
5399     *
5400     * @param listener The listener for layout bounds change.
5401     */
5402    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5403        ListenerInfo li = mListenerInfo;
5404        if (li == null || li.mOnLayoutChangeListeners == null) {
5405            return;
5406        }
5407        li.mOnLayoutChangeListeners.remove(listener);
5408    }
5409
5410    /**
5411     * Add a listener for attach state changes.
5412     *
5413     * This listener will be called whenever this view is attached or detached
5414     * from a window. Remove the listener using
5415     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5416     *
5417     * @param listener Listener to attach
5418     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5419     */
5420    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5421        ListenerInfo li = getListenerInfo();
5422        if (li.mOnAttachStateChangeListeners == null) {
5423            li.mOnAttachStateChangeListeners
5424                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5425        }
5426        li.mOnAttachStateChangeListeners.add(listener);
5427    }
5428
5429    /**
5430     * Remove a listener for attach state changes. The listener will receive no further
5431     * notification of window attach/detach events.
5432     *
5433     * @param listener Listener to remove
5434     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5435     */
5436    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5437        ListenerInfo li = mListenerInfo;
5438        if (li == null || li.mOnAttachStateChangeListeners == null) {
5439            return;
5440        }
5441        li.mOnAttachStateChangeListeners.remove(listener);
5442    }
5443
5444    /**
5445     * Returns the focus-change callback registered for this view.
5446     *
5447     * @return The callback, or null if one is not registered.
5448     */
5449    public OnFocusChangeListener getOnFocusChangeListener() {
5450        ListenerInfo li = mListenerInfo;
5451        return li != null ? li.mOnFocusChangeListener : null;
5452    }
5453
5454    /**
5455     * Register a callback to be invoked when this view is clicked. If this view is not
5456     * clickable, it becomes clickable.
5457     *
5458     * @param l The callback that will run
5459     *
5460     * @see #setClickable(boolean)
5461     */
5462    public void setOnClickListener(@Nullable OnClickListener l) {
5463        if (!isClickable()) {
5464            setClickable(true);
5465        }
5466        getListenerInfo().mOnClickListener = l;
5467    }
5468
5469    /**
5470     * Return whether this view has an attached OnClickListener.  Returns
5471     * true if there is a listener, false if there is none.
5472     */
5473    public boolean hasOnClickListeners() {
5474        ListenerInfo li = mListenerInfo;
5475        return (li != null && li.mOnClickListener != null);
5476    }
5477
5478    /**
5479     * Register a callback to be invoked when this view is clicked and held. If this view is not
5480     * long clickable, it becomes long clickable.
5481     *
5482     * @param l The callback that will run
5483     *
5484     * @see #setLongClickable(boolean)
5485     */
5486    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5487        if (!isLongClickable()) {
5488            setLongClickable(true);
5489        }
5490        getListenerInfo().mOnLongClickListener = l;
5491    }
5492
5493    /**
5494     * Register a callback to be invoked when this view is context clicked. If the view is not
5495     * context clickable, it becomes context clickable.
5496     *
5497     * @param l The callback that will run
5498     * @see #setContextClickable(boolean)
5499     */
5500    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5501        if (!isContextClickable()) {
5502            setContextClickable(true);
5503        }
5504        getListenerInfo().mOnContextClickListener = l;
5505    }
5506
5507    /**
5508     * Register a callback to be invoked when the context menu for this view is
5509     * being built. If this view is not long clickable, it becomes long clickable.
5510     *
5511     * @param l The callback that will run
5512     *
5513     */
5514    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5515        if (!isLongClickable()) {
5516            setLongClickable(true);
5517        }
5518        getListenerInfo().mOnCreateContextMenuListener = l;
5519    }
5520
5521    /**
5522     * Set an observer to collect stats for each frame rendered for this view.
5523     *
5524     * @hide
5525     */
5526    public void addFrameMetricsListener(Window window,
5527            Window.OnFrameMetricsAvailableListener listener,
5528            Handler handler) {
5529        if (mAttachInfo != null) {
5530            if (mAttachInfo.mThreadedRenderer != null) {
5531                if (mFrameMetricsObservers == null) {
5532                    mFrameMetricsObservers = new ArrayList<>();
5533                }
5534
5535                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5536                        handler.getLooper(), listener);
5537                mFrameMetricsObservers.add(fmo);
5538                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
5539            } else {
5540                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5541            }
5542        } else {
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        }
5551    }
5552
5553    /**
5554     * Remove observer configured to collect frame stats for this view.
5555     *
5556     * @hide
5557     */
5558    public void removeFrameMetricsListener(
5559            Window.OnFrameMetricsAvailableListener listener) {
5560        ThreadedRenderer renderer = getThreadedRenderer();
5561        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
5562        if (fmo == null) {
5563            throw new IllegalArgumentException(
5564                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
5565        }
5566
5567        if (mFrameMetricsObservers != null) {
5568            mFrameMetricsObservers.remove(fmo);
5569            if (renderer != null) {
5570                renderer.removeFrameMetricsObserver(fmo);
5571            }
5572        }
5573    }
5574
5575    private void registerPendingFrameMetricsObservers() {
5576        if (mFrameMetricsObservers != null) {
5577            ThreadedRenderer renderer = getThreadedRenderer();
5578            if (renderer != null) {
5579                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
5580                    renderer.addFrameMetricsObserver(fmo);
5581                }
5582            } else {
5583                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5584            }
5585        }
5586    }
5587
5588    private FrameMetricsObserver findFrameMetricsObserver(
5589            Window.OnFrameMetricsAvailableListener listener) {
5590        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
5591            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
5592            if (observer.mListener == listener) {
5593                return observer;
5594            }
5595        }
5596
5597        return null;
5598    }
5599
5600    /**
5601     * Call this view's OnClickListener, if it is defined.  Performs all normal
5602     * actions associated with clicking: reporting accessibility event, playing
5603     * a sound, etc.
5604     *
5605     * @return True there was an assigned OnClickListener that was called, false
5606     *         otherwise is returned.
5607     */
5608    public boolean performClick() {
5609        final boolean result;
5610        final ListenerInfo li = mListenerInfo;
5611        if (li != null && li.mOnClickListener != null) {
5612            playSoundEffect(SoundEffectConstants.CLICK);
5613            li.mOnClickListener.onClick(this);
5614            result = true;
5615        } else {
5616            result = false;
5617        }
5618
5619        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5620        return result;
5621    }
5622
5623    /**
5624     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5625     * this only calls the listener, and does not do any associated clicking
5626     * actions like reporting an accessibility event.
5627     *
5628     * @return True there was an assigned OnClickListener that was called, false
5629     *         otherwise is returned.
5630     */
5631    public boolean callOnClick() {
5632        ListenerInfo li = mListenerInfo;
5633        if (li != null && li.mOnClickListener != null) {
5634            li.mOnClickListener.onClick(this);
5635            return true;
5636        }
5637        return false;
5638    }
5639
5640    /**
5641     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5642     * context menu if the OnLongClickListener did not consume the event.
5643     *
5644     * @return {@code true} if one of the above receivers consumed the event,
5645     *         {@code false} otherwise
5646     */
5647    public boolean performLongClick() {
5648        return performLongClickInternal(mLongClickX, mLongClickY);
5649    }
5650
5651    /**
5652     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5653     * context menu if the OnLongClickListener did not consume the event,
5654     * anchoring it to an (x,y) coordinate.
5655     *
5656     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5657     *          to disable anchoring
5658     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5659     *          to disable anchoring
5660     * @return {@code true} if one of the above receivers consumed the event,
5661     *         {@code false} otherwise
5662     */
5663    public boolean performLongClick(float x, float y) {
5664        mLongClickX = x;
5665        mLongClickY = y;
5666        final boolean handled = performLongClick();
5667        mLongClickX = Float.NaN;
5668        mLongClickY = Float.NaN;
5669        return handled;
5670    }
5671
5672    /**
5673     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5674     * context menu if the OnLongClickListener did not consume the event,
5675     * optionally anchoring it to an (x,y) coordinate.
5676     *
5677     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5678     *          to disable anchoring
5679     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5680     *          to disable anchoring
5681     * @return {@code true} if one of the above receivers consumed the event,
5682     *         {@code false} otherwise
5683     */
5684    private boolean performLongClickInternal(float x, float y) {
5685        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5686
5687        boolean handled = false;
5688        final ListenerInfo li = mListenerInfo;
5689        if (li != null && li.mOnLongClickListener != null) {
5690            handled = li.mOnLongClickListener.onLongClick(View.this);
5691        }
5692        if (!handled) {
5693            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5694            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5695        }
5696        if (handled) {
5697            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5698        }
5699        return handled;
5700    }
5701
5702    /**
5703     * Call this view's OnContextClickListener, if it is defined.
5704     *
5705     * @param x the x coordinate of the context click
5706     * @param y the y coordinate of the context click
5707     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5708     *         otherwise.
5709     */
5710    public boolean performContextClick(float x, float y) {
5711        return performContextClick();
5712    }
5713
5714    /**
5715     * Call this view's OnContextClickListener, if it is defined.
5716     *
5717     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5718     *         otherwise.
5719     */
5720    public boolean performContextClick() {
5721        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5722
5723        boolean handled = false;
5724        ListenerInfo li = mListenerInfo;
5725        if (li != null && li.mOnContextClickListener != null) {
5726            handled = li.mOnContextClickListener.onContextClick(View.this);
5727        }
5728        if (handled) {
5729            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5730        }
5731        return handled;
5732    }
5733
5734    /**
5735     * Performs button-related actions during a touch down event.
5736     *
5737     * @param event The event.
5738     * @return True if the down was consumed.
5739     *
5740     * @hide
5741     */
5742    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5743        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5744            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5745            showContextMenu(event.getX(), event.getY());
5746            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5747            return true;
5748        }
5749        return false;
5750    }
5751
5752    /**
5753     * Shows the context menu for this view.
5754     *
5755     * @return {@code true} if the context menu was shown, {@code false}
5756     *         otherwise
5757     * @see #showContextMenu(float, float)
5758     */
5759    public boolean showContextMenu() {
5760        return getParent().showContextMenuForChild(this);
5761    }
5762
5763    /**
5764     * Shows the context menu for this view anchored to the specified
5765     * view-relative coordinate.
5766     *
5767     * @param x the X coordinate in pixels relative to the view to which the
5768     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5769     * @param y the Y coordinate in pixels relative to the view to which the
5770     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5771     * @return {@code true} if the context menu was shown, {@code false}
5772     *         otherwise
5773     */
5774    public boolean showContextMenu(float x, float y) {
5775        return getParent().showContextMenuForChild(this, x, y);
5776    }
5777
5778    /**
5779     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5780     *
5781     * @param callback Callback that will control the lifecycle of the action mode
5782     * @return The new action mode if it is started, null otherwise
5783     *
5784     * @see ActionMode
5785     * @see #startActionMode(android.view.ActionMode.Callback, int)
5786     */
5787    public ActionMode startActionMode(ActionMode.Callback callback) {
5788        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5789    }
5790
5791    /**
5792     * Start an action mode with the given type.
5793     *
5794     * @param callback Callback that will control the lifecycle of the action mode
5795     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5796     * @return The new action mode if it is started, null otherwise
5797     *
5798     * @see ActionMode
5799     */
5800    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5801        ViewParent parent = getParent();
5802        if (parent == null) return null;
5803        try {
5804            return parent.startActionModeForChild(this, callback, type);
5805        } catch (AbstractMethodError ame) {
5806            // Older implementations of custom views might not implement this.
5807            return parent.startActionModeForChild(this, callback);
5808        }
5809    }
5810
5811    /**
5812     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5813     * Context, creating a unique View identifier to retrieve the result.
5814     *
5815     * @param intent The Intent to be started.
5816     * @param requestCode The request code to use.
5817     * @hide
5818     */
5819    public void startActivityForResult(Intent intent, int requestCode) {
5820        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5821        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5822    }
5823
5824    /**
5825     * If this View corresponds to the calling who, dispatches the activity result.
5826     * @param who The identifier for the targeted View to receive the result.
5827     * @param requestCode The integer request code originally supplied to
5828     *                    startActivityForResult(), allowing you to identify who this
5829     *                    result came from.
5830     * @param resultCode The integer result code returned by the child activity
5831     *                   through its setResult().
5832     * @param data An Intent, which can return result data to the caller
5833     *               (various data can be attached to Intent "extras").
5834     * @return {@code true} if the activity result was dispatched.
5835     * @hide
5836     */
5837    public boolean dispatchActivityResult(
5838            String who, int requestCode, int resultCode, Intent data) {
5839        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5840            onActivityResult(requestCode, resultCode, data);
5841            mStartActivityRequestWho = null;
5842            return true;
5843        }
5844        return false;
5845    }
5846
5847    /**
5848     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5849     *
5850     * @param requestCode The integer request code originally supplied to
5851     *                    startActivityForResult(), allowing you to identify who this
5852     *                    result came from.
5853     * @param resultCode The integer result code returned by the child activity
5854     *                   through its setResult().
5855     * @param data An Intent, which can return result data to the caller
5856     *               (various data can be attached to Intent "extras").
5857     * @hide
5858     */
5859    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5860        // Do nothing.
5861    }
5862
5863    /**
5864     * Register a callback to be invoked when a hardware key is pressed in this view.
5865     * Key presses in software input methods will generally not trigger the methods of
5866     * this listener.
5867     * @param l the key listener to attach to this view
5868     */
5869    public void setOnKeyListener(OnKeyListener l) {
5870        getListenerInfo().mOnKeyListener = l;
5871    }
5872
5873    /**
5874     * Register a callback to be invoked when a touch event is sent to this view.
5875     * @param l the touch listener to attach to this view
5876     */
5877    public void setOnTouchListener(OnTouchListener l) {
5878        getListenerInfo().mOnTouchListener = l;
5879    }
5880
5881    /**
5882     * Register a callback to be invoked when a generic motion event is sent to this view.
5883     * @param l the generic motion listener to attach to this view
5884     */
5885    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5886        getListenerInfo().mOnGenericMotionListener = l;
5887    }
5888
5889    /**
5890     * Register a callback to be invoked when a hover event is sent to this view.
5891     * @param l the hover listener to attach to this view
5892     */
5893    public void setOnHoverListener(OnHoverListener l) {
5894        getListenerInfo().mOnHoverListener = l;
5895    }
5896
5897    /**
5898     * Register a drag event listener callback object for this View. The parameter is
5899     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5900     * View, the system calls the
5901     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5902     * @param l An implementation of {@link android.view.View.OnDragListener}.
5903     */
5904    public void setOnDragListener(OnDragListener l) {
5905        getListenerInfo().mOnDragListener = l;
5906    }
5907
5908    /**
5909     * Give this view focus. This will cause
5910     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5911     *
5912     * Note: this does not check whether this {@link View} should get focus, it just
5913     * gives it focus no matter what.  It should only be called internally by framework
5914     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5915     *
5916     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5917     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5918     *        focus moved when requestFocus() is called. It may not always
5919     *        apply, in which case use the default View.FOCUS_DOWN.
5920     * @param previouslyFocusedRect The rectangle of the view that had focus
5921     *        prior in this View's coordinate system.
5922     */
5923    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5924        if (DBG) {
5925            System.out.println(this + " requestFocus()");
5926        }
5927
5928        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5929            mPrivateFlags |= PFLAG_FOCUSED;
5930
5931            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5932
5933            if (mParent != null) {
5934                mParent.requestChildFocus(this, this);
5935            }
5936
5937            if (mAttachInfo != null) {
5938                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5939            }
5940
5941            onFocusChanged(true, direction, previouslyFocusedRect);
5942            refreshDrawableState();
5943        }
5944    }
5945
5946    /**
5947     * Sets this view's preference for reveal behavior when it gains focus.
5948     *
5949     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
5950     * this view would prefer to be brought fully into view when it gains focus.
5951     * For example, a text field that a user is meant to type into. Other views such
5952     * as scrolling containers may prefer to opt-out of this behavior.</p>
5953     *
5954     * <p>The default value for views is true, though subclasses may change this
5955     * based on their preferred behavior.</p>
5956     *
5957     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
5958     *
5959     * @see #getRevealOnFocusHint()
5960     */
5961    public final void setRevealOnFocusHint(boolean revealOnFocus) {
5962        if (revealOnFocus) {
5963            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
5964        } else {
5965            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
5966        }
5967    }
5968
5969    /**
5970     * Returns this view's preference for reveal behavior when it gains focus.
5971     *
5972     * <p>When this method returns true for a child view requesting focus, ancestor
5973     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
5974     * should make a best effort to make the newly focused child fully visible to the user.
5975     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
5976     * other properties affecting visibility to the user as part of the focus change.</p>
5977     *
5978     * @return true if this view would prefer to become fully visible when it gains focus,
5979     *         false if it would prefer not to disrupt scroll positioning
5980     *
5981     * @see #setRevealOnFocusHint(boolean)
5982     */
5983    public final boolean getRevealOnFocusHint() {
5984        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
5985    }
5986
5987    /**
5988     * Populates <code>outRect</code> with the hotspot bounds. By default,
5989     * the hotspot bounds are identical to the screen bounds.
5990     *
5991     * @param outRect rect to populate with hotspot bounds
5992     * @hide Only for internal use by views and widgets.
5993     */
5994    public void getHotspotBounds(Rect outRect) {
5995        final Drawable background = getBackground();
5996        if (background != null) {
5997            background.getHotspotBounds(outRect);
5998        } else {
5999            getBoundsOnScreen(outRect);
6000        }
6001    }
6002
6003    /**
6004     * Request that a rectangle of this view be visible on the screen,
6005     * scrolling if necessary just enough.
6006     *
6007     * <p>A View should call this if it maintains some notion of which part
6008     * of its content is interesting.  For example, a text editing view
6009     * should call this when its cursor moves.
6010     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6011     * It should not be affected by which part of the View is currently visible or its scroll
6012     * position.
6013     *
6014     * @param rectangle The rectangle in the View's content coordinate space
6015     * @return Whether any parent scrolled.
6016     */
6017    public boolean requestRectangleOnScreen(Rect rectangle) {
6018        return requestRectangleOnScreen(rectangle, false);
6019    }
6020
6021    /**
6022     * Request that a rectangle of this view be visible on the screen,
6023     * scrolling if necessary just enough.
6024     *
6025     * <p>A View should call this if it maintains some notion of which part
6026     * of its content is interesting.  For example, a text editing view
6027     * should call this when its cursor moves.
6028     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6029     * It should not be affected by which part of the View is currently visible or its scroll
6030     * position.
6031     * <p>When <code>immediate</code> is set to true, scrolling will not be
6032     * animated.
6033     *
6034     * @param rectangle The rectangle in the View's content coordinate space
6035     * @param immediate True to forbid animated scrolling, false otherwise
6036     * @return Whether any parent scrolled.
6037     */
6038    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6039        if (mParent == null) {
6040            return false;
6041        }
6042
6043        View child = this;
6044
6045        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6046        position.set(rectangle);
6047
6048        ViewParent parent = mParent;
6049        boolean scrolled = false;
6050        while (parent != null) {
6051            rectangle.set((int) position.left, (int) position.top,
6052                    (int) position.right, (int) position.bottom);
6053
6054            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6055
6056            if (!(parent instanceof View)) {
6057                break;
6058            }
6059
6060            // move it from child's content coordinate space to parent's content coordinate space
6061            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6062
6063            child = (View) parent;
6064            parent = child.getParent();
6065        }
6066
6067        return scrolled;
6068    }
6069
6070    /**
6071     * Called when this view wants to give up focus. If focus is cleared
6072     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6073     * <p>
6074     * <strong>Note:</strong> When a View clears focus the framework is trying
6075     * to give focus to the first focusable View from the top. Hence, if this
6076     * View is the first from the top that can take focus, then all callbacks
6077     * related to clearing focus will be invoked after which the framework will
6078     * give focus to this view.
6079     * </p>
6080     */
6081    public void clearFocus() {
6082        if (DBG) {
6083            System.out.println(this + " clearFocus()");
6084        }
6085
6086        clearFocusInternal(null, true, true);
6087    }
6088
6089    /**
6090     * Clears focus from the view, optionally propagating the change up through
6091     * the parent hierarchy and requesting that the root view place new focus.
6092     *
6093     * @param propagate whether to propagate the change up through the parent
6094     *            hierarchy
6095     * @param refocus when propagate is true, specifies whether to request the
6096     *            root view place new focus
6097     */
6098    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6099        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6100            mPrivateFlags &= ~PFLAG_FOCUSED;
6101
6102            if (propagate && mParent != null) {
6103                mParent.clearChildFocus(this);
6104            }
6105
6106            onFocusChanged(false, 0, null);
6107            refreshDrawableState();
6108
6109            if (propagate && (!refocus || !rootViewRequestFocus())) {
6110                notifyGlobalFocusCleared(this);
6111            }
6112        }
6113    }
6114
6115    void notifyGlobalFocusCleared(View oldFocus) {
6116        if (oldFocus != null && mAttachInfo != null) {
6117            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6118        }
6119    }
6120
6121    boolean rootViewRequestFocus() {
6122        final View root = getRootView();
6123        return root != null && root.requestFocus();
6124    }
6125
6126    /**
6127     * Called internally by the view system when a new view is getting focus.
6128     * This is what clears the old focus.
6129     * <p>
6130     * <b>NOTE:</b> The parent view's focused child must be updated manually
6131     * after calling this method. Otherwise, the view hierarchy may be left in
6132     * an inconstent state.
6133     */
6134    void unFocus(View focused) {
6135        if (DBG) {
6136            System.out.println(this + " unFocus()");
6137        }
6138
6139        clearFocusInternal(focused, false, false);
6140    }
6141
6142    /**
6143     * Returns true if this view has focus itself, or is the ancestor of the
6144     * view that has focus.
6145     *
6146     * @return True if this view has or contains focus, false otherwise.
6147     */
6148    @ViewDebug.ExportedProperty(category = "focus")
6149    public boolean hasFocus() {
6150        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6151    }
6152
6153    /**
6154     * Returns true if this view is focusable or if it contains a reachable View
6155     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
6156     * is a View whose parents do not block descendants focus.
6157     *
6158     * Only {@link #VISIBLE} views are considered focusable.
6159     *
6160     * @return True if the view is focusable or if the view contains a focusable
6161     *         View, false otherwise.
6162     *
6163     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6164     * @see ViewGroup#getTouchscreenBlocksFocus()
6165     */
6166    public boolean hasFocusable() {
6167        if (!isFocusableInTouchMode()) {
6168            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6169                final ViewGroup g = (ViewGroup) p;
6170                if (g.shouldBlockFocusForTouchscreen()) {
6171                    return false;
6172                }
6173            }
6174        }
6175        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
6176    }
6177
6178    /**
6179     * Called by the view system when the focus state of this view changes.
6180     * When the focus change event is caused by directional navigation, direction
6181     * and previouslyFocusedRect provide insight into where the focus is coming from.
6182     * When overriding, be sure to call up through to the super class so that
6183     * the standard focus handling will occur.
6184     *
6185     * @param gainFocus True if the View has focus; false otherwise.
6186     * @param direction The direction focus has moved when requestFocus()
6187     *                  is called to give this view focus. Values are
6188     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6189     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6190     *                  It may not always apply, in which case use the default.
6191     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6192     *        system, of the previously focused view.  If applicable, this will be
6193     *        passed in as finer grained information about where the focus is coming
6194     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6195     */
6196    @CallSuper
6197    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6198            @Nullable Rect previouslyFocusedRect) {
6199        if (gainFocus) {
6200            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6201        } else {
6202            notifyViewAccessibilityStateChangedIfNeeded(
6203                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6204        }
6205
6206        InputMethodManager imm = InputMethodManager.peekInstance();
6207        if (!gainFocus) {
6208            if (isPressed()) {
6209                setPressed(false);
6210            }
6211            if (imm != null && mAttachInfo != null
6212                    && mAttachInfo.mHasWindowFocus) {
6213                imm.focusOut(this);
6214            }
6215            onFocusLost();
6216        } else if (imm != null && mAttachInfo != null
6217                && mAttachInfo.mHasWindowFocus) {
6218            imm.focusIn(this);
6219        }
6220
6221        invalidate(true);
6222        ListenerInfo li = mListenerInfo;
6223        if (li != null && li.mOnFocusChangeListener != null) {
6224            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6225        }
6226
6227        if (mAttachInfo != null) {
6228            mAttachInfo.mKeyDispatchState.reset(this);
6229        }
6230    }
6231
6232    /**
6233     * Sends an accessibility event of the given type. If accessibility is
6234     * not enabled this method has no effect. The default implementation calls
6235     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6236     * to populate information about the event source (this View), then calls
6237     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6238     * populate the text content of the event source including its descendants,
6239     * and last calls
6240     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6241     * on its parent to request sending of the event to interested parties.
6242     * <p>
6243     * If an {@link AccessibilityDelegate} has been specified via calling
6244     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6245     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6246     * responsible for handling this call.
6247     * </p>
6248     *
6249     * @param eventType The type of the event to send, as defined by several types from
6250     * {@link android.view.accessibility.AccessibilityEvent}, such as
6251     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6252     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6253     *
6254     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6255     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6256     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6257     * @see AccessibilityDelegate
6258     */
6259    public void sendAccessibilityEvent(int eventType) {
6260        if (mAccessibilityDelegate != null) {
6261            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6262        } else {
6263            sendAccessibilityEventInternal(eventType);
6264        }
6265    }
6266
6267    /**
6268     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6269     * {@link AccessibilityEvent} to make an announcement which is related to some
6270     * sort of a context change for which none of the events representing UI transitions
6271     * is a good fit. For example, announcing a new page in a book. If accessibility
6272     * is not enabled this method does nothing.
6273     *
6274     * @param text The announcement text.
6275     */
6276    public void announceForAccessibility(CharSequence text) {
6277        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6278            AccessibilityEvent event = AccessibilityEvent.obtain(
6279                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6280            onInitializeAccessibilityEvent(event);
6281            event.getText().add(text);
6282            event.setContentDescription(null);
6283            mParent.requestSendAccessibilityEvent(this, event);
6284        }
6285    }
6286
6287    /**
6288     * @see #sendAccessibilityEvent(int)
6289     *
6290     * Note: Called from the default {@link AccessibilityDelegate}.
6291     *
6292     * @hide
6293     */
6294    public void sendAccessibilityEventInternal(int eventType) {
6295        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6296            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6297        }
6298    }
6299
6300    /**
6301     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6302     * takes as an argument an empty {@link AccessibilityEvent} and does not
6303     * perform a check whether accessibility is enabled.
6304     * <p>
6305     * If an {@link AccessibilityDelegate} has been specified via calling
6306     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6307     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6308     * is responsible for handling this call.
6309     * </p>
6310     *
6311     * @param event The event to send.
6312     *
6313     * @see #sendAccessibilityEvent(int)
6314     */
6315    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6316        if (mAccessibilityDelegate != null) {
6317            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6318        } else {
6319            sendAccessibilityEventUncheckedInternal(event);
6320        }
6321    }
6322
6323    /**
6324     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6325     *
6326     * Note: Called from the default {@link AccessibilityDelegate}.
6327     *
6328     * @hide
6329     */
6330    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6331        if (!isShown()) {
6332            return;
6333        }
6334        onInitializeAccessibilityEvent(event);
6335        // Only a subset of accessibility events populates text content.
6336        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6337            dispatchPopulateAccessibilityEvent(event);
6338        }
6339        // In the beginning we called #isShown(), so we know that getParent() is not null.
6340        getParent().requestSendAccessibilityEvent(this, event);
6341    }
6342
6343    /**
6344     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6345     * to its children for adding their text content to the event. Note that the
6346     * event text is populated in a separate dispatch path since we add to the
6347     * event not only the text of the source but also the text of all its descendants.
6348     * A typical implementation will call
6349     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6350     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6351     * on each child. Override this method if custom population of the event text
6352     * content is required.
6353     * <p>
6354     * If an {@link AccessibilityDelegate} has been specified via calling
6355     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6356     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6357     * is responsible for handling this call.
6358     * </p>
6359     * <p>
6360     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6361     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6362     * </p>
6363     *
6364     * @param event The event.
6365     *
6366     * @return True if the event population was completed.
6367     */
6368    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6369        if (mAccessibilityDelegate != null) {
6370            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6371        } else {
6372            return dispatchPopulateAccessibilityEventInternal(event);
6373        }
6374    }
6375
6376    /**
6377     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6378     *
6379     * Note: Called from the default {@link AccessibilityDelegate}.
6380     *
6381     * @hide
6382     */
6383    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6384        onPopulateAccessibilityEvent(event);
6385        return false;
6386    }
6387
6388    /**
6389     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6390     * giving a chance to this View to populate the accessibility event with its
6391     * text content. While this method is free to modify event
6392     * attributes other than text content, doing so should normally be performed in
6393     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6394     * <p>
6395     * Example: Adding formatted date string to an accessibility event in addition
6396     *          to the text added by the super implementation:
6397     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6398     *     super.onPopulateAccessibilityEvent(event);
6399     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6400     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6401     *         mCurrentDate.getTimeInMillis(), flags);
6402     *     event.getText().add(selectedDateUtterance);
6403     * }</pre>
6404     * <p>
6405     * If an {@link AccessibilityDelegate} has been specified via calling
6406     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6407     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6408     * is responsible for handling this call.
6409     * </p>
6410     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6411     * information to the event, in case the default implementation has basic information to add.
6412     * </p>
6413     *
6414     * @param event The accessibility event which to populate.
6415     *
6416     * @see #sendAccessibilityEvent(int)
6417     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6418     */
6419    @CallSuper
6420    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6421        if (mAccessibilityDelegate != null) {
6422            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6423        } else {
6424            onPopulateAccessibilityEventInternal(event);
6425        }
6426    }
6427
6428    /**
6429     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6430     *
6431     * Note: Called from the default {@link AccessibilityDelegate}.
6432     *
6433     * @hide
6434     */
6435    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6436    }
6437
6438    /**
6439     * Initializes an {@link AccessibilityEvent} with information about
6440     * this View which is the event source. In other words, the source of
6441     * an accessibility event is the view whose state change triggered firing
6442     * the event.
6443     * <p>
6444     * Example: Setting the password property of an event in addition
6445     *          to properties set by the super implementation:
6446     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6447     *     super.onInitializeAccessibilityEvent(event);
6448     *     event.setPassword(true);
6449     * }</pre>
6450     * <p>
6451     * If an {@link AccessibilityDelegate} has been specified via calling
6452     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6453     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6454     * is responsible for handling this call.
6455     * </p>
6456     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6457     * information to the event, in case the default implementation has basic information to add.
6458     * </p>
6459     * @param event The event to initialize.
6460     *
6461     * @see #sendAccessibilityEvent(int)
6462     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6463     */
6464    @CallSuper
6465    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6466        if (mAccessibilityDelegate != null) {
6467            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6468        } else {
6469            onInitializeAccessibilityEventInternal(event);
6470        }
6471    }
6472
6473    /**
6474     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6475     *
6476     * Note: Called from the default {@link AccessibilityDelegate}.
6477     *
6478     * @hide
6479     */
6480    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6481        event.setSource(this);
6482        event.setClassName(getAccessibilityClassName());
6483        event.setPackageName(getContext().getPackageName());
6484        event.setEnabled(isEnabled());
6485        event.setContentDescription(mContentDescription);
6486
6487        switch (event.getEventType()) {
6488            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6489                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6490                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6491                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6492                event.setItemCount(focusablesTempList.size());
6493                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6494                if (mAttachInfo != null) {
6495                    focusablesTempList.clear();
6496                }
6497            } break;
6498            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6499                CharSequence text = getIterableTextForAccessibility();
6500                if (text != null && text.length() > 0) {
6501                    event.setFromIndex(getAccessibilitySelectionStart());
6502                    event.setToIndex(getAccessibilitySelectionEnd());
6503                    event.setItemCount(text.length());
6504                }
6505            } break;
6506        }
6507    }
6508
6509    /**
6510     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6511     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6512     * This method is responsible for obtaining an accessibility node info from a
6513     * pool of reusable instances and calling
6514     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6515     * initialize the former.
6516     * <p>
6517     * Note: The client is responsible for recycling the obtained instance by calling
6518     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6519     * </p>
6520     *
6521     * @return A populated {@link AccessibilityNodeInfo}.
6522     *
6523     * @see AccessibilityNodeInfo
6524     */
6525    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6526        if (mAccessibilityDelegate != null) {
6527            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6528        } else {
6529            return createAccessibilityNodeInfoInternal();
6530        }
6531    }
6532
6533    /**
6534     * @see #createAccessibilityNodeInfo()
6535     *
6536     * @hide
6537     */
6538    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6539        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6540        if (provider != null) {
6541            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6542        } else {
6543            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6544            onInitializeAccessibilityNodeInfo(info);
6545            return info;
6546        }
6547    }
6548
6549    /**
6550     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6551     * The base implementation sets:
6552     * <ul>
6553     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6554     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6555     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6556     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6557     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6558     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6559     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6560     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6561     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6562     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6563     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6564     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6565     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6566     * </ul>
6567     * <p>
6568     * Subclasses should override this method, call the super implementation,
6569     * and set additional attributes.
6570     * </p>
6571     * <p>
6572     * If an {@link AccessibilityDelegate} has been specified via calling
6573     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6574     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6575     * is responsible for handling this call.
6576     * </p>
6577     *
6578     * @param info The instance to initialize.
6579     */
6580    @CallSuper
6581    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6582        if (mAccessibilityDelegate != null) {
6583            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6584        } else {
6585            onInitializeAccessibilityNodeInfoInternal(info);
6586        }
6587    }
6588
6589    /**
6590     * Gets the location of this view in screen coordinates.
6591     *
6592     * @param outRect The output location
6593     * @hide
6594     */
6595    public void getBoundsOnScreen(Rect outRect) {
6596        getBoundsOnScreen(outRect, false);
6597    }
6598
6599    /**
6600     * Gets the location of this view in screen coordinates.
6601     *
6602     * @param outRect The output location
6603     * @param clipToParent Whether to clip child bounds to the parent ones.
6604     * @hide
6605     */
6606    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6607        if (mAttachInfo == null) {
6608            return;
6609        }
6610
6611        RectF position = mAttachInfo.mTmpTransformRect;
6612        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6613
6614        if (!hasIdentityMatrix()) {
6615            getMatrix().mapRect(position);
6616        }
6617
6618        position.offset(mLeft, mTop);
6619
6620        ViewParent parent = mParent;
6621        while (parent instanceof View) {
6622            View parentView = (View) parent;
6623
6624            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6625
6626            if (clipToParent) {
6627                position.left = Math.max(position.left, 0);
6628                position.top = Math.max(position.top, 0);
6629                position.right = Math.min(position.right, parentView.getWidth());
6630                position.bottom = Math.min(position.bottom, parentView.getHeight());
6631            }
6632
6633            if (!parentView.hasIdentityMatrix()) {
6634                parentView.getMatrix().mapRect(position);
6635            }
6636
6637            position.offset(parentView.mLeft, parentView.mTop);
6638
6639            parent = parentView.mParent;
6640        }
6641
6642        if (parent instanceof ViewRootImpl) {
6643            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6644            position.offset(0, -viewRootImpl.mCurScrollY);
6645        }
6646
6647        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6648
6649        outRect.set(Math.round(position.left), Math.round(position.top),
6650                Math.round(position.right), Math.round(position.bottom));
6651    }
6652
6653    /**
6654     * Return the class name of this object to be used for accessibility purposes.
6655     * Subclasses should only override this if they are implementing something that
6656     * should be seen as a completely new class of view when used by accessibility,
6657     * unrelated to the class it is deriving from.  This is used to fill in
6658     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6659     */
6660    public CharSequence getAccessibilityClassName() {
6661        return View.class.getName();
6662    }
6663
6664    /**
6665     * Called when assist structure is being retrieved from a view as part of
6666     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6667     * @param structure Fill in with structured view data.  The default implementation
6668     * fills in all data that can be inferred from the view itself.
6669     */
6670    public void onProvideStructure(ViewStructure structure) {
6671        final int id = mID;
6672        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6673                && (id&0x0000ffff) != 0) {
6674            String pkg, type, entry;
6675            try {
6676                final Resources res = getResources();
6677                entry = res.getResourceEntryName(id);
6678                type = res.getResourceTypeName(id);
6679                pkg = res.getResourcePackageName(id);
6680            } catch (Resources.NotFoundException e) {
6681                entry = type = pkg = null;
6682            }
6683            structure.setId(id, pkg, type, entry);
6684        } else {
6685            structure.setId(id, null, null, null);
6686        }
6687        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6688        if (!hasIdentityMatrix()) {
6689            structure.setTransformation(getMatrix());
6690        }
6691        structure.setElevation(getZ());
6692        structure.setVisibility(getVisibility());
6693        structure.setEnabled(isEnabled());
6694        if (isClickable()) {
6695            structure.setClickable(true);
6696        }
6697        if (isFocusable()) {
6698            structure.setFocusable(true);
6699        }
6700        if (isFocused()) {
6701            structure.setFocused(true);
6702        }
6703        if (isAccessibilityFocused()) {
6704            structure.setAccessibilityFocused(true);
6705        }
6706        if (isSelected()) {
6707            structure.setSelected(true);
6708        }
6709        if (isActivated()) {
6710            structure.setActivated(true);
6711        }
6712        if (isLongClickable()) {
6713            structure.setLongClickable(true);
6714        }
6715        if (this instanceof Checkable) {
6716            structure.setCheckable(true);
6717            if (((Checkable)this).isChecked()) {
6718                structure.setChecked(true);
6719            }
6720        }
6721        if (isContextClickable()) {
6722            structure.setContextClickable(true);
6723        }
6724        structure.setClassName(getAccessibilityClassName().toString());
6725        structure.setContentDescription(getContentDescription());
6726    }
6727
6728    /**
6729     * Called when assist structure is being retrieved from a view as part of
6730     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6731     * generate additional virtual structure under this view.  The defaullt implementation
6732     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6733     * view's virtual accessibility nodes, if any.  You can override this for a more
6734     * optimal implementation providing this data.
6735     */
6736    public void onProvideVirtualStructure(ViewStructure structure) {
6737        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6738        if (provider != null) {
6739            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6740            structure.setChildCount(1);
6741            ViewStructure root = structure.newChild(0);
6742            populateVirtualStructure(root, provider, info);
6743            info.recycle();
6744        }
6745    }
6746
6747    private void populateVirtualStructure(ViewStructure structure,
6748            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6749        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6750                null, null, null);
6751        Rect rect = structure.getTempRect();
6752        info.getBoundsInParent(rect);
6753        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6754        structure.setVisibility(VISIBLE);
6755        structure.setEnabled(info.isEnabled());
6756        if (info.isClickable()) {
6757            structure.setClickable(true);
6758        }
6759        if (info.isFocusable()) {
6760            structure.setFocusable(true);
6761        }
6762        if (info.isFocused()) {
6763            structure.setFocused(true);
6764        }
6765        if (info.isAccessibilityFocused()) {
6766            structure.setAccessibilityFocused(true);
6767        }
6768        if (info.isSelected()) {
6769            structure.setSelected(true);
6770        }
6771        if (info.isLongClickable()) {
6772            structure.setLongClickable(true);
6773        }
6774        if (info.isCheckable()) {
6775            structure.setCheckable(true);
6776            if (info.isChecked()) {
6777                structure.setChecked(true);
6778            }
6779        }
6780        if (info.isContextClickable()) {
6781            structure.setContextClickable(true);
6782        }
6783        CharSequence cname = info.getClassName();
6784        structure.setClassName(cname != null ? cname.toString() : null);
6785        structure.setContentDescription(info.getContentDescription());
6786        if (info.getText() != null || info.getError() != null) {
6787            structure.setText(info.getText(), info.getTextSelectionStart(),
6788                    info.getTextSelectionEnd());
6789        }
6790        final int NCHILDREN = info.getChildCount();
6791        if (NCHILDREN > 0) {
6792            structure.setChildCount(NCHILDREN);
6793            for (int i=0; i<NCHILDREN; i++) {
6794                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6795                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6796                ViewStructure child = structure.newChild(i);
6797                populateVirtualStructure(child, provider, cinfo);
6798                cinfo.recycle();
6799            }
6800        }
6801    }
6802
6803    /**
6804     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6805     * implementation calls {@link #onProvideStructure} and
6806     * {@link #onProvideVirtualStructure}.
6807     */
6808    public void dispatchProvideStructure(ViewStructure structure) {
6809        if (!isAssistBlocked()) {
6810            onProvideStructure(structure);
6811            onProvideVirtualStructure(structure);
6812        } else {
6813            structure.setClassName(getAccessibilityClassName().toString());
6814            structure.setAssistBlocked(true);
6815        }
6816    }
6817
6818    /**
6819     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6820     *
6821     * Note: Called from the default {@link AccessibilityDelegate}.
6822     *
6823     * @hide
6824     */
6825    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6826        if (mAttachInfo == null) {
6827            return;
6828        }
6829
6830        Rect bounds = mAttachInfo.mTmpInvalRect;
6831
6832        getDrawingRect(bounds);
6833        info.setBoundsInParent(bounds);
6834
6835        getBoundsOnScreen(bounds, true);
6836        info.setBoundsInScreen(bounds);
6837
6838        ViewParent parent = getParentForAccessibility();
6839        if (parent instanceof View) {
6840            info.setParent((View) parent);
6841        }
6842
6843        if (mID != View.NO_ID) {
6844            View rootView = getRootView();
6845            if (rootView == null) {
6846                rootView = this;
6847            }
6848
6849            View label = rootView.findLabelForView(this, mID);
6850            if (label != null) {
6851                info.setLabeledBy(label);
6852            }
6853
6854            if ((mAttachInfo.mAccessibilityFetchFlags
6855                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6856                    && Resources.resourceHasPackage(mID)) {
6857                try {
6858                    String viewId = getResources().getResourceName(mID);
6859                    info.setViewIdResourceName(viewId);
6860                } catch (Resources.NotFoundException nfe) {
6861                    /* ignore */
6862                }
6863            }
6864        }
6865
6866        if (mLabelForId != View.NO_ID) {
6867            View rootView = getRootView();
6868            if (rootView == null) {
6869                rootView = this;
6870            }
6871            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6872            if (labeled != null) {
6873                info.setLabelFor(labeled);
6874            }
6875        }
6876
6877        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6878            View rootView = getRootView();
6879            if (rootView == null) {
6880                rootView = this;
6881            }
6882            View next = rootView.findViewInsideOutShouldExist(this,
6883                    mAccessibilityTraversalBeforeId);
6884            if (next != null && next.includeForAccessibility()) {
6885                info.setTraversalBefore(next);
6886            }
6887        }
6888
6889        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6890            View rootView = getRootView();
6891            if (rootView == null) {
6892                rootView = this;
6893            }
6894            View next = rootView.findViewInsideOutShouldExist(this,
6895                    mAccessibilityTraversalAfterId);
6896            if (next != null && next.includeForAccessibility()) {
6897                info.setTraversalAfter(next);
6898            }
6899        }
6900
6901        info.setVisibleToUser(isVisibleToUser());
6902
6903        if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags
6904                & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) {
6905            info.setImportantForAccessibility(isImportantForAccessibility());
6906        } else {
6907            info.setImportantForAccessibility(true);
6908        }
6909
6910        info.setPackageName(mContext.getPackageName());
6911        info.setClassName(getAccessibilityClassName());
6912        info.setContentDescription(getContentDescription());
6913
6914        info.setEnabled(isEnabled());
6915        info.setClickable(isClickable());
6916        info.setFocusable(isFocusable());
6917        info.setFocused(isFocused());
6918        info.setAccessibilityFocused(isAccessibilityFocused());
6919        info.setSelected(isSelected());
6920        info.setLongClickable(isLongClickable());
6921        info.setContextClickable(isContextClickable());
6922        info.setLiveRegion(getAccessibilityLiveRegion());
6923
6924        // TODO: These make sense only if we are in an AdapterView but all
6925        // views can be selected. Maybe from accessibility perspective
6926        // we should report as selectable view in an AdapterView.
6927        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6928        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6929
6930        if (isFocusable()) {
6931            if (isFocused()) {
6932                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6933            } else {
6934                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6935            }
6936        }
6937
6938        if (!isAccessibilityFocused()) {
6939            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6940        } else {
6941            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6942        }
6943
6944        if (isClickable() && isEnabled()) {
6945            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6946        }
6947
6948        if (isLongClickable() && isEnabled()) {
6949            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6950        }
6951
6952        if (isContextClickable() && isEnabled()) {
6953            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6954        }
6955
6956        CharSequence text = getIterableTextForAccessibility();
6957        if (text != null && text.length() > 0) {
6958            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6959
6960            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6961            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6962            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6963            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6964                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6965                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6966        }
6967
6968        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6969        populateAccessibilityNodeInfoDrawingOrderInParent(info);
6970    }
6971
6972    /**
6973     * Determine the order in which this view will be drawn relative to its siblings for a11y
6974     *
6975     * @param info The info whose drawing order should be populated
6976     */
6977    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
6978        /*
6979         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
6980         * drawing order may not be well-defined, and some Views with custom drawing order may
6981         * not be initialized sufficiently to respond properly getChildDrawingOrder.
6982         */
6983        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
6984            info.setDrawingOrder(0);
6985            return;
6986        }
6987        int drawingOrderInParent = 1;
6988        // Iterate up the hierarchy if parents are not important for a11y
6989        View viewAtDrawingLevel = this;
6990        final ViewParent parent = getParentForAccessibility();
6991        while (viewAtDrawingLevel != parent) {
6992            final ViewParent currentParent = viewAtDrawingLevel.getParent();
6993            if (!(currentParent instanceof ViewGroup)) {
6994                // Should only happen for the Decor
6995                drawingOrderInParent = 0;
6996                break;
6997            } else {
6998                final ViewGroup parentGroup = (ViewGroup) currentParent;
6999                final int childCount = parentGroup.getChildCount();
7000                if (childCount > 1) {
7001                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7002                    if (preorderedList != null) {
7003                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7004                        for (int i = 0; i < childDrawIndex; i++) {
7005                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7006                        }
7007                    } else {
7008                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7009                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7010                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7011                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7012                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7013                        if (childDrawIndex != 0) {
7014                            for (int i = 0; i < numChildrenToIterate; i++) {
7015                                final int otherDrawIndex = (customOrder ?
7016                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7017                                if (otherDrawIndex < childDrawIndex) {
7018                                    drawingOrderInParent +=
7019                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7020                                }
7021                            }
7022                        }
7023                    }
7024                }
7025            }
7026            viewAtDrawingLevel = (View) currentParent;
7027        }
7028        info.setDrawingOrder(drawingOrderInParent);
7029    }
7030
7031    private static int numViewsForAccessibility(View view) {
7032        if (view != null) {
7033            if (view.includeForAccessibility()) {
7034                return 1;
7035            } else if (view instanceof ViewGroup) {
7036                return ((ViewGroup) view).getNumChildrenForAccessibility();
7037            }
7038        }
7039        return 0;
7040    }
7041
7042    private View findLabelForView(View view, int labeledId) {
7043        if (mMatchLabelForPredicate == null) {
7044            mMatchLabelForPredicate = new MatchLabelForPredicate();
7045        }
7046        mMatchLabelForPredicate.mLabeledId = labeledId;
7047        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7048    }
7049
7050    /**
7051     * Computes whether this view is visible to the user. Such a view is
7052     * attached, visible, all its predecessors are visible, it is not clipped
7053     * entirely by its predecessors, and has an alpha greater than zero.
7054     *
7055     * @return Whether the view is visible on the screen.
7056     *
7057     * @hide
7058     */
7059    protected boolean isVisibleToUser() {
7060        return isVisibleToUser(null);
7061    }
7062
7063    /**
7064     * Computes whether the given portion of this view is visible to the user.
7065     * Such a view is attached, visible, all its predecessors are visible,
7066     * has an alpha greater than zero, and the specified portion is not
7067     * clipped entirely by its predecessors.
7068     *
7069     * @param boundInView the portion of the view to test; coordinates should be relative; may be
7070     *                    <code>null</code>, and the entire view will be tested in this case.
7071     *                    When <code>true</code> is returned by the function, the actual visible
7072     *                    region will be stored in this parameter; that is, if boundInView is fully
7073     *                    contained within the view, no modification will be made, otherwise regions
7074     *                    outside of the visible area of the view will be clipped.
7075     *
7076     * @return Whether the specified portion of the view is visible on the screen.
7077     *
7078     * @hide
7079     */
7080    protected boolean isVisibleToUser(Rect boundInView) {
7081        if (mAttachInfo != null) {
7082            // Attached to invisible window means this view is not visible.
7083            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
7084                return false;
7085            }
7086            // An invisible predecessor or one with alpha zero means
7087            // that this view is not visible to the user.
7088            Object current = this;
7089            while (current instanceof View) {
7090                View view = (View) current;
7091                // We have attach info so this view is attached and there is no
7092                // need to check whether we reach to ViewRootImpl on the way up.
7093                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
7094                        view.getVisibility() != VISIBLE) {
7095                    return false;
7096                }
7097                current = view.mParent;
7098            }
7099            // Check if the view is entirely covered by its predecessors.
7100            Rect visibleRect = mAttachInfo.mTmpInvalRect;
7101            Point offset = mAttachInfo.mPoint;
7102            if (!getGlobalVisibleRect(visibleRect, offset)) {
7103                return false;
7104            }
7105            // Check if the visible portion intersects the rectangle of interest.
7106            if (boundInView != null) {
7107                visibleRect.offset(-offset.x, -offset.y);
7108                return boundInView.intersect(visibleRect);
7109            }
7110            return true;
7111        }
7112        return false;
7113    }
7114
7115    /**
7116     * Returns the delegate for implementing accessibility support via
7117     * composition. For more details see {@link AccessibilityDelegate}.
7118     *
7119     * @return The delegate, or null if none set.
7120     *
7121     * @hide
7122     */
7123    public AccessibilityDelegate getAccessibilityDelegate() {
7124        return mAccessibilityDelegate;
7125    }
7126
7127    /**
7128     * Sets a delegate for implementing accessibility support via composition
7129     * (as opposed to inheritance). For more details, see
7130     * {@link AccessibilityDelegate}.
7131     * <p>
7132     * <strong>Note:</strong> On platform versions prior to
7133     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
7134     * views in the {@code android.widget.*} package are called <i>before</i>
7135     * host methods. This prevents certain properties such as class name from
7136     * being modified by overriding
7137     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
7138     * as any changes will be overwritten by the host class.
7139     * <p>
7140     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
7141     * methods are called <i>after</i> host methods, which all properties to be
7142     * modified without being overwritten by the host class.
7143     *
7144     * @param delegate the object to which accessibility method calls should be
7145     *                 delegated
7146     * @see AccessibilityDelegate
7147     */
7148    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
7149        mAccessibilityDelegate = delegate;
7150    }
7151
7152    /**
7153     * Gets the provider for managing a virtual view hierarchy rooted at this View
7154     * and reported to {@link android.accessibilityservice.AccessibilityService}s
7155     * that explore the window content.
7156     * <p>
7157     * If this method returns an instance, this instance is responsible for managing
7158     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
7159     * View including the one representing the View itself. Similarly the returned
7160     * instance is responsible for performing accessibility actions on any virtual
7161     * view or the root view itself.
7162     * </p>
7163     * <p>
7164     * If an {@link AccessibilityDelegate} has been specified via calling
7165     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7166     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
7167     * is responsible for handling this call.
7168     * </p>
7169     *
7170     * @return The provider.
7171     *
7172     * @see AccessibilityNodeProvider
7173     */
7174    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
7175        if (mAccessibilityDelegate != null) {
7176            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
7177        } else {
7178            return null;
7179        }
7180    }
7181
7182    /**
7183     * Gets the unique identifier of this view on the screen for accessibility purposes.
7184     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
7185     *
7186     * @return The view accessibility id.
7187     *
7188     * @hide
7189     */
7190    public int getAccessibilityViewId() {
7191        if (mAccessibilityViewId == NO_ID) {
7192            mAccessibilityViewId = sNextAccessibilityViewId++;
7193        }
7194        return mAccessibilityViewId;
7195    }
7196
7197    /**
7198     * Gets the unique identifier of the window in which this View reseides.
7199     *
7200     * @return The window accessibility id.
7201     *
7202     * @hide
7203     */
7204    public int getAccessibilityWindowId() {
7205        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
7206                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
7207    }
7208
7209    /**
7210     * Returns the {@link View}'s content description.
7211     * <p>
7212     * <strong>Note:</strong> Do not override this method, as it will have no
7213     * effect on the content description presented to accessibility services.
7214     * You must call {@link #setContentDescription(CharSequence)} to modify the
7215     * content description.
7216     *
7217     * @return the content description
7218     * @see #setContentDescription(CharSequence)
7219     * @attr ref android.R.styleable#View_contentDescription
7220     */
7221    @ViewDebug.ExportedProperty(category = "accessibility")
7222    public CharSequence getContentDescription() {
7223        return mContentDescription;
7224    }
7225
7226    /**
7227     * Sets the {@link View}'s content description.
7228     * <p>
7229     * A content description briefly describes the view and is primarily used
7230     * for accessibility support to determine how a view should be presented to
7231     * the user. In the case of a view with no textual representation, such as
7232     * {@link android.widget.ImageButton}, a useful content description
7233     * explains what the view does. For example, an image button with a phone
7234     * icon that is used to place a call may use "Call" as its content
7235     * description. An image of a floppy disk that is used to save a file may
7236     * use "Save".
7237     *
7238     * @param contentDescription The content description.
7239     * @see #getContentDescription()
7240     * @attr ref android.R.styleable#View_contentDescription
7241     */
7242    @RemotableViewMethod
7243    public void setContentDescription(CharSequence contentDescription) {
7244        if (mContentDescription == null) {
7245            if (contentDescription == null) {
7246                return;
7247            }
7248        } else if (mContentDescription.equals(contentDescription)) {
7249            return;
7250        }
7251        mContentDescription = contentDescription;
7252        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
7253        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
7254            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
7255            notifySubtreeAccessibilityStateChangedIfNeeded();
7256        } else {
7257            notifyViewAccessibilityStateChangedIfNeeded(
7258                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
7259        }
7260    }
7261
7262    /**
7263     * Sets the id of a view before which this one is visited in accessibility traversal.
7264     * A screen-reader must visit the content of this view before the content of the one
7265     * it precedes. For example, if view B is set to be before view A, then a screen-reader
7266     * will traverse the entire content of B before traversing the entire content of A,
7267     * regardles of what traversal strategy it is using.
7268     * <p>
7269     * Views that do not have specified before/after relationships are traversed in order
7270     * determined by the screen-reader.
7271     * </p>
7272     * <p>
7273     * Setting that this view is before a view that is not important for accessibility
7274     * or if this view is not important for accessibility will have no effect as the
7275     * screen-reader is not aware of unimportant views.
7276     * </p>
7277     *
7278     * @param beforeId The id of a view this one precedes in accessibility traversal.
7279     *
7280     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
7281     *
7282     * @see #setImportantForAccessibility(int)
7283     */
7284    @RemotableViewMethod
7285    public void setAccessibilityTraversalBefore(int beforeId) {
7286        if (mAccessibilityTraversalBeforeId == beforeId) {
7287            return;
7288        }
7289        mAccessibilityTraversalBeforeId = beforeId;
7290        notifyViewAccessibilityStateChangedIfNeeded(
7291                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7292    }
7293
7294    /**
7295     * Gets the id of a view before which this one is visited in accessibility traversal.
7296     *
7297     * @return The id of a view this one precedes in accessibility traversal if
7298     *         specified, otherwise {@link #NO_ID}.
7299     *
7300     * @see #setAccessibilityTraversalBefore(int)
7301     */
7302    public int getAccessibilityTraversalBefore() {
7303        return mAccessibilityTraversalBeforeId;
7304    }
7305
7306    /**
7307     * Sets the id of a view after which this one is visited in accessibility traversal.
7308     * A screen-reader must visit the content of the other view before the content of this
7309     * one. For example, if view B is set to be after view A, then a screen-reader
7310     * will traverse the entire content of A before traversing the entire content of B,
7311     * regardles of what traversal strategy it is using.
7312     * <p>
7313     * Views that do not have specified before/after relationships are traversed in order
7314     * determined by the screen-reader.
7315     * </p>
7316     * <p>
7317     * Setting that this view is after a view that is not important for accessibility
7318     * or if this view is not important for accessibility will have no effect as the
7319     * screen-reader is not aware of unimportant views.
7320     * </p>
7321     *
7322     * @param afterId The id of a view this one succedees in accessibility traversal.
7323     *
7324     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
7325     *
7326     * @see #setImportantForAccessibility(int)
7327     */
7328    @RemotableViewMethod
7329    public void setAccessibilityTraversalAfter(int afterId) {
7330        if (mAccessibilityTraversalAfterId == afterId) {
7331            return;
7332        }
7333        mAccessibilityTraversalAfterId = afterId;
7334        notifyViewAccessibilityStateChangedIfNeeded(
7335                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7336    }
7337
7338    /**
7339     * Gets the id of a view after which this one is visited in accessibility traversal.
7340     *
7341     * @return The id of a view this one succeedes in accessibility traversal if
7342     *         specified, otherwise {@link #NO_ID}.
7343     *
7344     * @see #setAccessibilityTraversalAfter(int)
7345     */
7346    public int getAccessibilityTraversalAfter() {
7347        return mAccessibilityTraversalAfterId;
7348    }
7349
7350    /**
7351     * Gets the id of a view for which this view serves as a label for
7352     * accessibility purposes.
7353     *
7354     * @return The labeled view id.
7355     */
7356    @ViewDebug.ExportedProperty(category = "accessibility")
7357    public int getLabelFor() {
7358        return mLabelForId;
7359    }
7360
7361    /**
7362     * Sets the id of a view for which this view serves as a label for
7363     * accessibility purposes.
7364     *
7365     * @param id The labeled view id.
7366     */
7367    @RemotableViewMethod
7368    public void setLabelFor(@IdRes int id) {
7369        if (mLabelForId == id) {
7370            return;
7371        }
7372        mLabelForId = id;
7373        if (mLabelForId != View.NO_ID
7374                && mID == View.NO_ID) {
7375            mID = generateViewId();
7376        }
7377        notifyViewAccessibilityStateChangedIfNeeded(
7378                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7379    }
7380
7381    /**
7382     * Invoked whenever this view loses focus, either by losing window focus or by losing
7383     * focus within its window. This method can be used to clear any state tied to the
7384     * focus. For instance, if a button is held pressed with the trackball and the window
7385     * loses focus, this method can be used to cancel the press.
7386     *
7387     * Subclasses of View overriding this method should always call super.onFocusLost().
7388     *
7389     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7390     * @see #onWindowFocusChanged(boolean)
7391     *
7392     * @hide pending API council approval
7393     */
7394    @CallSuper
7395    protected void onFocusLost() {
7396        resetPressedState();
7397    }
7398
7399    private void resetPressedState() {
7400        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7401            return;
7402        }
7403
7404        if (isPressed()) {
7405            setPressed(false);
7406
7407            if (!mHasPerformedLongPress) {
7408                removeLongPressCallback();
7409            }
7410        }
7411    }
7412
7413    /**
7414     * Returns true if this view has focus
7415     *
7416     * @return True if this view has focus, false otherwise.
7417     */
7418    @ViewDebug.ExportedProperty(category = "focus")
7419    public boolean isFocused() {
7420        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7421    }
7422
7423    /**
7424     * Find the view in the hierarchy rooted at this view that currently has
7425     * focus.
7426     *
7427     * @return The view that currently has focus, or null if no focused view can
7428     *         be found.
7429     */
7430    public View findFocus() {
7431        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7432    }
7433
7434    /**
7435     * Indicates whether this view is one of the set of scrollable containers in
7436     * its window.
7437     *
7438     * @return whether this view is one of the set of scrollable containers in
7439     * its window
7440     *
7441     * @attr ref android.R.styleable#View_isScrollContainer
7442     */
7443    public boolean isScrollContainer() {
7444        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7445    }
7446
7447    /**
7448     * Change whether this view is one of the set of scrollable containers in
7449     * its window.  This will be used to determine whether the window can
7450     * resize or must pan when a soft input area is open -- scrollable
7451     * containers allow the window to use resize mode since the container
7452     * will appropriately shrink.
7453     *
7454     * @attr ref android.R.styleable#View_isScrollContainer
7455     */
7456    public void setScrollContainer(boolean isScrollContainer) {
7457        if (isScrollContainer) {
7458            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7459                mAttachInfo.mScrollContainers.add(this);
7460                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7461            }
7462            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7463        } else {
7464            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7465                mAttachInfo.mScrollContainers.remove(this);
7466            }
7467            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7468        }
7469    }
7470
7471    /**
7472     * Returns the quality of the drawing cache.
7473     *
7474     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7475     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7476     *
7477     * @see #setDrawingCacheQuality(int)
7478     * @see #setDrawingCacheEnabled(boolean)
7479     * @see #isDrawingCacheEnabled()
7480     *
7481     * @attr ref android.R.styleable#View_drawingCacheQuality
7482     */
7483    @DrawingCacheQuality
7484    public int getDrawingCacheQuality() {
7485        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7486    }
7487
7488    /**
7489     * Set the drawing cache quality of this view. This value is used only when the
7490     * drawing cache is enabled
7491     *
7492     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7493     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7494     *
7495     * @see #getDrawingCacheQuality()
7496     * @see #setDrawingCacheEnabled(boolean)
7497     * @see #isDrawingCacheEnabled()
7498     *
7499     * @attr ref android.R.styleable#View_drawingCacheQuality
7500     */
7501    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7502        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7503    }
7504
7505    /**
7506     * Returns whether the screen should remain on, corresponding to the current
7507     * value of {@link #KEEP_SCREEN_ON}.
7508     *
7509     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7510     *
7511     * @see #setKeepScreenOn(boolean)
7512     *
7513     * @attr ref android.R.styleable#View_keepScreenOn
7514     */
7515    public boolean getKeepScreenOn() {
7516        return (mViewFlags & KEEP_SCREEN_ON) != 0;
7517    }
7518
7519    /**
7520     * Controls whether the screen should remain on, modifying the
7521     * value of {@link #KEEP_SCREEN_ON}.
7522     *
7523     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7524     *
7525     * @see #getKeepScreenOn()
7526     *
7527     * @attr ref android.R.styleable#View_keepScreenOn
7528     */
7529    public void setKeepScreenOn(boolean keepScreenOn) {
7530        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7531    }
7532
7533    /**
7534     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7535     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7536     *
7537     * @attr ref android.R.styleable#View_nextFocusLeft
7538     */
7539    public int getNextFocusLeftId() {
7540        return mNextFocusLeftId;
7541    }
7542
7543    /**
7544     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7545     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7546     * decide automatically.
7547     *
7548     * @attr ref android.R.styleable#View_nextFocusLeft
7549     */
7550    public void setNextFocusLeftId(int nextFocusLeftId) {
7551        mNextFocusLeftId = nextFocusLeftId;
7552    }
7553
7554    /**
7555     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7556     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7557     *
7558     * @attr ref android.R.styleable#View_nextFocusRight
7559     */
7560    public int getNextFocusRightId() {
7561        return mNextFocusRightId;
7562    }
7563
7564    /**
7565     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7566     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7567     * decide automatically.
7568     *
7569     * @attr ref android.R.styleable#View_nextFocusRight
7570     */
7571    public void setNextFocusRightId(int nextFocusRightId) {
7572        mNextFocusRightId = nextFocusRightId;
7573    }
7574
7575    /**
7576     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7577     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7578     *
7579     * @attr ref android.R.styleable#View_nextFocusUp
7580     */
7581    public int getNextFocusUpId() {
7582        return mNextFocusUpId;
7583    }
7584
7585    /**
7586     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7587     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7588     * decide automatically.
7589     *
7590     * @attr ref android.R.styleable#View_nextFocusUp
7591     */
7592    public void setNextFocusUpId(int nextFocusUpId) {
7593        mNextFocusUpId = nextFocusUpId;
7594    }
7595
7596    /**
7597     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7598     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7599     *
7600     * @attr ref android.R.styleable#View_nextFocusDown
7601     */
7602    public int getNextFocusDownId() {
7603        return mNextFocusDownId;
7604    }
7605
7606    /**
7607     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7608     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7609     * decide automatically.
7610     *
7611     * @attr ref android.R.styleable#View_nextFocusDown
7612     */
7613    public void setNextFocusDownId(int nextFocusDownId) {
7614        mNextFocusDownId = nextFocusDownId;
7615    }
7616
7617    /**
7618     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7619     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7620     *
7621     * @attr ref android.R.styleable#View_nextFocusForward
7622     */
7623    public int getNextFocusForwardId() {
7624        return mNextFocusForwardId;
7625    }
7626
7627    /**
7628     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7629     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7630     * decide automatically.
7631     *
7632     * @attr ref android.R.styleable#View_nextFocusForward
7633     */
7634    public void setNextFocusForwardId(int nextFocusForwardId) {
7635        mNextFocusForwardId = nextFocusForwardId;
7636    }
7637
7638    /**
7639     * Returns the visibility of this view and all of its ancestors
7640     *
7641     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7642     */
7643    public boolean isShown() {
7644        View current = this;
7645        //noinspection ConstantConditions
7646        do {
7647            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7648                return false;
7649            }
7650            ViewParent parent = current.mParent;
7651            if (parent == null) {
7652                return false; // We are not attached to the view root
7653            }
7654            if (!(parent instanceof View)) {
7655                return true;
7656            }
7657            current = (View) parent;
7658        } while (current != null);
7659
7660        return false;
7661    }
7662
7663    /**
7664     * Called by the view hierarchy when the content insets for a window have
7665     * changed, to allow it to adjust its content to fit within those windows.
7666     * The content insets tell you the space that the status bar, input method,
7667     * and other system windows infringe on the application's window.
7668     *
7669     * <p>You do not normally need to deal with this function, since the default
7670     * window decoration given to applications takes care of applying it to the
7671     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7672     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7673     * and your content can be placed under those system elements.  You can then
7674     * use this method within your view hierarchy if you have parts of your UI
7675     * which you would like to ensure are not being covered.
7676     *
7677     * <p>The default implementation of this method simply applies the content
7678     * insets to the view's padding, consuming that content (modifying the
7679     * insets to be 0), and returning true.  This behavior is off by default, but can
7680     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7681     *
7682     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7683     * insets object is propagated down the hierarchy, so any changes made to it will
7684     * be seen by all following views (including potentially ones above in
7685     * the hierarchy since this is a depth-first traversal).  The first view
7686     * that returns true will abort the entire traversal.
7687     *
7688     * <p>The default implementation works well for a situation where it is
7689     * used with a container that covers the entire window, allowing it to
7690     * apply the appropriate insets to its content on all edges.  If you need
7691     * a more complicated layout (such as two different views fitting system
7692     * windows, one on the top of the window, and one on the bottom),
7693     * you can override the method and handle the insets however you would like.
7694     * Note that the insets provided by the framework are always relative to the
7695     * far edges of the window, not accounting for the location of the called view
7696     * within that window.  (In fact when this method is called you do not yet know
7697     * where the layout will place the view, as it is done before layout happens.)
7698     *
7699     * <p>Note: unlike many View methods, there is no dispatch phase to this
7700     * call.  If you are overriding it in a ViewGroup and want to allow the
7701     * call to continue to your children, you must be sure to call the super
7702     * implementation.
7703     *
7704     * <p>Here is a sample layout that makes use of fitting system windows
7705     * to have controls for a video view placed inside of the window decorations
7706     * that it hides and shows.  This can be used with code like the second
7707     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7708     *
7709     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7710     *
7711     * @param insets Current content insets of the window.  Prior to
7712     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7713     * the insets or else you and Android will be unhappy.
7714     *
7715     * @return {@code true} if this view applied the insets and it should not
7716     * continue propagating further down the hierarchy, {@code false} otherwise.
7717     * @see #getFitsSystemWindows()
7718     * @see #setFitsSystemWindows(boolean)
7719     * @see #setSystemUiVisibility(int)
7720     *
7721     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7722     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7723     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7724     * to implement handling their own insets.
7725     */
7726    @Deprecated
7727    protected boolean fitSystemWindows(Rect insets) {
7728        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7729            if (insets == null) {
7730                // Null insets by definition have already been consumed.
7731                // This call cannot apply insets since there are none to apply,
7732                // so return false.
7733                return false;
7734            }
7735            // If we're not in the process of dispatching the newer apply insets call,
7736            // that means we're not in the compatibility path. Dispatch into the newer
7737            // apply insets path and take things from there.
7738            try {
7739                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7740                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7741            } finally {
7742                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7743            }
7744        } else {
7745            // We're being called from the newer apply insets path.
7746            // Perform the standard fallback behavior.
7747            return fitSystemWindowsInt(insets);
7748        }
7749    }
7750
7751    private boolean fitSystemWindowsInt(Rect insets) {
7752        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7753            mUserPaddingStart = UNDEFINED_PADDING;
7754            mUserPaddingEnd = UNDEFINED_PADDING;
7755            Rect localInsets = sThreadLocal.get();
7756            if (localInsets == null) {
7757                localInsets = new Rect();
7758                sThreadLocal.set(localInsets);
7759            }
7760            boolean res = computeFitSystemWindows(insets, localInsets);
7761            mUserPaddingLeftInitial = localInsets.left;
7762            mUserPaddingRightInitial = localInsets.right;
7763            internalSetPadding(localInsets.left, localInsets.top,
7764                    localInsets.right, localInsets.bottom);
7765            return res;
7766        }
7767        return false;
7768    }
7769
7770    /**
7771     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7772     *
7773     * <p>This method should be overridden by views that wish to apply a policy different from or
7774     * in addition to the default behavior. Clients that wish to force a view subtree
7775     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7776     *
7777     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7778     * it will be called during dispatch instead of this method. The listener may optionally
7779     * call this method from its own implementation if it wishes to apply the view's default
7780     * insets policy in addition to its own.</p>
7781     *
7782     * <p>Implementations of this method should either return the insets parameter unchanged
7783     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7784     * that this view applied itself. This allows new inset types added in future platform
7785     * versions to pass through existing implementations unchanged without being erroneously
7786     * consumed.</p>
7787     *
7788     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7789     * property is set then the view will consume the system window insets and apply them
7790     * as padding for the view.</p>
7791     *
7792     * @param insets Insets to apply
7793     * @return The supplied insets with any applied insets consumed
7794     */
7795    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7796        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7797            // We weren't called from within a direct call to fitSystemWindows,
7798            // call into it as a fallback in case we're in a class that overrides it
7799            // and has logic to perform.
7800            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7801                return insets.consumeSystemWindowInsets();
7802            }
7803        } else {
7804            // We were called from within a direct call to fitSystemWindows.
7805            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7806                return insets.consumeSystemWindowInsets();
7807            }
7808        }
7809        return insets;
7810    }
7811
7812    /**
7813     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7814     * window insets to this view. The listener's
7815     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7816     * method will be called instead of the view's
7817     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7818     *
7819     * @param listener Listener to set
7820     *
7821     * @see #onApplyWindowInsets(WindowInsets)
7822     */
7823    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7824        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7825    }
7826
7827    /**
7828     * Request to apply the given window insets to this view or another view in its subtree.
7829     *
7830     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7831     * obscured by window decorations or overlays. This can include the status and navigation bars,
7832     * action bars, input methods and more. New inset categories may be added in the future.
7833     * The method returns the insets provided minus any that were applied by this view or its
7834     * children.</p>
7835     *
7836     * <p>Clients wishing to provide custom behavior should override the
7837     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7838     * {@link OnApplyWindowInsetsListener} via the
7839     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7840     * method.</p>
7841     *
7842     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7843     * </p>
7844     *
7845     * @param insets Insets to apply
7846     * @return The provided insets minus the insets that were consumed
7847     */
7848    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7849        try {
7850            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7851            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7852                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7853            } else {
7854                return onApplyWindowInsets(insets);
7855            }
7856        } finally {
7857            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7858        }
7859    }
7860
7861    /**
7862     * Compute the view's coordinate within the surface.
7863     *
7864     * <p>Computes the coordinates of this view in its surface. The argument
7865     * must be an array of two integers. After the method returns, the array
7866     * contains the x and y location in that order.</p>
7867     * @hide
7868     * @param location an array of two integers in which to hold the coordinates
7869     */
7870    public void getLocationInSurface(@Size(2) int[] location) {
7871        getLocationInWindow(location);
7872        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
7873            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
7874            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
7875        }
7876    }
7877
7878    /**
7879     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7880     * only available if the view is attached.
7881     *
7882     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7883     */
7884    public WindowInsets getRootWindowInsets() {
7885        if (mAttachInfo != null) {
7886            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7887        }
7888        return null;
7889    }
7890
7891    /**
7892     * @hide Compute the insets that should be consumed by this view and the ones
7893     * that should propagate to those under it.
7894     */
7895    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7896        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7897                || mAttachInfo == null
7898                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7899                        && !mAttachInfo.mOverscanRequested)) {
7900            outLocalInsets.set(inoutInsets);
7901            inoutInsets.set(0, 0, 0, 0);
7902            return true;
7903        } else {
7904            // The application wants to take care of fitting system window for
7905            // the content...  however we still need to take care of any overscan here.
7906            final Rect overscan = mAttachInfo.mOverscanInsets;
7907            outLocalInsets.set(overscan);
7908            inoutInsets.left -= overscan.left;
7909            inoutInsets.top -= overscan.top;
7910            inoutInsets.right -= overscan.right;
7911            inoutInsets.bottom -= overscan.bottom;
7912            return false;
7913        }
7914    }
7915
7916    /**
7917     * Compute insets that should be consumed by this view and the ones that should propagate
7918     * to those under it.
7919     *
7920     * @param in Insets currently being processed by this View, likely received as a parameter
7921     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7922     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7923     *                       by this view
7924     * @return Insets that should be passed along to views under this one
7925     */
7926    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7927        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7928                || mAttachInfo == null
7929                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7930            outLocalInsets.set(in.getSystemWindowInsets());
7931            return in.consumeSystemWindowInsets();
7932        } else {
7933            outLocalInsets.set(0, 0, 0, 0);
7934            return in;
7935        }
7936    }
7937
7938    /**
7939     * Sets whether or not this view should account for system screen decorations
7940     * such as the status bar and inset its content; that is, controlling whether
7941     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7942     * executed.  See that method for more details.
7943     *
7944     * <p>Note that if you are providing your own implementation of
7945     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7946     * flag to true -- your implementation will be overriding the default
7947     * implementation that checks this flag.
7948     *
7949     * @param fitSystemWindows If true, then the default implementation of
7950     * {@link #fitSystemWindows(Rect)} will be executed.
7951     *
7952     * @attr ref android.R.styleable#View_fitsSystemWindows
7953     * @see #getFitsSystemWindows()
7954     * @see #fitSystemWindows(Rect)
7955     * @see #setSystemUiVisibility(int)
7956     */
7957    public void setFitsSystemWindows(boolean fitSystemWindows) {
7958        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7959    }
7960
7961    /**
7962     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7963     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7964     * will be executed.
7965     *
7966     * @return {@code true} if the default implementation of
7967     * {@link #fitSystemWindows(Rect)} will be executed.
7968     *
7969     * @attr ref android.R.styleable#View_fitsSystemWindows
7970     * @see #setFitsSystemWindows(boolean)
7971     * @see #fitSystemWindows(Rect)
7972     * @see #setSystemUiVisibility(int)
7973     */
7974    @ViewDebug.ExportedProperty
7975    public boolean getFitsSystemWindows() {
7976        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7977    }
7978
7979    /** @hide */
7980    public boolean fitsSystemWindows() {
7981        return getFitsSystemWindows();
7982    }
7983
7984    /**
7985     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7986     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7987     */
7988    @Deprecated
7989    public void requestFitSystemWindows() {
7990        if (mParent != null) {
7991            mParent.requestFitSystemWindows();
7992        }
7993    }
7994
7995    /**
7996     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7997     */
7998    public void requestApplyInsets() {
7999        requestFitSystemWindows();
8000    }
8001
8002    /**
8003     * For use by PhoneWindow to make its own system window fitting optional.
8004     * @hide
8005     */
8006    public void makeOptionalFitsSystemWindows() {
8007        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8008    }
8009
8010    /**
8011     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8012     * treat them as such.
8013     * @hide
8014     */
8015    public void getOutsets(Rect outOutsetRect) {
8016        if (mAttachInfo != null) {
8017            outOutsetRect.set(mAttachInfo.mOutsets);
8018        } else {
8019            outOutsetRect.setEmpty();
8020        }
8021    }
8022
8023    /**
8024     * Returns the visibility status for this view.
8025     *
8026     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8027     * @attr ref android.R.styleable#View_visibility
8028     */
8029    @ViewDebug.ExportedProperty(mapping = {
8030        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8031        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8032        @ViewDebug.IntToString(from = GONE,      to = "GONE")
8033    })
8034    @Visibility
8035    public int getVisibility() {
8036        return mViewFlags & VISIBILITY_MASK;
8037    }
8038
8039    /**
8040     * Set the enabled state of this view.
8041     *
8042     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8043     * @attr ref android.R.styleable#View_visibility
8044     */
8045    @RemotableViewMethod
8046    public void setVisibility(@Visibility int visibility) {
8047        setFlags(visibility, VISIBILITY_MASK);
8048    }
8049
8050    /**
8051     * Returns the enabled status for this view. The interpretation of the
8052     * enabled state varies by subclass.
8053     *
8054     * @return True if this view is enabled, false otherwise.
8055     */
8056    @ViewDebug.ExportedProperty
8057    public boolean isEnabled() {
8058        return (mViewFlags & ENABLED_MASK) == ENABLED;
8059    }
8060
8061    /**
8062     * Set the enabled state of this view. The interpretation of the enabled
8063     * state varies by subclass.
8064     *
8065     * @param enabled True if this view is enabled, false otherwise.
8066     */
8067    @RemotableViewMethod
8068    public void setEnabled(boolean enabled) {
8069        if (enabled == isEnabled()) return;
8070
8071        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
8072
8073        /*
8074         * The View most likely has to change its appearance, so refresh
8075         * the drawable state.
8076         */
8077        refreshDrawableState();
8078
8079        // Invalidate too, since the default behavior for views is to be
8080        // be drawn at 50% alpha rather than to change the drawable.
8081        invalidate(true);
8082
8083        if (!enabled) {
8084            cancelPendingInputEvents();
8085        }
8086    }
8087
8088    /**
8089     * Set whether this view can receive the focus.
8090     *
8091     * Setting this to false will also ensure that this view is not focusable
8092     * in touch mode.
8093     *
8094     * @param focusable If true, this view can receive the focus.
8095     *
8096     * @see #setFocusableInTouchMode(boolean)
8097     * @attr ref android.R.styleable#View_focusable
8098     */
8099    public void setFocusable(boolean focusable) {
8100        if (!focusable) {
8101            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
8102        }
8103        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
8104    }
8105
8106    /**
8107     * Set whether this view can receive focus while in touch mode.
8108     *
8109     * Setting this to true will also ensure that this view is focusable.
8110     *
8111     * @param focusableInTouchMode If true, this view can receive the focus while
8112     *   in touch mode.
8113     *
8114     * @see #setFocusable(boolean)
8115     * @attr ref android.R.styleable#View_focusableInTouchMode
8116     */
8117    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
8118        // Focusable in touch mode should always be set before the focusable flag
8119        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
8120        // which, in touch mode, will not successfully request focus on this view
8121        // because the focusable in touch mode flag is not set
8122        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
8123        if (focusableInTouchMode) {
8124            setFlags(FOCUSABLE, FOCUSABLE_MASK);
8125        }
8126    }
8127
8128    /**
8129     * Set whether this view should have sound effects enabled for events such as
8130     * clicking and touching.
8131     *
8132     * <p>You may wish to disable sound effects for a view if you already play sounds,
8133     * for instance, a dial key that plays dtmf tones.
8134     *
8135     * @param soundEffectsEnabled whether sound effects are enabled for this view.
8136     * @see #isSoundEffectsEnabled()
8137     * @see #playSoundEffect(int)
8138     * @attr ref android.R.styleable#View_soundEffectsEnabled
8139     */
8140    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
8141        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
8142    }
8143
8144    /**
8145     * @return whether this view should have sound effects enabled for events such as
8146     *     clicking and touching.
8147     *
8148     * @see #setSoundEffectsEnabled(boolean)
8149     * @see #playSoundEffect(int)
8150     * @attr ref android.R.styleable#View_soundEffectsEnabled
8151     */
8152    @ViewDebug.ExportedProperty
8153    public boolean isSoundEffectsEnabled() {
8154        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
8155    }
8156
8157    /**
8158     * Set whether this view should have haptic feedback for events such as
8159     * long presses.
8160     *
8161     * <p>You may wish to disable haptic feedback if your view already controls
8162     * its own haptic feedback.
8163     *
8164     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
8165     * @see #isHapticFeedbackEnabled()
8166     * @see #performHapticFeedback(int)
8167     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8168     */
8169    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
8170        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
8171    }
8172
8173    /**
8174     * @return whether this view should have haptic feedback enabled for events
8175     * long presses.
8176     *
8177     * @see #setHapticFeedbackEnabled(boolean)
8178     * @see #performHapticFeedback(int)
8179     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8180     */
8181    @ViewDebug.ExportedProperty
8182    public boolean isHapticFeedbackEnabled() {
8183        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
8184    }
8185
8186    /**
8187     * Returns the layout direction for this view.
8188     *
8189     * @return One of {@link #LAYOUT_DIRECTION_LTR},
8190     *   {@link #LAYOUT_DIRECTION_RTL},
8191     *   {@link #LAYOUT_DIRECTION_INHERIT} or
8192     *   {@link #LAYOUT_DIRECTION_LOCALE}.
8193     *
8194     * @attr ref android.R.styleable#View_layoutDirection
8195     *
8196     * @hide
8197     */
8198    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8199        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
8200        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
8201        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
8202        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
8203    })
8204    @LayoutDir
8205    public int getRawLayoutDirection() {
8206        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
8207    }
8208
8209    /**
8210     * Set the layout direction for this view. This will propagate a reset of layout direction
8211     * resolution to the view's children and resolve layout direction for this view.
8212     *
8213     * @param layoutDirection the layout direction to set. Should be one of:
8214     *
8215     * {@link #LAYOUT_DIRECTION_LTR},
8216     * {@link #LAYOUT_DIRECTION_RTL},
8217     * {@link #LAYOUT_DIRECTION_INHERIT},
8218     * {@link #LAYOUT_DIRECTION_LOCALE}.
8219     *
8220     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
8221     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
8222     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
8223     *
8224     * @attr ref android.R.styleable#View_layoutDirection
8225     */
8226    @RemotableViewMethod
8227    public void setLayoutDirection(@LayoutDir int layoutDirection) {
8228        if (getRawLayoutDirection() != layoutDirection) {
8229            // Reset the current layout direction and the resolved one
8230            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
8231            resetRtlProperties();
8232            // Set the new layout direction (filtered)
8233            mPrivateFlags2 |=
8234                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
8235            // We need to resolve all RTL properties as they all depend on layout direction
8236            resolveRtlPropertiesIfNeeded();
8237            requestLayout();
8238            invalidate(true);
8239        }
8240    }
8241
8242    /**
8243     * Returns the resolved layout direction for this view.
8244     *
8245     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
8246     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
8247     *
8248     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
8249     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
8250     *
8251     * @attr ref android.R.styleable#View_layoutDirection
8252     */
8253    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8254        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
8255        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
8256    })
8257    @ResolvedLayoutDir
8258    public int getLayoutDirection() {
8259        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
8260        if (targetSdkVersion < JELLY_BEAN_MR1) {
8261            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
8262            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
8263        }
8264        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
8265                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
8266    }
8267
8268    /**
8269     * Indicates whether or not this view's layout is right-to-left. This is resolved from
8270     * layout attribute and/or the inherited value from the parent
8271     *
8272     * @return true if the layout is right-to-left.
8273     *
8274     * @hide
8275     */
8276    @ViewDebug.ExportedProperty(category = "layout")
8277    public boolean isLayoutRtl() {
8278        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
8279    }
8280
8281    /**
8282     * Indicates whether the view is currently tracking transient state that the
8283     * app should not need to concern itself with saving and restoring, but that
8284     * the framework should take special note to preserve when possible.
8285     *
8286     * <p>A view with transient state cannot be trivially rebound from an external
8287     * data source, such as an adapter binding item views in a list. This may be
8288     * because the view is performing an animation, tracking user selection
8289     * of content, or similar.</p>
8290     *
8291     * @return true if the view has transient state
8292     */
8293    @ViewDebug.ExportedProperty(category = "layout")
8294    public boolean hasTransientState() {
8295        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
8296    }
8297
8298    /**
8299     * Set whether this view is currently tracking transient state that the
8300     * framework should attempt to preserve when possible. This flag is reference counted,
8301     * so every call to setHasTransientState(true) should be paired with a later call
8302     * to setHasTransientState(false).
8303     *
8304     * <p>A view with transient state cannot be trivially rebound from an external
8305     * data source, such as an adapter binding item views in a list. This may be
8306     * because the view is performing an animation, tracking user selection
8307     * of content, or similar.</p>
8308     *
8309     * @param hasTransientState true if this view has transient state
8310     */
8311    public void setHasTransientState(boolean hasTransientState) {
8312        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
8313                mTransientStateCount - 1;
8314        if (mTransientStateCount < 0) {
8315            mTransientStateCount = 0;
8316            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
8317                    "unmatched pair of setHasTransientState calls");
8318        } else if ((hasTransientState && mTransientStateCount == 1) ||
8319                (!hasTransientState && mTransientStateCount == 0)) {
8320            // update flag if we've just incremented up from 0 or decremented down to 0
8321            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
8322                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
8323            if (mParent != null) {
8324                try {
8325                    mParent.childHasTransientStateChanged(this, hasTransientState);
8326                } catch (AbstractMethodError e) {
8327                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8328                            " does not fully implement ViewParent", e);
8329                }
8330            }
8331        }
8332    }
8333
8334    /**
8335     * Returns true if this view is currently attached to a window.
8336     */
8337    public boolean isAttachedToWindow() {
8338        return mAttachInfo != null;
8339    }
8340
8341    /**
8342     * Returns true if this view has been through at least one layout since it
8343     * was last attached to or detached from a window.
8344     */
8345    public boolean isLaidOut() {
8346        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
8347    }
8348
8349    /**
8350     * If this view doesn't do any drawing on its own, set this flag to
8351     * allow further optimizations. By default, this flag is not set on
8352     * View, but could be set on some View subclasses such as ViewGroup.
8353     *
8354     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8355     * you should clear this flag.
8356     *
8357     * @param willNotDraw whether or not this View draw on its own
8358     */
8359    public void setWillNotDraw(boolean willNotDraw) {
8360        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8361    }
8362
8363    /**
8364     * Returns whether or not this View draws on its own.
8365     *
8366     * @return true if this view has nothing to draw, false otherwise
8367     */
8368    @ViewDebug.ExportedProperty(category = "drawing")
8369    public boolean willNotDraw() {
8370        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8371    }
8372
8373    /**
8374     * When a View's drawing cache is enabled, drawing is redirected to an
8375     * offscreen bitmap. Some views, like an ImageView, must be able to
8376     * bypass this mechanism if they already draw a single bitmap, to avoid
8377     * unnecessary usage of the memory.
8378     *
8379     * @param willNotCacheDrawing true if this view does not cache its
8380     *        drawing, false otherwise
8381     */
8382    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8383        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8384    }
8385
8386    /**
8387     * Returns whether or not this View can cache its drawing or not.
8388     *
8389     * @return true if this view does not cache its drawing, false otherwise
8390     */
8391    @ViewDebug.ExportedProperty(category = "drawing")
8392    public boolean willNotCacheDrawing() {
8393        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8394    }
8395
8396    /**
8397     * Indicates whether this view reacts to click events or not.
8398     *
8399     * @return true if the view is clickable, false otherwise
8400     *
8401     * @see #setClickable(boolean)
8402     * @attr ref android.R.styleable#View_clickable
8403     */
8404    @ViewDebug.ExportedProperty
8405    public boolean isClickable() {
8406        return (mViewFlags & CLICKABLE) == CLICKABLE;
8407    }
8408
8409    /**
8410     * Enables or disables click events for this view. When a view
8411     * is clickable it will change its state to "pressed" on every click.
8412     * Subclasses should set the view clickable to visually react to
8413     * user's clicks.
8414     *
8415     * @param clickable true to make the view clickable, false otherwise
8416     *
8417     * @see #isClickable()
8418     * @attr ref android.R.styleable#View_clickable
8419     */
8420    public void setClickable(boolean clickable) {
8421        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8422    }
8423
8424    /**
8425     * Indicates whether this view reacts to long click events or not.
8426     *
8427     * @return true if the view is long clickable, false otherwise
8428     *
8429     * @see #setLongClickable(boolean)
8430     * @attr ref android.R.styleable#View_longClickable
8431     */
8432    public boolean isLongClickable() {
8433        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8434    }
8435
8436    /**
8437     * Enables or disables long click events for this view. When a view is long
8438     * clickable it reacts to the user holding down the button for a longer
8439     * duration than a tap. This event can either launch the listener or a
8440     * context menu.
8441     *
8442     * @param longClickable true to make the view long clickable, false otherwise
8443     * @see #isLongClickable()
8444     * @attr ref android.R.styleable#View_longClickable
8445     */
8446    public void setLongClickable(boolean longClickable) {
8447        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8448    }
8449
8450    /**
8451     * Indicates whether this view reacts to context clicks or not.
8452     *
8453     * @return true if the view is context clickable, false otherwise
8454     * @see #setContextClickable(boolean)
8455     * @attr ref android.R.styleable#View_contextClickable
8456     */
8457    public boolean isContextClickable() {
8458        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8459    }
8460
8461    /**
8462     * Enables or disables context clicking for this view. This event can launch the listener.
8463     *
8464     * @param contextClickable true to make the view react to a context click, false otherwise
8465     * @see #isContextClickable()
8466     * @attr ref android.R.styleable#View_contextClickable
8467     */
8468    public void setContextClickable(boolean contextClickable) {
8469        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8470    }
8471
8472    /**
8473     * Sets the pressed state for this view and provides a touch coordinate for
8474     * animation hinting.
8475     *
8476     * @param pressed Pass true to set the View's internal state to "pressed",
8477     *            or false to reverts the View's internal state from a
8478     *            previously set "pressed" state.
8479     * @param x The x coordinate of the touch that caused the press
8480     * @param y The y coordinate of the touch that caused the press
8481     */
8482    private void setPressed(boolean pressed, float x, float y) {
8483        if (pressed) {
8484            drawableHotspotChanged(x, y);
8485        }
8486
8487        setPressed(pressed);
8488    }
8489
8490    /**
8491     * Sets the pressed state for this view.
8492     *
8493     * @see #isClickable()
8494     * @see #setClickable(boolean)
8495     *
8496     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8497     *        the View's internal state from a previously set "pressed" state.
8498     */
8499    public void setPressed(boolean pressed) {
8500        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8501
8502        if (pressed) {
8503            mPrivateFlags |= PFLAG_PRESSED;
8504        } else {
8505            mPrivateFlags &= ~PFLAG_PRESSED;
8506        }
8507
8508        if (needsRefresh) {
8509            refreshDrawableState();
8510        }
8511        dispatchSetPressed(pressed);
8512    }
8513
8514    /**
8515     * Dispatch setPressed to all of this View's children.
8516     *
8517     * @see #setPressed(boolean)
8518     *
8519     * @param pressed The new pressed state
8520     */
8521    protected void dispatchSetPressed(boolean pressed) {
8522    }
8523
8524    /**
8525     * Indicates whether the view is currently in pressed state. Unless
8526     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8527     * the pressed state.
8528     *
8529     * @see #setPressed(boolean)
8530     * @see #isClickable()
8531     * @see #setClickable(boolean)
8532     *
8533     * @return true if the view is currently pressed, false otherwise
8534     */
8535    @ViewDebug.ExportedProperty
8536    public boolean isPressed() {
8537        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8538    }
8539
8540    /**
8541     * @hide
8542     * Indicates whether this view will participate in data collection through
8543     * {@link ViewStructure}.  If true, it will not provide any data
8544     * for itself or its children.  If false, the normal data collection will be allowed.
8545     *
8546     * @return Returns false if assist data collection is not blocked, else true.
8547     *
8548     * @see #setAssistBlocked(boolean)
8549     * @attr ref android.R.styleable#View_assistBlocked
8550     */
8551    public boolean isAssistBlocked() {
8552        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8553    }
8554
8555    /**
8556     * @hide
8557     * Controls whether assist data collection from this view and its children is enabled
8558     * (that is, whether {@link #onProvideStructure} and
8559     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8560     * allowing normal assist collection.  Setting this to false will disable assist collection.
8561     *
8562     * @param enabled Set to true to <em>disable</em> assist data collection, or false
8563     * (the default) to allow it.
8564     *
8565     * @see #isAssistBlocked()
8566     * @see #onProvideStructure
8567     * @see #onProvideVirtualStructure
8568     * @attr ref android.R.styleable#View_assistBlocked
8569     */
8570    public void setAssistBlocked(boolean enabled) {
8571        if (enabled) {
8572            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8573        } else {
8574            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8575        }
8576    }
8577
8578    /**
8579     * Indicates whether this view will save its state (that is,
8580     * whether its {@link #onSaveInstanceState} method will be called).
8581     *
8582     * @return Returns true if the view state saving is enabled, else false.
8583     *
8584     * @see #setSaveEnabled(boolean)
8585     * @attr ref android.R.styleable#View_saveEnabled
8586     */
8587    public boolean isSaveEnabled() {
8588        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8589    }
8590
8591    /**
8592     * Controls whether the saving of this view's state is
8593     * enabled (that is, whether its {@link #onSaveInstanceState} method
8594     * will be called).  Note that even if freezing is enabled, the
8595     * view still must have an id assigned to it (via {@link #setId(int)})
8596     * for its state to be saved.  This flag can only disable the
8597     * saving of this view; any child views may still have their state saved.
8598     *
8599     * @param enabled Set to false to <em>disable</em> state saving, or true
8600     * (the default) to allow it.
8601     *
8602     * @see #isSaveEnabled()
8603     * @see #setId(int)
8604     * @see #onSaveInstanceState()
8605     * @attr ref android.R.styleable#View_saveEnabled
8606     */
8607    public void setSaveEnabled(boolean enabled) {
8608        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8609    }
8610
8611    /**
8612     * Gets whether the framework should discard touches when the view's
8613     * window is obscured by another visible window.
8614     * Refer to the {@link View} security documentation for more details.
8615     *
8616     * @return True if touch filtering is enabled.
8617     *
8618     * @see #setFilterTouchesWhenObscured(boolean)
8619     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8620     */
8621    @ViewDebug.ExportedProperty
8622    public boolean getFilterTouchesWhenObscured() {
8623        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8624    }
8625
8626    /**
8627     * Sets whether the framework should discard touches when the view's
8628     * window is obscured by another visible window.
8629     * Refer to the {@link View} security documentation for more details.
8630     *
8631     * @param enabled True if touch filtering should be enabled.
8632     *
8633     * @see #getFilterTouchesWhenObscured
8634     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8635     */
8636    public void setFilterTouchesWhenObscured(boolean enabled) {
8637        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8638                FILTER_TOUCHES_WHEN_OBSCURED);
8639    }
8640
8641    /**
8642     * Indicates whether the entire hierarchy under this view will save its
8643     * state when a state saving traversal occurs from its parent.  The default
8644     * is true; if false, these views will not be saved unless
8645     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8646     *
8647     * @return Returns true if the view state saving from parent is enabled, else false.
8648     *
8649     * @see #setSaveFromParentEnabled(boolean)
8650     */
8651    public boolean isSaveFromParentEnabled() {
8652        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8653    }
8654
8655    /**
8656     * Controls whether the entire hierarchy under this view will save its
8657     * state when a state saving traversal occurs from its parent.  The default
8658     * is true; if false, these views will not be saved unless
8659     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8660     *
8661     * @param enabled Set to false to <em>disable</em> state saving, or true
8662     * (the default) to allow it.
8663     *
8664     * @see #isSaveFromParentEnabled()
8665     * @see #setId(int)
8666     * @see #onSaveInstanceState()
8667     */
8668    public void setSaveFromParentEnabled(boolean enabled) {
8669        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8670    }
8671
8672
8673    /**
8674     * Returns whether this View is able to take focus.
8675     *
8676     * @return True if this view can take focus, or false otherwise.
8677     * @attr ref android.R.styleable#View_focusable
8678     */
8679    @ViewDebug.ExportedProperty(category = "focus")
8680    public final boolean isFocusable() {
8681        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8682    }
8683
8684    /**
8685     * When a view is focusable, it may not want to take focus when in touch mode.
8686     * For example, a button would like focus when the user is navigating via a D-pad
8687     * so that the user can click on it, but once the user starts touching the screen,
8688     * the button shouldn't take focus
8689     * @return Whether the view is focusable in touch mode.
8690     * @attr ref android.R.styleable#View_focusableInTouchMode
8691     */
8692    @ViewDebug.ExportedProperty
8693    public final boolean isFocusableInTouchMode() {
8694        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8695    }
8696
8697    /**
8698     * Find the nearest view in the specified direction that can take focus.
8699     * This does not actually give focus to that view.
8700     *
8701     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8702     *
8703     * @return The nearest focusable in the specified direction, or null if none
8704     *         can be found.
8705     */
8706    public View focusSearch(@FocusRealDirection int direction) {
8707        if (mParent != null) {
8708            return mParent.focusSearch(this, direction);
8709        } else {
8710            return null;
8711        }
8712    }
8713
8714    /**
8715     * This method is the last chance for the focused view and its ancestors to
8716     * respond to an arrow key. This is called when the focused view did not
8717     * consume the key internally, nor could the view system find a new view in
8718     * the requested direction to give focus to.
8719     *
8720     * @param focused The currently focused view.
8721     * @param direction The direction focus wants to move. One of FOCUS_UP,
8722     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8723     * @return True if the this view consumed this unhandled move.
8724     */
8725    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8726        return false;
8727    }
8728
8729    /**
8730     * If a user manually specified the next view id for a particular direction,
8731     * use the root to look up the view.
8732     * @param root The root view of the hierarchy containing this view.
8733     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8734     * or FOCUS_BACKWARD.
8735     * @return The user specified next view, or null if there is none.
8736     */
8737    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8738        switch (direction) {
8739            case FOCUS_LEFT:
8740                if (mNextFocusLeftId == View.NO_ID) return null;
8741                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8742            case FOCUS_RIGHT:
8743                if (mNextFocusRightId == View.NO_ID) return null;
8744                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8745            case FOCUS_UP:
8746                if (mNextFocusUpId == View.NO_ID) return null;
8747                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8748            case FOCUS_DOWN:
8749                if (mNextFocusDownId == View.NO_ID) return null;
8750                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8751            case FOCUS_FORWARD:
8752                if (mNextFocusForwardId == View.NO_ID) return null;
8753                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8754            case FOCUS_BACKWARD: {
8755                if (mID == View.NO_ID) return null;
8756                final int id = mID;
8757                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8758                    @Override
8759                    public boolean apply(View t) {
8760                        return t.mNextFocusForwardId == id;
8761                    }
8762                });
8763            }
8764        }
8765        return null;
8766    }
8767
8768    private View findViewInsideOutShouldExist(View root, int id) {
8769        if (mMatchIdPredicate == null) {
8770            mMatchIdPredicate = new MatchIdPredicate();
8771        }
8772        mMatchIdPredicate.mId = id;
8773        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8774        if (result == null) {
8775            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8776        }
8777        return result;
8778    }
8779
8780    /**
8781     * Find and return all focusable views that are descendants of this view,
8782     * possibly including this view if it is focusable itself.
8783     *
8784     * @param direction The direction of the focus
8785     * @return A list of focusable views
8786     */
8787    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8788        ArrayList<View> result = new ArrayList<View>(24);
8789        addFocusables(result, direction);
8790        return result;
8791    }
8792
8793    /**
8794     * Add any focusable views that are descendants of this view (possibly
8795     * including this view if it is focusable itself) to views.  If we are in touch mode,
8796     * only add views that are also focusable in touch mode.
8797     *
8798     * @param views Focusable views found so far
8799     * @param direction The direction of the focus
8800     */
8801    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8802        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
8803    }
8804
8805    /**
8806     * Adds any focusable views that are descendants of this view (possibly
8807     * including this view if it is focusable itself) to views. This method
8808     * adds all focusable views regardless if we are in touch mode or
8809     * only views focusable in touch mode if we are in touch mode or
8810     * only views that can take accessibility focus if accessibility is enabled
8811     * depending on the focusable mode parameter.
8812     *
8813     * @param views Focusable views found so far or null if all we are interested is
8814     *        the number of focusables.
8815     * @param direction The direction of the focus.
8816     * @param focusableMode The type of focusables to be added.
8817     *
8818     * @see #FOCUSABLES_ALL
8819     * @see #FOCUSABLES_TOUCH_MODE
8820     */
8821    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8822            @FocusableMode int focusableMode) {
8823        if (views == null) {
8824            return;
8825        }
8826        if (!isFocusable()) {
8827            return;
8828        }
8829        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8830                && !isFocusableInTouchMode()) {
8831            return;
8832        }
8833        views.add(this);
8834    }
8835
8836    /**
8837     * Finds the Views that contain given text. The containment is case insensitive.
8838     * The search is performed by either the text that the View renders or the content
8839     * description that describes the view for accessibility purposes and the view does
8840     * not render or both. Clients can specify how the search is to be performed via
8841     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8842     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8843     *
8844     * @param outViews The output list of matching Views.
8845     * @param searched The text to match against.
8846     *
8847     * @see #FIND_VIEWS_WITH_TEXT
8848     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8849     * @see #setContentDescription(CharSequence)
8850     */
8851    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8852            @FindViewFlags int flags) {
8853        if (getAccessibilityNodeProvider() != null) {
8854            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8855                outViews.add(this);
8856            }
8857        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8858                && (searched != null && searched.length() > 0)
8859                && (mContentDescription != null && mContentDescription.length() > 0)) {
8860            String searchedLowerCase = searched.toString().toLowerCase();
8861            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8862            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8863                outViews.add(this);
8864            }
8865        }
8866    }
8867
8868    /**
8869     * Find and return all touchable views that are descendants of this view,
8870     * possibly including this view if it is touchable itself.
8871     *
8872     * @return A list of touchable views
8873     */
8874    public ArrayList<View> getTouchables() {
8875        ArrayList<View> result = new ArrayList<View>();
8876        addTouchables(result);
8877        return result;
8878    }
8879
8880    /**
8881     * Add any touchable views that are descendants of this view (possibly
8882     * including this view if it is touchable itself) to views.
8883     *
8884     * @param views Touchable views found so far
8885     */
8886    public void addTouchables(ArrayList<View> views) {
8887        final int viewFlags = mViewFlags;
8888
8889        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8890                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8891                && (viewFlags & ENABLED_MASK) == ENABLED) {
8892            views.add(this);
8893        }
8894    }
8895
8896    /**
8897     * Returns whether this View is accessibility focused.
8898     *
8899     * @return True if this View is accessibility focused.
8900     */
8901    public boolean isAccessibilityFocused() {
8902        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8903    }
8904
8905    /**
8906     * Call this to try to give accessibility focus to this view.
8907     *
8908     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8909     * returns false or the view is no visible or the view already has accessibility
8910     * focus.
8911     *
8912     * See also {@link #focusSearch(int)}, which is what you call to say that you
8913     * have focus, and you want your parent to look for the next one.
8914     *
8915     * @return Whether this view actually took accessibility focus.
8916     *
8917     * @hide
8918     */
8919    public boolean requestAccessibilityFocus() {
8920        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8921        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8922            return false;
8923        }
8924        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8925            return false;
8926        }
8927        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8928            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8929            ViewRootImpl viewRootImpl = getViewRootImpl();
8930            if (viewRootImpl != null) {
8931                viewRootImpl.setAccessibilityFocus(this, null);
8932            }
8933            invalidate();
8934            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8935            return true;
8936        }
8937        return false;
8938    }
8939
8940    /**
8941     * Call this to try to clear accessibility focus of this view.
8942     *
8943     * See also {@link #focusSearch(int)}, which is what you call to say that you
8944     * have focus, and you want your parent to look for the next one.
8945     *
8946     * @hide
8947     */
8948    public void clearAccessibilityFocus() {
8949        clearAccessibilityFocusNoCallbacks(0);
8950
8951        // Clear the global reference of accessibility focus if this view or
8952        // any of its descendants had accessibility focus. This will NOT send
8953        // an event or update internal state if focus is cleared from a
8954        // descendant view, which may leave views in inconsistent states.
8955        final ViewRootImpl viewRootImpl = getViewRootImpl();
8956        if (viewRootImpl != null) {
8957            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8958            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8959                viewRootImpl.setAccessibilityFocus(null, null);
8960            }
8961        }
8962    }
8963
8964    private void sendAccessibilityHoverEvent(int eventType) {
8965        // Since we are not delivering to a client accessibility events from not
8966        // important views (unless the clinet request that) we need to fire the
8967        // event from the deepest view exposed to the client. As a consequence if
8968        // the user crosses a not exposed view the client will see enter and exit
8969        // of the exposed predecessor followed by and enter and exit of that same
8970        // predecessor when entering and exiting the not exposed descendant. This
8971        // is fine since the client has a clear idea which view is hovered at the
8972        // price of a couple more events being sent. This is a simple and
8973        // working solution.
8974        View source = this;
8975        while (true) {
8976            if (source.includeForAccessibility()) {
8977                source.sendAccessibilityEvent(eventType);
8978                return;
8979            }
8980            ViewParent parent = source.getParent();
8981            if (parent instanceof View) {
8982                source = (View) parent;
8983            } else {
8984                return;
8985            }
8986        }
8987    }
8988
8989    /**
8990     * Clears accessibility focus without calling any callback methods
8991     * normally invoked in {@link #clearAccessibilityFocus()}. This method
8992     * is used separately from that one for clearing accessibility focus when
8993     * giving this focus to another view.
8994     *
8995     * @param action The action, if any, that led to focus being cleared. Set to
8996     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
8997     * the window.
8998     */
8999    void clearAccessibilityFocusNoCallbacks(int action) {
9000        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
9001            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
9002            invalidate();
9003            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9004                AccessibilityEvent event = AccessibilityEvent.obtain(
9005                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
9006                event.setAction(action);
9007                if (mAccessibilityDelegate != null) {
9008                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
9009                } else {
9010                    sendAccessibilityEventUnchecked(event);
9011                }
9012            }
9013        }
9014    }
9015
9016    /**
9017     * Call this to try to give focus to a specific view or to one of its
9018     * descendants.
9019     *
9020     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9021     * false), or if it is focusable and it is not focusable in touch mode
9022     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9023     *
9024     * See also {@link #focusSearch(int)}, which is what you call to say that you
9025     * have focus, and you want your parent to look for the next one.
9026     *
9027     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
9028     * {@link #FOCUS_DOWN} and <code>null</code>.
9029     *
9030     * @return Whether this view or one of its descendants actually took focus.
9031     */
9032    public final boolean requestFocus() {
9033        return requestFocus(View.FOCUS_DOWN);
9034    }
9035
9036    /**
9037     * Call this to try to give focus to a specific view or to one of its
9038     * descendants and give it a hint about what direction focus is heading.
9039     *
9040     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9041     * false), or if it is focusable and it is not focusable in touch mode
9042     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9043     *
9044     * See also {@link #focusSearch(int)}, which is what you call to say that you
9045     * have focus, and you want your parent to look for the next one.
9046     *
9047     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
9048     * <code>null</code> set for the previously focused rectangle.
9049     *
9050     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9051     * @return Whether this view or one of its descendants actually took focus.
9052     */
9053    public final boolean requestFocus(int direction) {
9054        return requestFocus(direction, null);
9055    }
9056
9057    /**
9058     * Call this to try to give focus to a specific view or to one of its descendants
9059     * and give it hints about the direction and a specific rectangle that the focus
9060     * is coming from.  The rectangle can help give larger views a finer grained hint
9061     * about where focus is coming from, and therefore, where to show selection, or
9062     * forward focus change internally.
9063     *
9064     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9065     * false), or if it is focusable and it is not focusable in touch mode
9066     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9067     *
9068     * A View will not take focus if it is not visible.
9069     *
9070     * A View will not take focus if one of its parents has
9071     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
9072     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
9073     *
9074     * See also {@link #focusSearch(int)}, which is what you call to say that you
9075     * have focus, and you want your parent to look for the next one.
9076     *
9077     * You may wish to override this method if your custom {@link View} has an internal
9078     * {@link View} that it wishes to forward the request to.
9079     *
9080     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9081     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
9082     *        to give a finer grained hint about where focus is coming from.  May be null
9083     *        if there is no hint.
9084     * @return Whether this view or one of its descendants actually took focus.
9085     */
9086    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
9087        return requestFocusNoSearch(direction, previouslyFocusedRect);
9088    }
9089
9090    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
9091        // need to be focusable
9092        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
9093                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9094            return false;
9095        }
9096
9097        // need to be focusable in touch mode if in touch mode
9098        if (isInTouchMode() &&
9099            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
9100               return false;
9101        }
9102
9103        // need to not have any parents blocking us
9104        if (hasAncestorThatBlocksDescendantFocus()) {
9105            return false;
9106        }
9107
9108        handleFocusGainInternal(direction, previouslyFocusedRect);
9109        return true;
9110    }
9111
9112    /**
9113     * Call this to try to give focus to a specific view or to one of its descendants. This is a
9114     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
9115     * touch mode to request focus when they are touched.
9116     *
9117     * @return Whether this view or one of its descendants actually took focus.
9118     *
9119     * @see #isInTouchMode()
9120     *
9121     */
9122    public final boolean requestFocusFromTouch() {
9123        // Leave touch mode if we need to
9124        if (isInTouchMode()) {
9125            ViewRootImpl viewRoot = getViewRootImpl();
9126            if (viewRoot != null) {
9127                viewRoot.ensureTouchMode(false);
9128            }
9129        }
9130        return requestFocus(View.FOCUS_DOWN);
9131    }
9132
9133    /**
9134     * @return Whether any ancestor of this view blocks descendant focus.
9135     */
9136    private boolean hasAncestorThatBlocksDescendantFocus() {
9137        final boolean focusableInTouchMode = isFocusableInTouchMode();
9138        ViewParent ancestor = mParent;
9139        while (ancestor instanceof ViewGroup) {
9140            final ViewGroup vgAncestor = (ViewGroup) ancestor;
9141            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
9142                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
9143                return true;
9144            } else {
9145                ancestor = vgAncestor.getParent();
9146            }
9147        }
9148        return false;
9149    }
9150
9151    /**
9152     * Gets the mode for determining whether this View is important for accessibility
9153     * which is if it fires accessibility events and if it is reported to
9154     * accessibility services that query the screen.
9155     *
9156     * @return The mode for determining whether a View is important for accessibility.
9157     *
9158     * @attr ref android.R.styleable#View_importantForAccessibility
9159     *
9160     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9161     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9162     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9163     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9164     */
9165    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
9166            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
9167            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
9168            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
9169            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
9170                    to = "noHideDescendants")
9171        })
9172    public int getImportantForAccessibility() {
9173        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9174                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9175    }
9176
9177    /**
9178     * Sets the live region mode for this view. This indicates to accessibility
9179     * services whether they should automatically notify the user about changes
9180     * to the view's content description or text, or to the content descriptions
9181     * or text of the view's children (where applicable).
9182     * <p>
9183     * For example, in a login screen with a TextView that displays an "incorrect
9184     * password" notification, that view should be marked as a live region with
9185     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9186     * <p>
9187     * To disable change notifications for this view, use
9188     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
9189     * mode for most views.
9190     * <p>
9191     * To indicate that the user should be notified of changes, use
9192     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9193     * <p>
9194     * If the view's changes should interrupt ongoing speech and notify the user
9195     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
9196     *
9197     * @param mode The live region mode for this view, one of:
9198     *        <ul>
9199     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
9200     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
9201     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
9202     *        </ul>
9203     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9204     */
9205    public void setAccessibilityLiveRegion(int mode) {
9206        if (mode != getAccessibilityLiveRegion()) {
9207            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9208            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
9209                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9210            notifyViewAccessibilityStateChangedIfNeeded(
9211                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9212        }
9213    }
9214
9215    /**
9216     * Gets the live region mode for this View.
9217     *
9218     * @return The live region mode for the view.
9219     *
9220     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9221     *
9222     * @see #setAccessibilityLiveRegion(int)
9223     */
9224    public int getAccessibilityLiveRegion() {
9225        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
9226                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
9227    }
9228
9229    /**
9230     * Sets how to determine whether this view is important for accessibility
9231     * which is if it fires accessibility events and if it is reported to
9232     * accessibility services that query the screen.
9233     *
9234     * @param mode How to determine whether this view is important for accessibility.
9235     *
9236     * @attr ref android.R.styleable#View_importantForAccessibility
9237     *
9238     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9239     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9240     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9241     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9242     */
9243    public void setImportantForAccessibility(int mode) {
9244        final int oldMode = getImportantForAccessibility();
9245        if (mode != oldMode) {
9246            final boolean hideDescendants =
9247                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
9248
9249            // If this node or its descendants are no longer important, try to
9250            // clear accessibility focus.
9251            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
9252                final View focusHost = findAccessibilityFocusHost(hideDescendants);
9253                if (focusHost != null) {
9254                    focusHost.clearAccessibilityFocus();
9255                }
9256            }
9257
9258            // If we're moving between AUTO and another state, we might not need
9259            // to send a subtree changed notification. We'll store the computed
9260            // importance, since we'll need to check it later to make sure.
9261            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
9262                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
9263            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
9264            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9265            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
9266                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9267            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
9268                notifySubtreeAccessibilityStateChangedIfNeeded();
9269            } else {
9270                notifyViewAccessibilityStateChangedIfNeeded(
9271                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9272            }
9273        }
9274    }
9275
9276    /**
9277     * Returns the view within this view's hierarchy that is hosting
9278     * accessibility focus.
9279     *
9280     * @param searchDescendants whether to search for focus in descendant views
9281     * @return the view hosting accessibility focus, or {@code null}
9282     */
9283    private View findAccessibilityFocusHost(boolean searchDescendants) {
9284        if (isAccessibilityFocusedViewOrHost()) {
9285            return this;
9286        }
9287
9288        if (searchDescendants) {
9289            final ViewRootImpl viewRoot = getViewRootImpl();
9290            if (viewRoot != null) {
9291                final View focusHost = viewRoot.getAccessibilityFocusedHost();
9292                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9293                    return focusHost;
9294                }
9295            }
9296        }
9297
9298        return null;
9299    }
9300
9301    /**
9302     * Computes whether this view should be exposed for accessibility. In
9303     * general, views that are interactive or provide information are exposed
9304     * while views that serve only as containers are hidden.
9305     * <p>
9306     * If an ancestor of this view has importance
9307     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
9308     * returns <code>false</code>.
9309     * <p>
9310     * Otherwise, the value is computed according to the view's
9311     * {@link #getImportantForAccessibility()} value:
9312     * <ol>
9313     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
9314     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
9315     * </code>
9316     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
9317     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
9318     * view satisfies any of the following:
9319     * <ul>
9320     * <li>Is actionable, e.g. {@link #isClickable()},
9321     * {@link #isLongClickable()}, or {@link #isFocusable()}
9322     * <li>Has an {@link AccessibilityDelegate}
9323     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
9324     * {@link OnKeyListener}, etc.
9325     * <li>Is an accessibility live region, e.g.
9326     * {@link #getAccessibilityLiveRegion()} is not
9327     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
9328     * </ul>
9329     * </ol>
9330     *
9331     * @return Whether the view is exposed for accessibility.
9332     * @see #setImportantForAccessibility(int)
9333     * @see #getImportantForAccessibility()
9334     */
9335    public boolean isImportantForAccessibility() {
9336        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9337                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9338        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
9339                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9340            return false;
9341        }
9342
9343        // Check parent mode to ensure we're not hidden.
9344        ViewParent parent = mParent;
9345        while (parent instanceof View) {
9346            if (((View) parent).getImportantForAccessibility()
9347                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9348                return false;
9349            }
9350            parent = parent.getParent();
9351        }
9352
9353        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
9354                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
9355                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
9356    }
9357
9358    /**
9359     * Gets the parent for accessibility purposes. Note that the parent for
9360     * accessibility is not necessary the immediate parent. It is the first
9361     * predecessor that is important for accessibility.
9362     *
9363     * @return The parent for accessibility purposes.
9364     */
9365    public ViewParent getParentForAccessibility() {
9366        if (mParent instanceof View) {
9367            View parentView = (View) mParent;
9368            if (parentView.includeForAccessibility()) {
9369                return mParent;
9370            } else {
9371                return mParent.getParentForAccessibility();
9372            }
9373        }
9374        return null;
9375    }
9376
9377    /**
9378     * Adds the children of this View relevant for accessibility to the given list
9379     * as output. Since some Views are not important for accessibility the added
9380     * child views are not necessarily direct children of this view, rather they are
9381     * the first level of descendants important for accessibility.
9382     *
9383     * @param outChildren The output list that will receive children for accessibility.
9384     */
9385    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
9386
9387    }
9388
9389    /**
9390     * Whether to regard this view for accessibility. A view is regarded for
9391     * accessibility if it is important for accessibility or the querying
9392     * accessibility service has explicitly requested that view not
9393     * important for accessibility are regarded.
9394     *
9395     * @return Whether to regard the view for accessibility.
9396     *
9397     * @hide
9398     */
9399    public boolean includeForAccessibility() {
9400        if (mAttachInfo != null) {
9401            return (mAttachInfo.mAccessibilityFetchFlags
9402                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
9403                    || isImportantForAccessibility();
9404        }
9405        return false;
9406    }
9407
9408    /**
9409     * Returns whether the View is considered actionable from
9410     * accessibility perspective. Such view are important for
9411     * accessibility.
9412     *
9413     * @return True if the view is actionable for accessibility.
9414     *
9415     * @hide
9416     */
9417    public boolean isActionableForAccessibility() {
9418        return (isClickable() || isLongClickable() || isFocusable());
9419    }
9420
9421    /**
9422     * Returns whether the View has registered callbacks which makes it
9423     * important for accessibility.
9424     *
9425     * @return True if the view is actionable for accessibility.
9426     */
9427    private boolean hasListenersForAccessibility() {
9428        ListenerInfo info = getListenerInfo();
9429        return mTouchDelegate != null || info.mOnKeyListener != null
9430                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
9431                || info.mOnHoverListener != null || info.mOnDragListener != null;
9432    }
9433
9434    /**
9435     * Notifies that the accessibility state of this view changed. The change
9436     * is local to this view and does not represent structural changes such
9437     * as children and parent. For example, the view became focusable. The
9438     * notification is at at most once every
9439     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9440     * to avoid unnecessary load to the system. Also once a view has a pending
9441     * notification this method is a NOP until the notification has been sent.
9442     *
9443     * @hide
9444     */
9445    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
9446        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9447            return;
9448        }
9449        if (mSendViewStateChangedAccessibilityEvent == null) {
9450            mSendViewStateChangedAccessibilityEvent =
9451                    new SendViewStateChangedAccessibilityEvent();
9452        }
9453        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9454    }
9455
9456    /**
9457     * Notifies that the accessibility state of this view changed. The change
9458     * is *not* local to this view and does represent structural changes such
9459     * as children and parent. For example, the view size changed. The
9460     * notification is at at most once every
9461     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9462     * to avoid unnecessary load to the system. Also once a view has a pending
9463     * notification this method is a NOP until the notification has been sent.
9464     *
9465     * @hide
9466     */
9467    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9468        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9469            return;
9470        }
9471        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9472            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9473            if (mParent != null) {
9474                try {
9475                    mParent.notifySubtreeAccessibilityStateChanged(
9476                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9477                } catch (AbstractMethodError e) {
9478                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9479                            " does not fully implement ViewParent", e);
9480                }
9481            }
9482        }
9483    }
9484
9485    /**
9486     * Change the visibility of the View without triggering any other changes. This is
9487     * important for transitions, where visibility changes should not adjust focus or
9488     * trigger a new layout. This is only used when the visibility has already been changed
9489     * and we need a transient value during an animation. When the animation completes,
9490     * the original visibility value is always restored.
9491     *
9492     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9493     * @hide
9494     */
9495    public void setTransitionVisibility(@Visibility int visibility) {
9496        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9497    }
9498
9499    /**
9500     * Reset the flag indicating the accessibility state of the subtree rooted
9501     * at this view changed.
9502     */
9503    void resetSubtreeAccessibilityStateChanged() {
9504        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9505    }
9506
9507    /**
9508     * Report an accessibility action to this view's parents for delegated processing.
9509     *
9510     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9511     * call this method to delegate an accessibility action to a supporting parent. If the parent
9512     * returns true from its
9513     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9514     * method this method will return true to signify that the action was consumed.</p>
9515     *
9516     * <p>This method is useful for implementing nested scrolling child views. If
9517     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9518     * a custom view implementation may invoke this method to allow a parent to consume the
9519     * scroll first. If this method returns true the custom view should skip its own scrolling
9520     * behavior.</p>
9521     *
9522     * @param action Accessibility action to delegate
9523     * @param arguments Optional action arguments
9524     * @return true if the action was consumed by a parent
9525     */
9526    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9527        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9528            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9529                return true;
9530            }
9531        }
9532        return false;
9533    }
9534
9535    /**
9536     * Performs the specified accessibility action on the view. For
9537     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9538     * <p>
9539     * If an {@link AccessibilityDelegate} has been specified via calling
9540     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9541     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9542     * is responsible for handling this call.
9543     * </p>
9544     *
9545     * <p>The default implementation will delegate
9546     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9547     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9548     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9549     *
9550     * @param action The action to perform.
9551     * @param arguments Optional action arguments.
9552     * @return Whether the action was performed.
9553     */
9554    public boolean performAccessibilityAction(int action, Bundle arguments) {
9555      if (mAccessibilityDelegate != null) {
9556          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9557      } else {
9558          return performAccessibilityActionInternal(action, arguments);
9559      }
9560    }
9561
9562   /**
9563    * @see #performAccessibilityAction(int, Bundle)
9564    *
9565    * Note: Called from the default {@link AccessibilityDelegate}.
9566    *
9567    * @hide
9568    */
9569    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9570        if (isNestedScrollingEnabled()
9571                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9572                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9573                || action == R.id.accessibilityActionScrollUp
9574                || action == R.id.accessibilityActionScrollLeft
9575                || action == R.id.accessibilityActionScrollDown
9576                || action == R.id.accessibilityActionScrollRight)) {
9577            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9578                return true;
9579            }
9580        }
9581
9582        switch (action) {
9583            case AccessibilityNodeInfo.ACTION_CLICK: {
9584                if (isClickable()) {
9585                    performClick();
9586                    return true;
9587                }
9588            } break;
9589            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9590                if (isLongClickable()) {
9591                    performLongClick();
9592                    return true;
9593                }
9594            } break;
9595            case AccessibilityNodeInfo.ACTION_FOCUS: {
9596                if (!hasFocus()) {
9597                    // Get out of touch mode since accessibility
9598                    // wants to move focus around.
9599                    getViewRootImpl().ensureTouchMode(false);
9600                    return requestFocus();
9601                }
9602            } break;
9603            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9604                if (hasFocus()) {
9605                    clearFocus();
9606                    return !isFocused();
9607                }
9608            } break;
9609            case AccessibilityNodeInfo.ACTION_SELECT: {
9610                if (!isSelected()) {
9611                    setSelected(true);
9612                    return isSelected();
9613                }
9614            } break;
9615            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9616                if (isSelected()) {
9617                    setSelected(false);
9618                    return !isSelected();
9619                }
9620            } break;
9621            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9622                if (!isAccessibilityFocused()) {
9623                    return requestAccessibilityFocus();
9624                }
9625            } break;
9626            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9627                if (isAccessibilityFocused()) {
9628                    clearAccessibilityFocus();
9629                    return true;
9630                }
9631            } break;
9632            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9633                if (arguments != null) {
9634                    final int granularity = arguments.getInt(
9635                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9636                    final boolean extendSelection = arguments.getBoolean(
9637                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9638                    return traverseAtGranularity(granularity, true, extendSelection);
9639                }
9640            } break;
9641            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9642                if (arguments != null) {
9643                    final int granularity = arguments.getInt(
9644                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9645                    final boolean extendSelection = arguments.getBoolean(
9646                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9647                    return traverseAtGranularity(granularity, false, extendSelection);
9648                }
9649            } break;
9650            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9651                CharSequence text = getIterableTextForAccessibility();
9652                if (text == null) {
9653                    return false;
9654                }
9655                final int start = (arguments != null) ? arguments.getInt(
9656                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9657                final int end = (arguments != null) ? arguments.getInt(
9658                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9659                // Only cursor position can be specified (selection length == 0)
9660                if ((getAccessibilitySelectionStart() != start
9661                        || getAccessibilitySelectionEnd() != end)
9662                        && (start == end)) {
9663                    setAccessibilitySelection(start, end);
9664                    notifyViewAccessibilityStateChangedIfNeeded(
9665                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9666                    return true;
9667                }
9668            } break;
9669            case R.id.accessibilityActionShowOnScreen: {
9670                if (mAttachInfo != null) {
9671                    final Rect r = mAttachInfo.mTmpInvalRect;
9672                    getDrawingRect(r);
9673                    return requestRectangleOnScreen(r, true);
9674                }
9675            } break;
9676            case R.id.accessibilityActionContextClick: {
9677                if (isContextClickable()) {
9678                    performContextClick();
9679                    return true;
9680                }
9681            } break;
9682        }
9683        return false;
9684    }
9685
9686    private boolean traverseAtGranularity(int granularity, boolean forward,
9687            boolean extendSelection) {
9688        CharSequence text = getIterableTextForAccessibility();
9689        if (text == null || text.length() == 0) {
9690            return false;
9691        }
9692        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9693        if (iterator == null) {
9694            return false;
9695        }
9696        int current = getAccessibilitySelectionEnd();
9697        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9698            current = forward ? 0 : text.length();
9699        }
9700        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9701        if (range == null) {
9702            return false;
9703        }
9704        final int segmentStart = range[0];
9705        final int segmentEnd = range[1];
9706        int selectionStart;
9707        int selectionEnd;
9708        if (extendSelection && isAccessibilitySelectionExtendable()) {
9709            selectionStart = getAccessibilitySelectionStart();
9710            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9711                selectionStart = forward ? segmentStart : segmentEnd;
9712            }
9713            selectionEnd = forward ? segmentEnd : segmentStart;
9714        } else {
9715            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9716        }
9717        setAccessibilitySelection(selectionStart, selectionEnd);
9718        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9719                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9720        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9721        return true;
9722    }
9723
9724    /**
9725     * Gets the text reported for accessibility purposes.
9726     *
9727     * @return The accessibility text.
9728     *
9729     * @hide
9730     */
9731    public CharSequence getIterableTextForAccessibility() {
9732        return getContentDescription();
9733    }
9734
9735    /**
9736     * Gets whether accessibility selection can be extended.
9737     *
9738     * @return If selection is extensible.
9739     *
9740     * @hide
9741     */
9742    public boolean isAccessibilitySelectionExtendable() {
9743        return false;
9744    }
9745
9746    /**
9747     * @hide
9748     */
9749    public int getAccessibilitySelectionStart() {
9750        return mAccessibilityCursorPosition;
9751    }
9752
9753    /**
9754     * @hide
9755     */
9756    public int getAccessibilitySelectionEnd() {
9757        return getAccessibilitySelectionStart();
9758    }
9759
9760    /**
9761     * @hide
9762     */
9763    public void setAccessibilitySelection(int start, int end) {
9764        if (start ==  end && end == mAccessibilityCursorPosition) {
9765            return;
9766        }
9767        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9768            mAccessibilityCursorPosition = start;
9769        } else {
9770            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9771        }
9772        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9773    }
9774
9775    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9776            int fromIndex, int toIndex) {
9777        if (mParent == null) {
9778            return;
9779        }
9780        AccessibilityEvent event = AccessibilityEvent.obtain(
9781                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9782        onInitializeAccessibilityEvent(event);
9783        onPopulateAccessibilityEvent(event);
9784        event.setFromIndex(fromIndex);
9785        event.setToIndex(toIndex);
9786        event.setAction(action);
9787        event.setMovementGranularity(granularity);
9788        mParent.requestSendAccessibilityEvent(this, event);
9789    }
9790
9791    /**
9792     * @hide
9793     */
9794    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9795        switch (granularity) {
9796            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9797                CharSequence text = getIterableTextForAccessibility();
9798                if (text != null && text.length() > 0) {
9799                    CharacterTextSegmentIterator iterator =
9800                        CharacterTextSegmentIterator.getInstance(
9801                                mContext.getResources().getConfiguration().locale);
9802                    iterator.initialize(text.toString());
9803                    return iterator;
9804                }
9805            } break;
9806            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9807                CharSequence text = getIterableTextForAccessibility();
9808                if (text != null && text.length() > 0) {
9809                    WordTextSegmentIterator iterator =
9810                        WordTextSegmentIterator.getInstance(
9811                                mContext.getResources().getConfiguration().locale);
9812                    iterator.initialize(text.toString());
9813                    return iterator;
9814                }
9815            } break;
9816            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9817                CharSequence text = getIterableTextForAccessibility();
9818                if (text != null && text.length() > 0) {
9819                    ParagraphTextSegmentIterator iterator =
9820                        ParagraphTextSegmentIterator.getInstance();
9821                    iterator.initialize(text.toString());
9822                    return iterator;
9823                }
9824            } break;
9825        }
9826        return null;
9827    }
9828
9829    /**
9830     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
9831     * and {@link #onFinishTemporaryDetach()}.
9832     *
9833     * <p>This method always returns {@code true} when called directly or indirectly from
9834     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
9835     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
9836     * <ul>
9837     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
9838     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
9839     * </ul>
9840     * </p>
9841     *
9842     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
9843     * and {@link #onFinishTemporaryDetach()}.
9844     */
9845    public final boolean isTemporarilyDetached() {
9846        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
9847    }
9848
9849    /**
9850     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
9851     * a container View.
9852     */
9853    @CallSuper
9854    public void dispatchStartTemporaryDetach() {
9855        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
9856        onStartTemporaryDetach();
9857    }
9858
9859    /**
9860     * This is called when a container is going to temporarily detach a child, with
9861     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9862     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9863     * {@link #onDetachedFromWindow()} when the container is done.
9864     */
9865    public void onStartTemporaryDetach() {
9866        removeUnsetPressCallback();
9867        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9868    }
9869
9870    /**
9871     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
9872     * a container View.
9873     */
9874    @CallSuper
9875    public void dispatchFinishTemporaryDetach() {
9876        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
9877        onFinishTemporaryDetach();
9878        if (hasWindowFocus() && hasFocus()) {
9879            InputMethodManager.getInstance().focusIn(this);
9880        }
9881    }
9882
9883    /**
9884     * Called after {@link #onStartTemporaryDetach} when the container is done
9885     * changing the view.
9886     */
9887    public void onFinishTemporaryDetach() {
9888    }
9889
9890    /**
9891     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9892     * for this view's window.  Returns null if the view is not currently attached
9893     * to the window.  Normally you will not need to use this directly, but
9894     * just use the standard high-level event callbacks like
9895     * {@link #onKeyDown(int, KeyEvent)}.
9896     */
9897    public KeyEvent.DispatcherState getKeyDispatcherState() {
9898        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9899    }
9900
9901    /**
9902     * Dispatch a key event before it is processed by any input method
9903     * associated with the view hierarchy.  This can be used to intercept
9904     * key events in special situations before the IME consumes them; a
9905     * typical example would be handling the BACK key to update the application's
9906     * UI instead of allowing the IME to see it and close itself.
9907     *
9908     * @param event The key event to be dispatched.
9909     * @return True if the event was handled, false otherwise.
9910     */
9911    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9912        return onKeyPreIme(event.getKeyCode(), event);
9913    }
9914
9915    /**
9916     * Dispatch a key event to the next view on the focus path. This path runs
9917     * from the top of the view tree down to the currently focused view. If this
9918     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9919     * the next node down the focus path. This method also fires any key
9920     * listeners.
9921     *
9922     * @param event The key event to be dispatched.
9923     * @return True if the event was handled, false otherwise.
9924     */
9925    public boolean dispatchKeyEvent(KeyEvent event) {
9926        if (mInputEventConsistencyVerifier != null) {
9927            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9928        }
9929
9930        // Give any attached key listener a first crack at the event.
9931        //noinspection SimplifiableIfStatement
9932        ListenerInfo li = mListenerInfo;
9933        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9934                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9935            return true;
9936        }
9937
9938        if (event.dispatch(this, mAttachInfo != null
9939                ? mAttachInfo.mKeyDispatchState : null, this)) {
9940            return true;
9941        }
9942
9943        if (mInputEventConsistencyVerifier != null) {
9944            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9945        }
9946        return false;
9947    }
9948
9949    /**
9950     * Dispatches a key shortcut event.
9951     *
9952     * @param event The key event to be dispatched.
9953     * @return True if the event was handled by the view, false otherwise.
9954     */
9955    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9956        return onKeyShortcut(event.getKeyCode(), event);
9957    }
9958
9959    /**
9960     * Pass the touch screen motion event down to the target view, or this
9961     * view if it is the target.
9962     *
9963     * @param event The motion event to be dispatched.
9964     * @return True if the event was handled by the view, false otherwise.
9965     */
9966    public boolean dispatchTouchEvent(MotionEvent event) {
9967        // If the event should be handled by accessibility focus first.
9968        if (event.isTargetAccessibilityFocus()) {
9969            // We don't have focus or no virtual descendant has it, do not handle the event.
9970            if (!isAccessibilityFocusedViewOrHost()) {
9971                return false;
9972            }
9973            // We have focus and got the event, then use normal event dispatch.
9974            event.setTargetAccessibilityFocus(false);
9975        }
9976
9977        boolean result = false;
9978
9979        if (mInputEventConsistencyVerifier != null) {
9980            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9981        }
9982
9983        final int actionMasked = event.getActionMasked();
9984        if (actionMasked == MotionEvent.ACTION_DOWN) {
9985            // Defensive cleanup for new gesture
9986            stopNestedScroll();
9987        }
9988
9989        if (onFilterTouchEventForSecurity(event)) {
9990            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
9991                result = true;
9992            }
9993            //noinspection SimplifiableIfStatement
9994            ListenerInfo li = mListenerInfo;
9995            if (li != null && li.mOnTouchListener != null
9996                    && (mViewFlags & ENABLED_MASK) == ENABLED
9997                    && li.mOnTouchListener.onTouch(this, event)) {
9998                result = true;
9999            }
10000
10001            if (!result && onTouchEvent(event)) {
10002                result = true;
10003            }
10004        }
10005
10006        if (!result && mInputEventConsistencyVerifier != null) {
10007            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10008        }
10009
10010        // Clean up after nested scrolls if this is the end of a gesture;
10011        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
10012        // of the gesture.
10013        if (actionMasked == MotionEvent.ACTION_UP ||
10014                actionMasked == MotionEvent.ACTION_CANCEL ||
10015                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
10016            stopNestedScroll();
10017        }
10018
10019        return result;
10020    }
10021
10022    boolean isAccessibilityFocusedViewOrHost() {
10023        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
10024                .getAccessibilityFocusedHost() == this);
10025    }
10026
10027    /**
10028     * Filter the touch event to apply security policies.
10029     *
10030     * @param event The motion event to be filtered.
10031     * @return True if the event should be dispatched, false if the event should be dropped.
10032     *
10033     * @see #getFilterTouchesWhenObscured
10034     */
10035    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
10036        //noinspection RedundantIfStatement
10037        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
10038                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
10039            // Window is obscured, drop this touch.
10040            return false;
10041        }
10042        return true;
10043    }
10044
10045    /**
10046     * Pass a trackball motion event down to the focused view.
10047     *
10048     * @param event The motion event to be dispatched.
10049     * @return True if the event was handled by the view, false otherwise.
10050     */
10051    public boolean dispatchTrackballEvent(MotionEvent event) {
10052        if (mInputEventConsistencyVerifier != null) {
10053            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
10054        }
10055
10056        return onTrackballEvent(event);
10057    }
10058
10059    /**
10060     * Dispatch a generic motion event.
10061     * <p>
10062     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10063     * are delivered to the view under the pointer.  All other generic motion events are
10064     * delivered to the focused view.  Hover events are handled specially and are delivered
10065     * to {@link #onHoverEvent(MotionEvent)}.
10066     * </p>
10067     *
10068     * @param event The motion event to be dispatched.
10069     * @return True if the event was handled by the view, false otherwise.
10070     */
10071    public boolean dispatchGenericMotionEvent(MotionEvent event) {
10072        if (mInputEventConsistencyVerifier != null) {
10073            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
10074        }
10075
10076        final int source = event.getSource();
10077        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
10078            final int action = event.getAction();
10079            if (action == MotionEvent.ACTION_HOVER_ENTER
10080                    || action == MotionEvent.ACTION_HOVER_MOVE
10081                    || action == MotionEvent.ACTION_HOVER_EXIT) {
10082                if (dispatchHoverEvent(event)) {
10083                    return true;
10084                }
10085            } else if (dispatchGenericPointerEvent(event)) {
10086                return true;
10087            }
10088        } else if (dispatchGenericFocusedEvent(event)) {
10089            return true;
10090        }
10091
10092        if (dispatchGenericMotionEventInternal(event)) {
10093            return true;
10094        }
10095
10096        if (mInputEventConsistencyVerifier != null) {
10097            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10098        }
10099        return false;
10100    }
10101
10102    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
10103        //noinspection SimplifiableIfStatement
10104        ListenerInfo li = mListenerInfo;
10105        if (li != null && li.mOnGenericMotionListener != null
10106                && (mViewFlags & ENABLED_MASK) == ENABLED
10107                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
10108            return true;
10109        }
10110
10111        if (onGenericMotionEvent(event)) {
10112            return true;
10113        }
10114
10115        final int actionButton = event.getActionButton();
10116        switch (event.getActionMasked()) {
10117            case MotionEvent.ACTION_BUTTON_PRESS:
10118                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
10119                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10120                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10121                    if (performContextClick(event.getX(), event.getY())) {
10122                        mInContextButtonPress = true;
10123                        setPressed(true, event.getX(), event.getY());
10124                        removeTapCallback();
10125                        removeLongPressCallback();
10126                        return true;
10127                    }
10128                }
10129                break;
10130
10131            case MotionEvent.ACTION_BUTTON_RELEASE:
10132                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10133                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10134                    mInContextButtonPress = false;
10135                    mIgnoreNextUpEvent = true;
10136                }
10137                break;
10138        }
10139
10140        if (mInputEventConsistencyVerifier != null) {
10141            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10142        }
10143        return false;
10144    }
10145
10146    /**
10147     * Dispatch a hover event.
10148     * <p>
10149     * Do not call this method directly.
10150     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10151     * </p>
10152     *
10153     * @param event The motion event to be dispatched.
10154     * @return True if the event was handled by the view, false otherwise.
10155     */
10156    protected boolean dispatchHoverEvent(MotionEvent event) {
10157        ListenerInfo li = mListenerInfo;
10158        //noinspection SimplifiableIfStatement
10159        if (li != null && li.mOnHoverListener != null
10160                && (mViewFlags & ENABLED_MASK) == ENABLED
10161                && li.mOnHoverListener.onHover(this, event)) {
10162            return true;
10163        }
10164
10165        return onHoverEvent(event);
10166    }
10167
10168    /**
10169     * Returns true if the view has a child to which it has recently sent
10170     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
10171     * it does not have a hovered child, then it must be the innermost hovered view.
10172     * @hide
10173     */
10174    protected boolean hasHoveredChild() {
10175        return false;
10176    }
10177
10178    /**
10179     * Dispatch a generic motion event to the view under the first pointer.
10180     * <p>
10181     * Do not call this method directly.
10182     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10183     * </p>
10184     *
10185     * @param event The motion event to be dispatched.
10186     * @return True if the event was handled by the view, false otherwise.
10187     */
10188    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
10189        return false;
10190    }
10191
10192    /**
10193     * Dispatch a generic motion event to the currently focused view.
10194     * <p>
10195     * Do not call this method directly.
10196     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10197     * </p>
10198     *
10199     * @param event The motion event to be dispatched.
10200     * @return True if the event was handled by the view, false otherwise.
10201     */
10202    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
10203        return false;
10204    }
10205
10206    /**
10207     * Dispatch a pointer event.
10208     * <p>
10209     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
10210     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
10211     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
10212     * and should not be expected to handle other pointing device features.
10213     * </p>
10214     *
10215     * @param event The motion event to be dispatched.
10216     * @return True if the event was handled by the view, false otherwise.
10217     * @hide
10218     */
10219    public final boolean dispatchPointerEvent(MotionEvent event) {
10220        if (event.isTouchEvent()) {
10221            return dispatchTouchEvent(event);
10222        } else {
10223            return dispatchGenericMotionEvent(event);
10224        }
10225    }
10226
10227    /**
10228     * Called when the window containing this view gains or loses window focus.
10229     * ViewGroups should override to route to their children.
10230     *
10231     * @param hasFocus True if the window containing this view now has focus,
10232     *        false otherwise.
10233     */
10234    public void dispatchWindowFocusChanged(boolean hasFocus) {
10235        onWindowFocusChanged(hasFocus);
10236    }
10237
10238    /**
10239     * Called when the window containing this view gains or loses focus.  Note
10240     * that this is separate from view focus: to receive key events, both
10241     * your view and its window must have focus.  If a window is displayed
10242     * on top of yours that takes input focus, then your own window will lose
10243     * focus but the view focus will remain unchanged.
10244     *
10245     * @param hasWindowFocus True if the window containing this view now has
10246     *        focus, false otherwise.
10247     */
10248    public void onWindowFocusChanged(boolean hasWindowFocus) {
10249        InputMethodManager imm = InputMethodManager.peekInstance();
10250        if (!hasWindowFocus) {
10251            if (isPressed()) {
10252                setPressed(false);
10253            }
10254            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10255                imm.focusOut(this);
10256            }
10257            removeLongPressCallback();
10258            removeTapCallback();
10259            onFocusLost();
10260        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10261            imm.focusIn(this);
10262        }
10263        refreshDrawableState();
10264    }
10265
10266    /**
10267     * Returns true if this view is in a window that currently has window focus.
10268     * Note that this is not the same as the view itself having focus.
10269     *
10270     * @return True if this view is in a window that currently has window focus.
10271     */
10272    public boolean hasWindowFocus() {
10273        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
10274    }
10275
10276    /**
10277     * Dispatch a view visibility change down the view hierarchy.
10278     * ViewGroups should override to route to their children.
10279     * @param changedView The view whose visibility changed. Could be 'this' or
10280     * an ancestor view.
10281     * @param visibility The new visibility of changedView: {@link #VISIBLE},
10282     * {@link #INVISIBLE} or {@link #GONE}.
10283     */
10284    protected void dispatchVisibilityChanged(@NonNull View changedView,
10285            @Visibility int visibility) {
10286        onVisibilityChanged(changedView, visibility);
10287    }
10288
10289    /**
10290     * Called when the visibility of the view or an ancestor of the view has
10291     * changed.
10292     *
10293     * @param changedView The view whose visibility changed. May be
10294     *                    {@code this} or an ancestor view.
10295     * @param visibility The new visibility, one of {@link #VISIBLE},
10296     *                   {@link #INVISIBLE} or {@link #GONE}.
10297     */
10298    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
10299    }
10300
10301    /**
10302     * Dispatch a hint about whether this view is displayed. For instance, when
10303     * a View moves out of the screen, it might receives a display hint indicating
10304     * the view is not displayed. Applications should not <em>rely</em> on this hint
10305     * as there is no guarantee that they will receive one.
10306     *
10307     * @param hint A hint about whether or not this view is displayed:
10308     * {@link #VISIBLE} or {@link #INVISIBLE}.
10309     */
10310    public void dispatchDisplayHint(@Visibility int hint) {
10311        onDisplayHint(hint);
10312    }
10313
10314    /**
10315     * Gives this view a hint about whether is displayed or not. For instance, when
10316     * a View moves out of the screen, it might receives a display hint indicating
10317     * the view is not displayed. Applications should not <em>rely</em> on this hint
10318     * as there is no guarantee that they will receive one.
10319     *
10320     * @param hint A hint about whether or not this view is displayed:
10321     * {@link #VISIBLE} or {@link #INVISIBLE}.
10322     */
10323    protected void onDisplayHint(@Visibility int hint) {
10324    }
10325
10326    /**
10327     * Dispatch a window visibility change down the view hierarchy.
10328     * ViewGroups should override to route to their children.
10329     *
10330     * @param visibility The new visibility of the window.
10331     *
10332     * @see #onWindowVisibilityChanged(int)
10333     */
10334    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
10335        onWindowVisibilityChanged(visibility);
10336    }
10337
10338    /**
10339     * Called when the window containing has change its visibility
10340     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
10341     * that this tells you whether or not your window is being made visible
10342     * to the window manager; this does <em>not</em> tell you whether or not
10343     * your window is obscured by other windows on the screen, even if it
10344     * is itself visible.
10345     *
10346     * @param visibility The new visibility of the window.
10347     */
10348    protected void onWindowVisibilityChanged(@Visibility int visibility) {
10349        if (visibility == VISIBLE) {
10350            initialAwakenScrollBars();
10351        }
10352    }
10353
10354    /**
10355     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
10356     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
10357     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
10358     *
10359     * @param isVisible true if this view's visibility to the user is uninterrupted by its
10360     *                  ancestors or by window visibility
10361     * @return true if this view is visible to the user, not counting clipping or overlapping
10362     */
10363    @Visibility boolean dispatchVisibilityAggregated(boolean isVisible) {
10364        final boolean thisVisible = getVisibility() == VISIBLE;
10365        // If we're not visible but something is telling us we are, ignore it.
10366        if (thisVisible || !isVisible) {
10367            onVisibilityAggregated(isVisible);
10368        }
10369        return thisVisible && isVisible;
10370    }
10371
10372    /**
10373     * Called when the user-visibility of this View is potentially affected by a change
10374     * to this view itself, an ancestor view or the window this view is attached to.
10375     *
10376     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
10377     *                  and this view's window is also visible
10378     */
10379    @CallSuper
10380    public void onVisibilityAggregated(boolean isVisible) {
10381        if (isVisible && mAttachInfo != null) {
10382            initialAwakenScrollBars();
10383        }
10384
10385        final Drawable dr = mBackground;
10386        if (dr != null && isVisible != dr.isVisible()) {
10387            dr.setVisible(isVisible, false);
10388        }
10389        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
10390        if (fg != null && isVisible != fg.isVisible()) {
10391            fg.setVisible(isVisible, false);
10392        }
10393    }
10394
10395    /**
10396     * Returns the current visibility of the window this view is attached to
10397     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
10398     *
10399     * @return Returns the current visibility of the view's window.
10400     */
10401    @Visibility
10402    public int getWindowVisibility() {
10403        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
10404    }
10405
10406    /**
10407     * Retrieve the overall visible display size in which the window this view is
10408     * attached to has been positioned in.  This takes into account screen
10409     * decorations above the window, for both cases where the window itself
10410     * is being position inside of them or the window is being placed under
10411     * then and covered insets are used for the window to position its content
10412     * inside.  In effect, this tells you the available area where content can
10413     * be placed and remain visible to users.
10414     *
10415     * <p>This function requires an IPC back to the window manager to retrieve
10416     * the requested information, so should not be used in performance critical
10417     * code like drawing.
10418     *
10419     * @param outRect Filled in with the visible display frame.  If the view
10420     * is not attached to a window, this is simply the raw display size.
10421     */
10422    public void getWindowVisibleDisplayFrame(Rect outRect) {
10423        if (mAttachInfo != null) {
10424            try {
10425                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10426            } catch (RemoteException e) {
10427                return;
10428            }
10429            // XXX This is really broken, and probably all needs to be done
10430            // in the window manager, and we need to know more about whether
10431            // we want the area behind or in front of the IME.
10432            final Rect insets = mAttachInfo.mVisibleInsets;
10433            outRect.left += insets.left;
10434            outRect.top += insets.top;
10435            outRect.right -= insets.right;
10436            outRect.bottom -= insets.bottom;
10437            return;
10438        }
10439        // The view is not attached to a display so we don't have a context.
10440        // Make a best guess about the display size.
10441        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10442        d.getRectSize(outRect);
10443    }
10444
10445    /**
10446     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
10447     * is currently in without any insets.
10448     *
10449     * @hide
10450     */
10451    public void getWindowDisplayFrame(Rect outRect) {
10452        if (mAttachInfo != null) {
10453            try {
10454                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10455            } catch (RemoteException e) {
10456                return;
10457            }
10458            return;
10459        }
10460        // The view is not attached to a display so we don't have a context.
10461        // Make a best guess about the display size.
10462        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10463        d.getRectSize(outRect);
10464    }
10465
10466    /**
10467     * Dispatch a notification about a resource configuration change down
10468     * the view hierarchy.
10469     * ViewGroups should override to route to their children.
10470     *
10471     * @param newConfig The new resource configuration.
10472     *
10473     * @see #onConfigurationChanged(android.content.res.Configuration)
10474     */
10475    public void dispatchConfigurationChanged(Configuration newConfig) {
10476        onConfigurationChanged(newConfig);
10477    }
10478
10479    /**
10480     * Called when the current configuration of the resources being used
10481     * by the application have changed.  You can use this to decide when
10482     * to reload resources that can changed based on orientation and other
10483     * configuration characteristics.  You only need to use this if you are
10484     * not relying on the normal {@link android.app.Activity} mechanism of
10485     * recreating the activity instance upon a configuration change.
10486     *
10487     * @param newConfig The new resource configuration.
10488     */
10489    protected void onConfigurationChanged(Configuration newConfig) {
10490    }
10491
10492    /**
10493     * Private function to aggregate all per-view attributes in to the view
10494     * root.
10495     */
10496    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10497        performCollectViewAttributes(attachInfo, visibility);
10498    }
10499
10500    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10501        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
10502            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
10503                attachInfo.mKeepScreenOn = true;
10504            }
10505            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
10506            ListenerInfo li = mListenerInfo;
10507            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
10508                attachInfo.mHasSystemUiListeners = true;
10509            }
10510        }
10511    }
10512
10513    void needGlobalAttributesUpdate(boolean force) {
10514        final AttachInfo ai = mAttachInfo;
10515        if (ai != null && !ai.mRecomputeGlobalAttributes) {
10516            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
10517                    || ai.mHasSystemUiListeners) {
10518                ai.mRecomputeGlobalAttributes = true;
10519            }
10520        }
10521    }
10522
10523    /**
10524     * Returns whether the device is currently in touch mode.  Touch mode is entered
10525     * once the user begins interacting with the device by touch, and affects various
10526     * things like whether focus is always visible to the user.
10527     *
10528     * @return Whether the device is in touch mode.
10529     */
10530    @ViewDebug.ExportedProperty
10531    public boolean isInTouchMode() {
10532        if (mAttachInfo != null) {
10533            return mAttachInfo.mInTouchMode;
10534        } else {
10535            return ViewRootImpl.isInTouchMode();
10536        }
10537    }
10538
10539    /**
10540     * Returns the context the view is running in, through which it can
10541     * access the current theme, resources, etc.
10542     *
10543     * @return The view's Context.
10544     */
10545    @ViewDebug.CapturedViewProperty
10546    public final Context getContext() {
10547        return mContext;
10548    }
10549
10550    /**
10551     * Handle a key event before it is processed by any input method
10552     * associated with the view hierarchy.  This can be used to intercept
10553     * key events in special situations before the IME consumes them; a
10554     * typical example would be handling the BACK key to update the application's
10555     * UI instead of allowing the IME to see it and close itself.
10556     *
10557     * @param keyCode The value in event.getKeyCode().
10558     * @param event Description of the key event.
10559     * @return If you handled the event, return true. If you want to allow the
10560     *         event to be handled by the next receiver, return false.
10561     */
10562    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10563        return false;
10564    }
10565
10566    /**
10567     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10568     * KeyEvent.Callback.onKeyDown()}: perform press of the view
10569     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10570     * is released, if the view is enabled and clickable.
10571     * <p>
10572     * Key presses in software keyboards will generally NOT trigger this
10573     * listener, although some may elect to do so in some situations. Do not
10574     * rely on this to catch software key presses.
10575     *
10576     * @param keyCode a key code that represents the button pressed, from
10577     *                {@link android.view.KeyEvent}
10578     * @param event the KeyEvent object that defines the button action
10579     */
10580    public boolean onKeyDown(int keyCode, KeyEvent event) {
10581        if (KeyEvent.isConfirmKey(keyCode)) {
10582            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10583                return true;
10584            }
10585
10586            // Long clickable items don't necessarily have to be clickable.
10587            if (((mViewFlags & CLICKABLE) == CLICKABLE
10588                    || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10589                    && (event.getRepeatCount() == 0)) {
10590                // For the purposes of menu anchoring and drawable hotspots,
10591                // key events are considered to be at the center of the view.
10592                final float x = getWidth() / 2f;
10593                final float y = getHeight() / 2f;
10594                setPressed(true, x, y);
10595                checkForLongClick(0, x, y);
10596                return true;
10597            }
10598        }
10599
10600        return false;
10601    }
10602
10603    /**
10604     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
10605     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
10606     * the event).
10607     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10608     * although some may elect to do so in some situations. Do not rely on this to
10609     * catch software key presses.
10610     */
10611    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
10612        return false;
10613    }
10614
10615    /**
10616     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
10617     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
10618     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
10619     * or {@link KeyEvent#KEYCODE_SPACE} is released.
10620     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10621     * although some may elect to do so in some situations. Do not rely on this to
10622     * catch software key presses.
10623     *
10624     * @param keyCode A key code that represents the button pressed, from
10625     *                {@link android.view.KeyEvent}.
10626     * @param event   The KeyEvent object that defines the button action.
10627     */
10628    public boolean onKeyUp(int keyCode, KeyEvent event) {
10629        if (KeyEvent.isConfirmKey(keyCode)) {
10630            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10631                return true;
10632            }
10633            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
10634                setPressed(false);
10635
10636                if (!mHasPerformedLongPress) {
10637                    // This is a tap, so remove the longpress check
10638                    removeLongPressCallback();
10639                    return performClick();
10640                }
10641            }
10642        }
10643        return false;
10644    }
10645
10646    /**
10647     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10648     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
10649     * the event).
10650     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10651     * although some may elect to do so in some situations. Do not rely on this to
10652     * catch software key presses.
10653     *
10654     * @param keyCode     A key code that represents the button pressed, from
10655     *                    {@link android.view.KeyEvent}.
10656     * @param repeatCount The number of times the action was made.
10657     * @param event       The KeyEvent object that defines the button action.
10658     */
10659    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10660        return false;
10661    }
10662
10663    /**
10664     * Called on the focused view when a key shortcut event is not handled.
10665     * Override this method to implement local key shortcuts for the View.
10666     * Key shortcuts can also be implemented by setting the
10667     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10668     *
10669     * @param keyCode The value in event.getKeyCode().
10670     * @param event Description of the key event.
10671     * @return If you handled the event, return true. If you want to allow the
10672     *         event to be handled by the next receiver, return false.
10673     */
10674    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10675        return false;
10676    }
10677
10678    /**
10679     * Check whether the called view is a text editor, in which case it
10680     * would make sense to automatically display a soft input window for
10681     * it.  Subclasses should override this if they implement
10682     * {@link #onCreateInputConnection(EditorInfo)} to return true if
10683     * a call on that method would return a non-null InputConnection, and
10684     * they are really a first-class editor that the user would normally
10685     * start typing on when the go into a window containing your view.
10686     *
10687     * <p>The default implementation always returns false.  This does
10688     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10689     * will not be called or the user can not otherwise perform edits on your
10690     * view; it is just a hint to the system that this is not the primary
10691     * purpose of this view.
10692     *
10693     * @return Returns true if this view is a text editor, else false.
10694     */
10695    public boolean onCheckIsTextEditor() {
10696        return false;
10697    }
10698
10699    /**
10700     * Create a new InputConnection for an InputMethod to interact
10701     * with the view.  The default implementation returns null, since it doesn't
10702     * support input methods.  You can override this to implement such support.
10703     * This is only needed for views that take focus and text input.
10704     *
10705     * <p>When implementing this, you probably also want to implement
10706     * {@link #onCheckIsTextEditor()} to indicate you will return a
10707     * non-null InputConnection.</p>
10708     *
10709     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10710     * object correctly and in its entirety, so that the connected IME can rely
10711     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10712     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10713     * must be filled in with the correct cursor position for IMEs to work correctly
10714     * with your application.</p>
10715     *
10716     * @param outAttrs Fill in with attribute information about the connection.
10717     */
10718    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10719        return null;
10720    }
10721
10722    /**
10723     * Called by the {@link android.view.inputmethod.InputMethodManager}
10724     * when a view who is not the current
10725     * input connection target is trying to make a call on the manager.  The
10726     * default implementation returns false; you can override this to return
10727     * true for certain views if you are performing InputConnection proxying
10728     * to them.
10729     * @param view The View that is making the InputMethodManager call.
10730     * @return Return true to allow the call, false to reject.
10731     */
10732    public boolean checkInputConnectionProxy(View view) {
10733        return false;
10734    }
10735
10736    /**
10737     * Show the context menu for this view. It is not safe to hold on to the
10738     * menu after returning from this method.
10739     *
10740     * You should normally not overload this method. Overload
10741     * {@link #onCreateContextMenu(ContextMenu)} or define an
10742     * {@link OnCreateContextMenuListener} to add items to the context menu.
10743     *
10744     * @param menu The context menu to populate
10745     */
10746    public void createContextMenu(ContextMenu menu) {
10747        ContextMenuInfo menuInfo = getContextMenuInfo();
10748
10749        // Sets the current menu info so all items added to menu will have
10750        // my extra info set.
10751        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10752
10753        onCreateContextMenu(menu);
10754        ListenerInfo li = mListenerInfo;
10755        if (li != null && li.mOnCreateContextMenuListener != null) {
10756            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10757        }
10758
10759        // Clear the extra information so subsequent items that aren't mine don't
10760        // have my extra info.
10761        ((MenuBuilder)menu).setCurrentMenuInfo(null);
10762
10763        if (mParent != null) {
10764            mParent.createContextMenu(menu);
10765        }
10766    }
10767
10768    /**
10769     * Views should implement this if they have extra information to associate
10770     * with the context menu. The return result is supplied as a parameter to
10771     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10772     * callback.
10773     *
10774     * @return Extra information about the item for which the context menu
10775     *         should be shown. This information will vary across different
10776     *         subclasses of View.
10777     */
10778    protected ContextMenuInfo getContextMenuInfo() {
10779        return null;
10780    }
10781
10782    /**
10783     * Views should implement this if the view itself is going to add items to
10784     * the context menu.
10785     *
10786     * @param menu the context menu to populate
10787     */
10788    protected void onCreateContextMenu(ContextMenu menu) {
10789    }
10790
10791    /**
10792     * Implement this method to handle trackball motion events.  The
10793     * <em>relative</em> movement of the trackball since the last event
10794     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10795     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10796     * that a movement of 1 corresponds to the user pressing one DPAD key (so
10797     * they will often be fractional values, representing the more fine-grained
10798     * movement information available from a trackball).
10799     *
10800     * @param event The motion event.
10801     * @return True if the event was handled, false otherwise.
10802     */
10803    public boolean onTrackballEvent(MotionEvent event) {
10804        return false;
10805    }
10806
10807    /**
10808     * Implement this method to handle generic motion events.
10809     * <p>
10810     * Generic motion events describe joystick movements, mouse hovers, track pad
10811     * touches, scroll wheel movements and other input events.  The
10812     * {@link MotionEvent#getSource() source} of the motion event specifies
10813     * the class of input that was received.  Implementations of this method
10814     * must examine the bits in the source before processing the event.
10815     * The following code example shows how this is done.
10816     * </p><p>
10817     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10818     * are delivered to the view under the pointer.  All other generic motion events are
10819     * delivered to the focused view.
10820     * </p>
10821     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10822     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10823     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10824     *             // process the joystick movement...
10825     *             return true;
10826     *         }
10827     *     }
10828     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10829     *         switch (event.getAction()) {
10830     *             case MotionEvent.ACTION_HOVER_MOVE:
10831     *                 // process the mouse hover movement...
10832     *                 return true;
10833     *             case MotionEvent.ACTION_SCROLL:
10834     *                 // process the scroll wheel movement...
10835     *                 return true;
10836     *         }
10837     *     }
10838     *     return super.onGenericMotionEvent(event);
10839     * }</pre>
10840     *
10841     * @param event The generic motion event being processed.
10842     * @return True if the event was handled, false otherwise.
10843     */
10844    public boolean onGenericMotionEvent(MotionEvent event) {
10845        return false;
10846    }
10847
10848    /**
10849     * Implement this method to handle hover events.
10850     * <p>
10851     * This method is called whenever a pointer is hovering into, over, or out of the
10852     * bounds of a view and the view is not currently being touched.
10853     * Hover events are represented as pointer events with action
10854     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10855     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10856     * </p>
10857     * <ul>
10858     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10859     * when the pointer enters the bounds of the view.</li>
10860     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10861     * when the pointer has already entered the bounds of the view and has moved.</li>
10862     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10863     * when the pointer has exited the bounds of the view or when the pointer is
10864     * about to go down due to a button click, tap, or similar user action that
10865     * causes the view to be touched.</li>
10866     * </ul>
10867     * <p>
10868     * The view should implement this method to return true to indicate that it is
10869     * handling the hover event, such as by changing its drawable state.
10870     * </p><p>
10871     * The default implementation calls {@link #setHovered} to update the hovered state
10872     * of the view when a hover enter or hover exit event is received, if the view
10873     * is enabled and is clickable.  The default implementation also sends hover
10874     * accessibility events.
10875     * </p>
10876     *
10877     * @param event The motion event that describes the hover.
10878     * @return True if the view handled the hover event.
10879     *
10880     * @see #isHovered
10881     * @see #setHovered
10882     * @see #onHoverChanged
10883     */
10884    public boolean onHoverEvent(MotionEvent event) {
10885        // The root view may receive hover (or touch) events that are outside the bounds of
10886        // the window.  This code ensures that we only send accessibility events for
10887        // hovers that are actually within the bounds of the root view.
10888        final int action = event.getActionMasked();
10889        if (!mSendingHoverAccessibilityEvents) {
10890            if ((action == MotionEvent.ACTION_HOVER_ENTER
10891                    || action == MotionEvent.ACTION_HOVER_MOVE)
10892                    && !hasHoveredChild()
10893                    && pointInView(event.getX(), event.getY())) {
10894                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10895                mSendingHoverAccessibilityEvents = true;
10896            }
10897        } else {
10898            if (action == MotionEvent.ACTION_HOVER_EXIT
10899                    || (action == MotionEvent.ACTION_MOVE
10900                            && !pointInView(event.getX(), event.getY()))) {
10901                mSendingHoverAccessibilityEvents = false;
10902                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10903            }
10904        }
10905
10906        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
10907                && event.isFromSource(InputDevice.SOURCE_MOUSE)
10908                && isOnScrollbar(event.getX(), event.getY())) {
10909            awakenScrollBars();
10910        }
10911        if (isHoverable()) {
10912            switch (action) {
10913                case MotionEvent.ACTION_HOVER_ENTER:
10914                    setHovered(true);
10915                    break;
10916                case MotionEvent.ACTION_HOVER_EXIT:
10917                    setHovered(false);
10918                    break;
10919            }
10920
10921            // Dispatch the event to onGenericMotionEvent before returning true.
10922            // This is to provide compatibility with existing applications that
10923            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10924            // break because of the new default handling for hoverable views
10925            // in onHoverEvent.
10926            // Note that onGenericMotionEvent will be called by default when
10927            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10928            dispatchGenericMotionEventInternal(event);
10929            // The event was already handled by calling setHovered(), so always
10930            // return true.
10931            return true;
10932        }
10933
10934        return false;
10935    }
10936
10937    /**
10938     * Returns true if the view should handle {@link #onHoverEvent}
10939     * by calling {@link #setHovered} to change its hovered state.
10940     *
10941     * @return True if the view is hoverable.
10942     */
10943    private boolean isHoverable() {
10944        final int viewFlags = mViewFlags;
10945        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10946            return false;
10947        }
10948
10949        return (viewFlags & CLICKABLE) == CLICKABLE
10950                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10951                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10952    }
10953
10954    /**
10955     * Returns true if the view is currently hovered.
10956     *
10957     * @return True if the view is currently hovered.
10958     *
10959     * @see #setHovered
10960     * @see #onHoverChanged
10961     */
10962    @ViewDebug.ExportedProperty
10963    public boolean isHovered() {
10964        return (mPrivateFlags & PFLAG_HOVERED) != 0;
10965    }
10966
10967    /**
10968     * Sets whether the view is currently hovered.
10969     * <p>
10970     * Calling this method also changes the drawable state of the view.  This
10971     * enables the view to react to hover by using different drawable resources
10972     * to change its appearance.
10973     * </p><p>
10974     * The {@link #onHoverChanged} method is called when the hovered state changes.
10975     * </p>
10976     *
10977     * @param hovered True if the view is hovered.
10978     *
10979     * @see #isHovered
10980     * @see #onHoverChanged
10981     */
10982    public void setHovered(boolean hovered) {
10983        if (hovered) {
10984            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10985                mPrivateFlags |= PFLAG_HOVERED;
10986                refreshDrawableState();
10987                onHoverChanged(true);
10988            }
10989        } else {
10990            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10991                mPrivateFlags &= ~PFLAG_HOVERED;
10992                refreshDrawableState();
10993                onHoverChanged(false);
10994            }
10995        }
10996    }
10997
10998    /**
10999     * Implement this method to handle hover state changes.
11000     * <p>
11001     * This method is called whenever the hover state changes as a result of a
11002     * call to {@link #setHovered}.
11003     * </p>
11004     *
11005     * @param hovered The current hover state, as returned by {@link #isHovered}.
11006     *
11007     * @see #isHovered
11008     * @see #setHovered
11009     */
11010    public void onHoverChanged(boolean hovered) {
11011    }
11012
11013    /**
11014     * Handles scroll bar dragging by mouse input.
11015     *
11016     * @hide
11017     * @param event The motion event.
11018     *
11019     * @return true if the event was handled as a scroll bar dragging, false otherwise.
11020     */
11021    protected boolean handleScrollBarDragging(MotionEvent event) {
11022        if (mScrollCache == null) {
11023            return false;
11024        }
11025        final float x = event.getX();
11026        final float y = event.getY();
11027        final int action = event.getAction();
11028        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
11029                && action != MotionEvent.ACTION_DOWN)
11030                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
11031                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
11032            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11033            return false;
11034        }
11035
11036        switch (action) {
11037            case MotionEvent.ACTION_MOVE:
11038                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
11039                    return false;
11040                }
11041                if (mScrollCache.mScrollBarDraggingState
11042                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
11043                    final Rect bounds = mScrollCache.mScrollBarBounds;
11044                    getVerticalScrollBarBounds(bounds);
11045                    final int range = computeVerticalScrollRange();
11046                    final int offset = computeVerticalScrollOffset();
11047                    final int extent = computeVerticalScrollExtent();
11048
11049                    final int thumbLength = ScrollBarUtils.getThumbLength(
11050                            bounds.height(), bounds.width(), extent, range);
11051                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11052                            bounds.height(), thumbLength, extent, range, offset);
11053
11054                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
11055                    final float maxThumbOffset = bounds.height() - thumbLength;
11056                    final float newThumbOffset =
11057                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11058                    final int height = getHeight();
11059                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11060                            && height > 0 && extent > 0) {
11061                        final int newY = Math.round((range - extent)
11062                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
11063                        if (newY != getScrollY()) {
11064                            mScrollCache.mScrollBarDraggingPos = y;
11065                            setScrollY(newY);
11066                        }
11067                    }
11068                    return true;
11069                }
11070                if (mScrollCache.mScrollBarDraggingState
11071                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
11072                    final Rect bounds = mScrollCache.mScrollBarBounds;
11073                    getHorizontalScrollBarBounds(bounds);
11074                    final int range = computeHorizontalScrollRange();
11075                    final int offset = computeHorizontalScrollOffset();
11076                    final int extent = computeHorizontalScrollExtent();
11077
11078                    final int thumbLength = ScrollBarUtils.getThumbLength(
11079                            bounds.width(), bounds.height(), extent, range);
11080                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11081                            bounds.width(), thumbLength, extent, range, offset);
11082
11083                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
11084                    final float maxThumbOffset = bounds.width() - thumbLength;
11085                    final float newThumbOffset =
11086                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11087                    final int width = getWidth();
11088                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11089                            && width > 0 && extent > 0) {
11090                        final int newX = Math.round((range - extent)
11091                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
11092                        if (newX != getScrollX()) {
11093                            mScrollCache.mScrollBarDraggingPos = x;
11094                            setScrollX(newX);
11095                        }
11096                    }
11097                    return true;
11098                }
11099            case MotionEvent.ACTION_DOWN:
11100                if (mScrollCache.state == ScrollabilityCache.OFF) {
11101                    return false;
11102                }
11103                if (isOnVerticalScrollbarThumb(x, y)) {
11104                    mScrollCache.mScrollBarDraggingState =
11105                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
11106                    mScrollCache.mScrollBarDraggingPos = y;
11107                    return true;
11108                }
11109                if (isOnHorizontalScrollbarThumb(x, y)) {
11110                    mScrollCache.mScrollBarDraggingState =
11111                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
11112                    mScrollCache.mScrollBarDraggingPos = x;
11113                    return true;
11114                }
11115        }
11116        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11117        return false;
11118    }
11119
11120    /**
11121     * Implement this method to handle touch screen motion events.
11122     * <p>
11123     * If this method is used to detect click actions, it is recommended that
11124     * the actions be performed by implementing and calling
11125     * {@link #performClick()}. This will ensure consistent system behavior,
11126     * including:
11127     * <ul>
11128     * <li>obeying click sound preferences
11129     * <li>dispatching OnClickListener calls
11130     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
11131     * accessibility features are enabled
11132     * </ul>
11133     *
11134     * @param event The motion event.
11135     * @return True if the event was handled, false otherwise.
11136     */
11137    public boolean onTouchEvent(MotionEvent event) {
11138        final float x = event.getX();
11139        final float y = event.getY();
11140        final int viewFlags = mViewFlags;
11141        final int action = event.getAction();
11142
11143        if ((viewFlags & ENABLED_MASK) == DISABLED) {
11144            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
11145                setPressed(false);
11146            }
11147            // A disabled view that is clickable still consumes the touch
11148            // events, it just doesn't respond to them.
11149            return (((viewFlags & CLICKABLE) == CLICKABLE
11150                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
11151                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
11152        }
11153        if (mTouchDelegate != null) {
11154            if (mTouchDelegate.onTouchEvent(event)) {
11155                return true;
11156            }
11157        }
11158
11159        if (((viewFlags & CLICKABLE) == CLICKABLE ||
11160                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
11161                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
11162            switch (action) {
11163                case MotionEvent.ACTION_UP:
11164                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
11165                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
11166                        // take focus if we don't have it already and we should in
11167                        // touch mode.
11168                        boolean focusTaken = false;
11169                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
11170                            focusTaken = requestFocus();
11171                        }
11172
11173                        if (prepressed) {
11174                            // The button is being released before we actually
11175                            // showed it as pressed.  Make it show the pressed
11176                            // state now (before scheduling the click) to ensure
11177                            // the user sees it.
11178                            setPressed(true, x, y);
11179                       }
11180
11181                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
11182                            // This is a tap, so remove the longpress check
11183                            removeLongPressCallback();
11184
11185                            // Only perform take click actions if we were in the pressed state
11186                            if (!focusTaken) {
11187                                // Use a Runnable and post this rather than calling
11188                                // performClick directly. This lets other visual state
11189                                // of the view update before click actions start.
11190                                if (mPerformClick == null) {
11191                                    mPerformClick = new PerformClick();
11192                                }
11193                                if (!post(mPerformClick)) {
11194                                    performClick();
11195                                }
11196                            }
11197                        }
11198
11199                        if (mUnsetPressedState == null) {
11200                            mUnsetPressedState = new UnsetPressedState();
11201                        }
11202
11203                        if (prepressed) {
11204                            postDelayed(mUnsetPressedState,
11205                                    ViewConfiguration.getPressedStateDuration());
11206                        } else if (!post(mUnsetPressedState)) {
11207                            // If the post failed, unpress right now
11208                            mUnsetPressedState.run();
11209                        }
11210
11211                        removeTapCallback();
11212                    }
11213                    mIgnoreNextUpEvent = false;
11214                    break;
11215
11216                case MotionEvent.ACTION_DOWN:
11217                    mHasPerformedLongPress = false;
11218
11219                    if (performButtonActionOnTouchDown(event)) {
11220                        break;
11221                    }
11222
11223                    // Walk up the hierarchy to determine if we're inside a scrolling container.
11224                    boolean isInScrollingContainer = isInScrollingContainer();
11225
11226                    // For views inside a scrolling container, delay the pressed feedback for
11227                    // a short period in case this is a scroll.
11228                    if (isInScrollingContainer) {
11229                        mPrivateFlags |= PFLAG_PREPRESSED;
11230                        if (mPendingCheckForTap == null) {
11231                            mPendingCheckForTap = new CheckForTap();
11232                        }
11233                        mPendingCheckForTap.x = event.getX();
11234                        mPendingCheckForTap.y = event.getY();
11235                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
11236                    } else {
11237                        // Not inside a scrolling container, so show the feedback right away
11238                        setPressed(true, x, y);
11239                        checkForLongClick(0, x, y);
11240                    }
11241                    break;
11242
11243                case MotionEvent.ACTION_CANCEL:
11244                    setPressed(false);
11245                    removeTapCallback();
11246                    removeLongPressCallback();
11247                    mInContextButtonPress = false;
11248                    mHasPerformedLongPress = false;
11249                    mIgnoreNextUpEvent = false;
11250                    break;
11251
11252                case MotionEvent.ACTION_MOVE:
11253                    drawableHotspotChanged(x, y);
11254
11255                    // Be lenient about moving outside of buttons
11256                    if (!pointInView(x, y, mTouchSlop)) {
11257                        // Outside button
11258                        removeTapCallback();
11259                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
11260                            // Remove any future long press/tap checks
11261                            removeLongPressCallback();
11262
11263                            setPressed(false);
11264                        }
11265                    }
11266                    break;
11267            }
11268
11269            return true;
11270        }
11271
11272        return false;
11273    }
11274
11275    /**
11276     * @hide
11277     */
11278    public boolean isInScrollingContainer() {
11279        ViewParent p = getParent();
11280        while (p != null && p instanceof ViewGroup) {
11281            if (((ViewGroup) p).shouldDelayChildPressedState()) {
11282                return true;
11283            }
11284            p = p.getParent();
11285        }
11286        return false;
11287    }
11288
11289    /**
11290     * Remove the longpress detection timer.
11291     */
11292    private void removeLongPressCallback() {
11293        if (mPendingCheckForLongPress != null) {
11294          removeCallbacks(mPendingCheckForLongPress);
11295        }
11296    }
11297
11298    /**
11299     * Remove the pending click action
11300     */
11301    private void removePerformClickCallback() {
11302        if (mPerformClick != null) {
11303            removeCallbacks(mPerformClick);
11304        }
11305    }
11306
11307    /**
11308     * Remove the prepress detection timer.
11309     */
11310    private void removeUnsetPressCallback() {
11311        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
11312            setPressed(false);
11313            removeCallbacks(mUnsetPressedState);
11314        }
11315    }
11316
11317    /**
11318     * Remove the tap detection timer.
11319     */
11320    private void removeTapCallback() {
11321        if (mPendingCheckForTap != null) {
11322            mPrivateFlags &= ~PFLAG_PREPRESSED;
11323            removeCallbacks(mPendingCheckForTap);
11324        }
11325    }
11326
11327    /**
11328     * Cancels a pending long press.  Your subclass can use this if you
11329     * want the context menu to come up if the user presses and holds
11330     * at the same place, but you don't want it to come up if they press
11331     * and then move around enough to cause scrolling.
11332     */
11333    public void cancelLongPress() {
11334        removeLongPressCallback();
11335
11336        /*
11337         * The prepressed state handled by the tap callback is a display
11338         * construct, but the tap callback will post a long press callback
11339         * less its own timeout. Remove it here.
11340         */
11341        removeTapCallback();
11342    }
11343
11344    /**
11345     * Remove the pending callback for sending a
11346     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
11347     */
11348    private void removeSendViewScrolledAccessibilityEventCallback() {
11349        if (mSendViewScrolledAccessibilityEvent != null) {
11350            removeCallbacks(mSendViewScrolledAccessibilityEvent);
11351            mSendViewScrolledAccessibilityEvent.mIsPending = false;
11352        }
11353    }
11354
11355    /**
11356     * Sets the TouchDelegate for this View.
11357     */
11358    public void setTouchDelegate(TouchDelegate delegate) {
11359        mTouchDelegate = delegate;
11360    }
11361
11362    /**
11363     * Gets the TouchDelegate for this View.
11364     */
11365    public TouchDelegate getTouchDelegate() {
11366        return mTouchDelegate;
11367    }
11368
11369    /**
11370     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
11371     *
11372     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
11373     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
11374     * available. This method should only be called for touch events.
11375     *
11376     * <p class="note">This api is not intended for most applications. Buffered dispatch
11377     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
11378     * streams will not improve your input latency. Side effects include: increased latency,
11379     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
11380     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
11381     * you.</p>
11382     */
11383    public final void requestUnbufferedDispatch(MotionEvent event) {
11384        final int action = event.getAction();
11385        if (mAttachInfo == null
11386                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
11387                || !event.isTouchEvent()) {
11388            return;
11389        }
11390        mAttachInfo.mUnbufferedDispatchRequested = true;
11391    }
11392
11393    /**
11394     * Set flags controlling behavior of this view.
11395     *
11396     * @param flags Constant indicating the value which should be set
11397     * @param mask Constant indicating the bit range that should be changed
11398     */
11399    void setFlags(int flags, int mask) {
11400        final boolean accessibilityEnabled =
11401                AccessibilityManager.getInstance(mContext).isEnabled();
11402        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
11403
11404        int old = mViewFlags;
11405        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
11406
11407        int changed = mViewFlags ^ old;
11408        if (changed == 0) {
11409            return;
11410        }
11411        int privateFlags = mPrivateFlags;
11412
11413        /* Check if the FOCUSABLE bit has changed */
11414        if (((changed & FOCUSABLE_MASK) != 0) &&
11415                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
11416            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
11417                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
11418                /* Give up focus if we are no longer focusable */
11419                clearFocus();
11420            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
11421                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
11422                /*
11423                 * Tell the view system that we are now available to take focus
11424                 * if no one else already has it.
11425                 */
11426                if (mParent != null) mParent.focusableViewAvailable(this);
11427            }
11428        }
11429
11430        final int newVisibility = flags & VISIBILITY_MASK;
11431        if (newVisibility == VISIBLE) {
11432            if ((changed & VISIBILITY_MASK) != 0) {
11433                /*
11434                 * If this view is becoming visible, invalidate it in case it changed while
11435                 * it was not visible. Marking it drawn ensures that the invalidation will
11436                 * go through.
11437                 */
11438                mPrivateFlags |= PFLAG_DRAWN;
11439                invalidate(true);
11440
11441                needGlobalAttributesUpdate(true);
11442
11443                // a view becoming visible is worth notifying the parent
11444                // about in case nothing has focus.  even if this specific view
11445                // isn't focusable, it may contain something that is, so let
11446                // the root view try to give this focus if nothing else does.
11447                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
11448                    mParent.focusableViewAvailable(this);
11449                }
11450            }
11451        }
11452
11453        /* Check if the GONE bit has changed */
11454        if ((changed & GONE) != 0) {
11455            needGlobalAttributesUpdate(false);
11456            requestLayout();
11457
11458            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
11459                if (hasFocus()) clearFocus();
11460                clearAccessibilityFocus();
11461                destroyDrawingCache();
11462                if (mParent instanceof View) {
11463                    // GONE views noop invalidation, so invalidate the parent
11464                    ((View) mParent).invalidate(true);
11465                }
11466                // Mark the view drawn to ensure that it gets invalidated properly the next
11467                // time it is visible and gets invalidated
11468                mPrivateFlags |= PFLAG_DRAWN;
11469            }
11470            if (mAttachInfo != null) {
11471                mAttachInfo.mViewVisibilityChanged = true;
11472            }
11473        }
11474
11475        /* Check if the VISIBLE bit has changed */
11476        if ((changed & INVISIBLE) != 0) {
11477            needGlobalAttributesUpdate(false);
11478            /*
11479             * If this view is becoming invisible, set the DRAWN flag so that
11480             * the next invalidate() will not be skipped.
11481             */
11482            mPrivateFlags |= PFLAG_DRAWN;
11483
11484            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
11485                // root view becoming invisible shouldn't clear focus and accessibility focus
11486                if (getRootView() != this) {
11487                    if (hasFocus()) clearFocus();
11488                    clearAccessibilityFocus();
11489                }
11490            }
11491            if (mAttachInfo != null) {
11492                mAttachInfo.mViewVisibilityChanged = true;
11493            }
11494        }
11495
11496        if ((changed & VISIBILITY_MASK) != 0) {
11497            // If the view is invisible, cleanup its display list to free up resources
11498            if (newVisibility != VISIBLE && mAttachInfo != null) {
11499                cleanupDraw();
11500            }
11501
11502            if (mParent instanceof ViewGroup) {
11503                ((ViewGroup) mParent).onChildVisibilityChanged(this,
11504                        (changed & VISIBILITY_MASK), newVisibility);
11505                ((View) mParent).invalidate(true);
11506            } else if (mParent != null) {
11507                mParent.invalidateChild(this, null);
11508            }
11509
11510            if (mAttachInfo != null) {
11511                dispatchVisibilityChanged(this, newVisibility);
11512
11513                // Aggregated visibility changes are dispatched to attached views
11514                // in visible windows where the parent is currently shown/drawn
11515                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
11516                // discounting clipping or overlapping. This makes it a good place
11517                // to change animation states.
11518                if (mParent != null && getWindowVisibility() == VISIBLE &&
11519                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
11520                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
11521                }
11522                notifySubtreeAccessibilityStateChangedIfNeeded();
11523            }
11524        }
11525
11526        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
11527            destroyDrawingCache();
11528        }
11529
11530        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
11531            destroyDrawingCache();
11532            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11533            invalidateParentCaches();
11534        }
11535
11536        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
11537            destroyDrawingCache();
11538            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11539        }
11540
11541        if ((changed & DRAW_MASK) != 0) {
11542            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
11543                if (mBackground != null
11544                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
11545                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11546                } else {
11547                    mPrivateFlags |= PFLAG_SKIP_DRAW;
11548                }
11549            } else {
11550                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11551            }
11552            requestLayout();
11553            invalidate(true);
11554        }
11555
11556        if ((changed & KEEP_SCREEN_ON) != 0) {
11557            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
11558                mParent.recomputeViewAttributes(this);
11559            }
11560        }
11561
11562        if (accessibilityEnabled) {
11563            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
11564                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
11565                    || (changed & CONTEXT_CLICKABLE) != 0) {
11566                if (oldIncludeForAccessibility != includeForAccessibility()) {
11567                    notifySubtreeAccessibilityStateChangedIfNeeded();
11568                } else {
11569                    notifyViewAccessibilityStateChangedIfNeeded(
11570                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11571                }
11572            } else if ((changed & ENABLED_MASK) != 0) {
11573                notifyViewAccessibilityStateChangedIfNeeded(
11574                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11575            }
11576        }
11577    }
11578
11579    /**
11580     * Change the view's z order in the tree, so it's on top of other sibling
11581     * views. This ordering change may affect layout, if the parent container
11582     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
11583     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
11584     * method should be followed by calls to {@link #requestLayout()} and
11585     * {@link View#invalidate()} on the view's parent to force the parent to redraw
11586     * with the new child ordering.
11587     *
11588     * @see ViewGroup#bringChildToFront(View)
11589     */
11590    public void bringToFront() {
11591        if (mParent != null) {
11592            mParent.bringChildToFront(this);
11593        }
11594    }
11595
11596    /**
11597     * This is called in response to an internal scroll in this view (i.e., the
11598     * view scrolled its own contents). This is typically as a result of
11599     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
11600     * called.
11601     *
11602     * @param l Current horizontal scroll origin.
11603     * @param t Current vertical scroll origin.
11604     * @param oldl Previous horizontal scroll origin.
11605     * @param oldt Previous vertical scroll origin.
11606     */
11607    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
11608        notifySubtreeAccessibilityStateChangedIfNeeded();
11609
11610        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11611            postSendViewScrolledAccessibilityEventCallback();
11612        }
11613
11614        mBackgroundSizeChanged = true;
11615        if (mForegroundInfo != null) {
11616            mForegroundInfo.mBoundsChanged = true;
11617        }
11618
11619        final AttachInfo ai = mAttachInfo;
11620        if (ai != null) {
11621            ai.mViewScrollChanged = true;
11622        }
11623
11624        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
11625            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
11626        }
11627    }
11628
11629    /**
11630     * Interface definition for a callback to be invoked when the scroll
11631     * X or Y positions of a view change.
11632     * <p>
11633     * <b>Note:</b> Some views handle scrolling independently from View and may
11634     * have their own separate listeners for scroll-type events. For example,
11635     * {@link android.widget.ListView ListView} allows clients to register an
11636     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
11637     * to listen for changes in list scroll position.
11638     *
11639     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
11640     */
11641    public interface OnScrollChangeListener {
11642        /**
11643         * Called when the scroll position of a view changes.
11644         *
11645         * @param v The view whose scroll position has changed.
11646         * @param scrollX Current horizontal scroll origin.
11647         * @param scrollY Current vertical scroll origin.
11648         * @param oldScrollX Previous horizontal scroll origin.
11649         * @param oldScrollY Previous vertical scroll origin.
11650         */
11651        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
11652    }
11653
11654    /**
11655     * Interface definition for a callback to be invoked when the layout bounds of a view
11656     * changes due to layout processing.
11657     */
11658    public interface OnLayoutChangeListener {
11659        /**
11660         * Called when the layout bounds of a view changes due to layout processing.
11661         *
11662         * @param v The view whose bounds have changed.
11663         * @param left The new value of the view's left property.
11664         * @param top The new value of the view's top property.
11665         * @param right The new value of the view's right property.
11666         * @param bottom The new value of the view's bottom property.
11667         * @param oldLeft The previous value of the view's left property.
11668         * @param oldTop The previous value of the view's top property.
11669         * @param oldRight The previous value of the view's right property.
11670         * @param oldBottom The previous value of the view's bottom property.
11671         */
11672        void onLayoutChange(View v, int left, int top, int right, int bottom,
11673            int oldLeft, int oldTop, int oldRight, int oldBottom);
11674    }
11675
11676    /**
11677     * This is called during layout when the size of this view has changed. If
11678     * you were just added to the view hierarchy, you're called with the old
11679     * values of 0.
11680     *
11681     * @param w Current width of this view.
11682     * @param h Current height of this view.
11683     * @param oldw Old width of this view.
11684     * @param oldh Old height of this view.
11685     */
11686    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
11687    }
11688
11689    /**
11690     * Called by draw to draw the child views. This may be overridden
11691     * by derived classes to gain control just before its children are drawn
11692     * (but after its own view has been drawn).
11693     * @param canvas the canvas on which to draw the view
11694     */
11695    protected void dispatchDraw(Canvas canvas) {
11696
11697    }
11698
11699    /**
11700     * Gets the parent of this view. Note that the parent is a
11701     * ViewParent and not necessarily a View.
11702     *
11703     * @return Parent of this view.
11704     */
11705    public final ViewParent getParent() {
11706        return mParent;
11707    }
11708
11709    /**
11710     * Set the horizontal scrolled position of your view. This will cause a call to
11711     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11712     * invalidated.
11713     * @param value the x position to scroll to
11714     */
11715    public void setScrollX(int value) {
11716        scrollTo(value, mScrollY);
11717    }
11718
11719    /**
11720     * Set the vertical scrolled position of your view. This will cause a call to
11721     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11722     * invalidated.
11723     * @param value the y position to scroll to
11724     */
11725    public void setScrollY(int value) {
11726        scrollTo(mScrollX, value);
11727    }
11728
11729    /**
11730     * Return the scrolled left position of this view. This is the left edge of
11731     * the displayed part of your view. You do not need to draw any pixels
11732     * farther left, since those are outside of the frame of your view on
11733     * screen.
11734     *
11735     * @return The left edge of the displayed part of your view, in pixels.
11736     */
11737    public final int getScrollX() {
11738        return mScrollX;
11739    }
11740
11741    /**
11742     * Return the scrolled top position of this view. This is the top edge of
11743     * the displayed part of your view. You do not need to draw any pixels above
11744     * it, since those are outside of the frame of your view on screen.
11745     *
11746     * @return The top edge of the displayed part of your view, in pixels.
11747     */
11748    public final int getScrollY() {
11749        return mScrollY;
11750    }
11751
11752    /**
11753     * Return the width of the your view.
11754     *
11755     * @return The width of your view, in pixels.
11756     */
11757    @ViewDebug.ExportedProperty(category = "layout")
11758    public final int getWidth() {
11759        return mRight - mLeft;
11760    }
11761
11762    /**
11763     * Return the height of your view.
11764     *
11765     * @return The height of your view, in pixels.
11766     */
11767    @ViewDebug.ExportedProperty(category = "layout")
11768    public final int getHeight() {
11769        return mBottom - mTop;
11770    }
11771
11772    /**
11773     * Return the visible drawing bounds of your view. Fills in the output
11774     * rectangle with the values from getScrollX(), getScrollY(),
11775     * getWidth(), and getHeight(). These bounds do not account for any
11776     * transformation properties currently set on the view, such as
11777     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11778     *
11779     * @param outRect The (scrolled) drawing bounds of the view.
11780     */
11781    public void getDrawingRect(Rect outRect) {
11782        outRect.left = mScrollX;
11783        outRect.top = mScrollY;
11784        outRect.right = mScrollX + (mRight - mLeft);
11785        outRect.bottom = mScrollY + (mBottom - mTop);
11786    }
11787
11788    /**
11789     * Like {@link #getMeasuredWidthAndState()}, but only returns the
11790     * raw width component (that is the result is masked by
11791     * {@link #MEASURED_SIZE_MASK}).
11792     *
11793     * @return The raw measured width of this view.
11794     */
11795    public final int getMeasuredWidth() {
11796        return mMeasuredWidth & MEASURED_SIZE_MASK;
11797    }
11798
11799    /**
11800     * Return the full width measurement information for this view as computed
11801     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11802     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11803     * This should be used during measurement and layout calculations only. Use
11804     * {@link #getWidth()} to see how wide a view is after layout.
11805     *
11806     * @return The measured width of this view as a bit mask.
11807     */
11808    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11809            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11810                    name = "MEASURED_STATE_TOO_SMALL"),
11811    })
11812    public final int getMeasuredWidthAndState() {
11813        return mMeasuredWidth;
11814    }
11815
11816    /**
11817     * Like {@link #getMeasuredHeightAndState()}, but only returns the
11818     * raw height component (that is the result is masked by
11819     * {@link #MEASURED_SIZE_MASK}).
11820     *
11821     * @return The raw measured height of this view.
11822     */
11823    public final int getMeasuredHeight() {
11824        return mMeasuredHeight & MEASURED_SIZE_MASK;
11825    }
11826
11827    /**
11828     * Return the full height measurement information for this view as computed
11829     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11830     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11831     * This should be used during measurement and layout calculations only. Use
11832     * {@link #getHeight()} to see how wide a view is after layout.
11833     *
11834     * @return The measured height of this view as a bit mask.
11835     */
11836    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11837            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11838                    name = "MEASURED_STATE_TOO_SMALL"),
11839    })
11840    public final int getMeasuredHeightAndState() {
11841        return mMeasuredHeight;
11842    }
11843
11844    /**
11845     * Return only the state bits of {@link #getMeasuredWidthAndState()}
11846     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11847     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11848     * and the height component is at the shifted bits
11849     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11850     */
11851    public final int getMeasuredState() {
11852        return (mMeasuredWidth&MEASURED_STATE_MASK)
11853                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11854                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11855    }
11856
11857    /**
11858     * The transform matrix of this view, which is calculated based on the current
11859     * rotation, scale, and pivot properties.
11860     *
11861     * @see #getRotation()
11862     * @see #getScaleX()
11863     * @see #getScaleY()
11864     * @see #getPivotX()
11865     * @see #getPivotY()
11866     * @return The current transform matrix for the view
11867     */
11868    public Matrix getMatrix() {
11869        ensureTransformationInfo();
11870        final Matrix matrix = mTransformationInfo.mMatrix;
11871        mRenderNode.getMatrix(matrix);
11872        return matrix;
11873    }
11874
11875    /**
11876     * Returns true if the transform matrix is the identity matrix.
11877     * Recomputes the matrix if necessary.
11878     *
11879     * @return True if the transform matrix is the identity matrix, false otherwise.
11880     */
11881    final boolean hasIdentityMatrix() {
11882        return mRenderNode.hasIdentityMatrix();
11883    }
11884
11885    void ensureTransformationInfo() {
11886        if (mTransformationInfo == null) {
11887            mTransformationInfo = new TransformationInfo();
11888        }
11889    }
11890
11891    /**
11892     * Utility method to retrieve the inverse of the current mMatrix property.
11893     * We cache the matrix to avoid recalculating it when transform properties
11894     * have not changed.
11895     *
11896     * @return The inverse of the current matrix of this view.
11897     * @hide
11898     */
11899    public final Matrix getInverseMatrix() {
11900        ensureTransformationInfo();
11901        if (mTransformationInfo.mInverseMatrix == null) {
11902            mTransformationInfo.mInverseMatrix = new Matrix();
11903        }
11904        final Matrix matrix = mTransformationInfo.mInverseMatrix;
11905        mRenderNode.getInverseMatrix(matrix);
11906        return matrix;
11907    }
11908
11909    /**
11910     * Gets the distance along the Z axis from the camera to this view.
11911     *
11912     * @see #setCameraDistance(float)
11913     *
11914     * @return The distance along the Z axis.
11915     */
11916    public float getCameraDistance() {
11917        final float dpi = mResources.getDisplayMetrics().densityDpi;
11918        return -(mRenderNode.getCameraDistance() * dpi);
11919    }
11920
11921    /**
11922     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11923     * views are drawn) from the camera to this view. The camera's distance
11924     * affects 3D transformations, for instance rotations around the X and Y
11925     * axis. If the rotationX or rotationY properties are changed and this view is
11926     * large (more than half the size of the screen), it is recommended to always
11927     * use a camera distance that's greater than the height (X axis rotation) or
11928     * the width (Y axis rotation) of this view.</p>
11929     *
11930     * <p>The distance of the camera from the view plane can have an affect on the
11931     * perspective distortion of the view when it is rotated around the x or y axis.
11932     * For example, a large distance will result in a large viewing angle, and there
11933     * will not be much perspective distortion of the view as it rotates. A short
11934     * distance may cause much more perspective distortion upon rotation, and can
11935     * also result in some drawing artifacts if the rotated view ends up partially
11936     * behind the camera (which is why the recommendation is to use a distance at
11937     * least as far as the size of the view, if the view is to be rotated.)</p>
11938     *
11939     * <p>The distance is expressed in "depth pixels." The default distance depends
11940     * on the screen density. For instance, on a medium density display, the
11941     * default distance is 1280. On a high density display, the default distance
11942     * is 1920.</p>
11943     *
11944     * <p>If you want to specify a distance that leads to visually consistent
11945     * results across various densities, use the following formula:</p>
11946     * <pre>
11947     * float scale = context.getResources().getDisplayMetrics().density;
11948     * view.setCameraDistance(distance * scale);
11949     * </pre>
11950     *
11951     * <p>The density scale factor of a high density display is 1.5,
11952     * and 1920 = 1280 * 1.5.</p>
11953     *
11954     * @param distance The distance in "depth pixels", if negative the opposite
11955     *        value is used
11956     *
11957     * @see #setRotationX(float)
11958     * @see #setRotationY(float)
11959     */
11960    public void setCameraDistance(float distance) {
11961        final float dpi = mResources.getDisplayMetrics().densityDpi;
11962
11963        invalidateViewProperty(true, false);
11964        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11965        invalidateViewProperty(false, false);
11966
11967        invalidateParentIfNeededAndWasQuickRejected();
11968    }
11969
11970    /**
11971     * The degrees that the view is rotated around the pivot point.
11972     *
11973     * @see #setRotation(float)
11974     * @see #getPivotX()
11975     * @see #getPivotY()
11976     *
11977     * @return The degrees of rotation.
11978     */
11979    @ViewDebug.ExportedProperty(category = "drawing")
11980    public float getRotation() {
11981        return mRenderNode.getRotation();
11982    }
11983
11984    /**
11985     * Sets the degrees that the view is rotated around the pivot point. Increasing values
11986     * result in clockwise rotation.
11987     *
11988     * @param rotation The degrees of rotation.
11989     *
11990     * @see #getRotation()
11991     * @see #getPivotX()
11992     * @see #getPivotY()
11993     * @see #setRotationX(float)
11994     * @see #setRotationY(float)
11995     *
11996     * @attr ref android.R.styleable#View_rotation
11997     */
11998    public void setRotation(float rotation) {
11999        if (rotation != getRotation()) {
12000            // Double-invalidation is necessary to capture view's old and new areas
12001            invalidateViewProperty(true, false);
12002            mRenderNode.setRotation(rotation);
12003            invalidateViewProperty(false, true);
12004
12005            invalidateParentIfNeededAndWasQuickRejected();
12006            notifySubtreeAccessibilityStateChangedIfNeeded();
12007        }
12008    }
12009
12010    /**
12011     * The degrees that the view is rotated around the vertical axis through the pivot point.
12012     *
12013     * @see #getPivotX()
12014     * @see #getPivotY()
12015     * @see #setRotationY(float)
12016     *
12017     * @return The degrees of Y rotation.
12018     */
12019    @ViewDebug.ExportedProperty(category = "drawing")
12020    public float getRotationY() {
12021        return mRenderNode.getRotationY();
12022    }
12023
12024    /**
12025     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
12026     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
12027     * down the y axis.
12028     *
12029     * When rotating large views, it is recommended to adjust the camera distance
12030     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12031     *
12032     * @param rotationY The degrees of Y rotation.
12033     *
12034     * @see #getRotationY()
12035     * @see #getPivotX()
12036     * @see #getPivotY()
12037     * @see #setRotation(float)
12038     * @see #setRotationX(float)
12039     * @see #setCameraDistance(float)
12040     *
12041     * @attr ref android.R.styleable#View_rotationY
12042     */
12043    public void setRotationY(float rotationY) {
12044        if (rotationY != getRotationY()) {
12045            invalidateViewProperty(true, false);
12046            mRenderNode.setRotationY(rotationY);
12047            invalidateViewProperty(false, true);
12048
12049            invalidateParentIfNeededAndWasQuickRejected();
12050            notifySubtreeAccessibilityStateChangedIfNeeded();
12051        }
12052    }
12053
12054    /**
12055     * The degrees that the view is rotated around the horizontal axis through the pivot point.
12056     *
12057     * @see #getPivotX()
12058     * @see #getPivotY()
12059     * @see #setRotationX(float)
12060     *
12061     * @return The degrees of X rotation.
12062     */
12063    @ViewDebug.ExportedProperty(category = "drawing")
12064    public float getRotationX() {
12065        return mRenderNode.getRotationX();
12066    }
12067
12068    /**
12069     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
12070     * Increasing values result in clockwise rotation from the viewpoint of looking down the
12071     * x axis.
12072     *
12073     * When rotating large views, it is recommended to adjust the camera distance
12074     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12075     *
12076     * @param rotationX The degrees of X rotation.
12077     *
12078     * @see #getRotationX()
12079     * @see #getPivotX()
12080     * @see #getPivotY()
12081     * @see #setRotation(float)
12082     * @see #setRotationY(float)
12083     * @see #setCameraDistance(float)
12084     *
12085     * @attr ref android.R.styleable#View_rotationX
12086     */
12087    public void setRotationX(float rotationX) {
12088        if (rotationX != getRotationX()) {
12089            invalidateViewProperty(true, false);
12090            mRenderNode.setRotationX(rotationX);
12091            invalidateViewProperty(false, true);
12092
12093            invalidateParentIfNeededAndWasQuickRejected();
12094            notifySubtreeAccessibilityStateChangedIfNeeded();
12095        }
12096    }
12097
12098    /**
12099     * The amount that the view is scaled in x around the pivot point, as a proportion of
12100     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
12101     *
12102     * <p>By default, this is 1.0f.
12103     *
12104     * @see #getPivotX()
12105     * @see #getPivotY()
12106     * @return The scaling factor.
12107     */
12108    @ViewDebug.ExportedProperty(category = "drawing")
12109    public float getScaleX() {
12110        return mRenderNode.getScaleX();
12111    }
12112
12113    /**
12114     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
12115     * the view's unscaled width. A value of 1 means that no scaling is applied.
12116     *
12117     * @param scaleX The scaling factor.
12118     * @see #getPivotX()
12119     * @see #getPivotY()
12120     *
12121     * @attr ref android.R.styleable#View_scaleX
12122     */
12123    public void setScaleX(float scaleX) {
12124        if (scaleX != getScaleX()) {
12125            invalidateViewProperty(true, false);
12126            mRenderNode.setScaleX(scaleX);
12127            invalidateViewProperty(false, true);
12128
12129            invalidateParentIfNeededAndWasQuickRejected();
12130            notifySubtreeAccessibilityStateChangedIfNeeded();
12131        }
12132    }
12133
12134    /**
12135     * The amount that the view is scaled in y around the pivot point, as a proportion of
12136     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
12137     *
12138     * <p>By default, this is 1.0f.
12139     *
12140     * @see #getPivotX()
12141     * @see #getPivotY()
12142     * @return The scaling factor.
12143     */
12144    @ViewDebug.ExportedProperty(category = "drawing")
12145    public float getScaleY() {
12146        return mRenderNode.getScaleY();
12147    }
12148
12149    /**
12150     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
12151     * the view's unscaled width. A value of 1 means that no scaling is applied.
12152     *
12153     * @param scaleY The scaling factor.
12154     * @see #getPivotX()
12155     * @see #getPivotY()
12156     *
12157     * @attr ref android.R.styleable#View_scaleY
12158     */
12159    public void setScaleY(float scaleY) {
12160        if (scaleY != getScaleY()) {
12161            invalidateViewProperty(true, false);
12162            mRenderNode.setScaleY(scaleY);
12163            invalidateViewProperty(false, true);
12164
12165            invalidateParentIfNeededAndWasQuickRejected();
12166            notifySubtreeAccessibilityStateChangedIfNeeded();
12167        }
12168    }
12169
12170    /**
12171     * The x location of the point around which the view is {@link #setRotation(float) rotated}
12172     * and {@link #setScaleX(float) scaled}.
12173     *
12174     * @see #getRotation()
12175     * @see #getScaleX()
12176     * @see #getScaleY()
12177     * @see #getPivotY()
12178     * @return The x location of the pivot point.
12179     *
12180     * @attr ref android.R.styleable#View_transformPivotX
12181     */
12182    @ViewDebug.ExportedProperty(category = "drawing")
12183    public float getPivotX() {
12184        return mRenderNode.getPivotX();
12185    }
12186
12187    /**
12188     * Sets the x location of the point around which the view is
12189     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
12190     * By default, the pivot point is centered on the object.
12191     * Setting this property disables this behavior and causes the view to use only the
12192     * explicitly set pivotX and pivotY values.
12193     *
12194     * @param pivotX The x location of the pivot point.
12195     * @see #getRotation()
12196     * @see #getScaleX()
12197     * @see #getScaleY()
12198     * @see #getPivotY()
12199     *
12200     * @attr ref android.R.styleable#View_transformPivotX
12201     */
12202    public void setPivotX(float pivotX) {
12203        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
12204            invalidateViewProperty(true, false);
12205            mRenderNode.setPivotX(pivotX);
12206            invalidateViewProperty(false, true);
12207
12208            invalidateParentIfNeededAndWasQuickRejected();
12209        }
12210    }
12211
12212    /**
12213     * The y location of the point around which the view is {@link #setRotation(float) rotated}
12214     * and {@link #setScaleY(float) scaled}.
12215     *
12216     * @see #getRotation()
12217     * @see #getScaleX()
12218     * @see #getScaleY()
12219     * @see #getPivotY()
12220     * @return The y location of the pivot point.
12221     *
12222     * @attr ref android.R.styleable#View_transformPivotY
12223     */
12224    @ViewDebug.ExportedProperty(category = "drawing")
12225    public float getPivotY() {
12226        return mRenderNode.getPivotY();
12227    }
12228
12229    /**
12230     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
12231     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
12232     * Setting this property disables this behavior and causes the view to use only the
12233     * explicitly set pivotX and pivotY values.
12234     *
12235     * @param pivotY The y location of the pivot point.
12236     * @see #getRotation()
12237     * @see #getScaleX()
12238     * @see #getScaleY()
12239     * @see #getPivotY()
12240     *
12241     * @attr ref android.R.styleable#View_transformPivotY
12242     */
12243    public void setPivotY(float pivotY) {
12244        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
12245            invalidateViewProperty(true, false);
12246            mRenderNode.setPivotY(pivotY);
12247            invalidateViewProperty(false, true);
12248
12249            invalidateParentIfNeededAndWasQuickRejected();
12250        }
12251    }
12252
12253    /**
12254     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
12255     * completely transparent and 1 means the view is completely opaque.
12256     *
12257     * <p>By default this is 1.0f.
12258     * @return The opacity of the view.
12259     */
12260    @ViewDebug.ExportedProperty(category = "drawing")
12261    public float getAlpha() {
12262        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
12263    }
12264
12265    /**
12266     * Sets the behavior for overlapping rendering for this view (see {@link
12267     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
12268     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
12269     * providing the value which is then used internally. That is, when {@link
12270     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
12271     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
12272     * instead.
12273     *
12274     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
12275     * instead of that returned by {@link #hasOverlappingRendering()}.
12276     *
12277     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
12278     */
12279    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
12280        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
12281        if (hasOverlappingRendering) {
12282            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12283        } else {
12284            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12285        }
12286    }
12287
12288    /**
12289     * Returns the value for overlapping rendering that is used internally. This is either
12290     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
12291     * the return value of {@link #hasOverlappingRendering()}, otherwise.
12292     *
12293     * @return The value for overlapping rendering being used internally.
12294     */
12295    public final boolean getHasOverlappingRendering() {
12296        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
12297                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
12298                hasOverlappingRendering();
12299    }
12300
12301    /**
12302     * Returns whether this View has content which overlaps.
12303     *
12304     * <p>This function, intended to be overridden by specific View types, is an optimization when
12305     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
12306     * an offscreen buffer and then composited into place, which can be expensive. If the view has
12307     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
12308     * directly. An example of overlapping rendering is a TextView with a background image, such as
12309     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
12310     * ImageView with only the foreground image. The default implementation returns true; subclasses
12311     * should override if they have cases which can be optimized.</p>
12312     *
12313     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
12314     * necessitates that a View return true if it uses the methods internally without passing the
12315     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
12316     *
12317     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
12318     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
12319     *
12320     * @return true if the content in this view might overlap, false otherwise.
12321     */
12322    @ViewDebug.ExportedProperty(category = "drawing")
12323    public boolean hasOverlappingRendering() {
12324        return true;
12325    }
12326
12327    /**
12328     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
12329     * completely transparent and 1 means the view is completely opaque.
12330     *
12331     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
12332     * can have significant performance implications, especially for large views. It is best to use
12333     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
12334     *
12335     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
12336     * strongly recommended for performance reasons to either override
12337     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
12338     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
12339     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
12340     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
12341     * of rendering cost, even for simple or small views. Starting with
12342     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
12343     * applied to the view at the rendering level.</p>
12344     *
12345     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
12346     * responsible for applying the opacity itself.</p>
12347     *
12348     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
12349     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
12350     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
12351     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
12352     *
12353     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
12354     * value will clip a View to its bounds, unless the View returns <code>false</code> from
12355     * {@link #hasOverlappingRendering}.</p>
12356     *
12357     * @param alpha The opacity of the view.
12358     *
12359     * @see #hasOverlappingRendering()
12360     * @see #setLayerType(int, android.graphics.Paint)
12361     *
12362     * @attr ref android.R.styleable#View_alpha
12363     */
12364    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
12365        ensureTransformationInfo();
12366        if (mTransformationInfo.mAlpha != alpha) {
12367            // Report visibility changes, which can affect children, to accessibility
12368            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
12369                notifySubtreeAccessibilityStateChangedIfNeeded();
12370            }
12371            mTransformationInfo.mAlpha = alpha;
12372            if (onSetAlpha((int) (alpha * 255))) {
12373                mPrivateFlags |= PFLAG_ALPHA_SET;
12374                // subclass is handling alpha - don't optimize rendering cache invalidation
12375                invalidateParentCaches();
12376                invalidate(true);
12377            } else {
12378                mPrivateFlags &= ~PFLAG_ALPHA_SET;
12379                invalidateViewProperty(true, false);
12380                mRenderNode.setAlpha(getFinalAlpha());
12381            }
12382        }
12383    }
12384
12385    /**
12386     * Faster version of setAlpha() which performs the same steps except there are
12387     * no calls to invalidate(). The caller of this function should perform proper invalidation
12388     * on the parent and this object. The return value indicates whether the subclass handles
12389     * alpha (the return value for onSetAlpha()).
12390     *
12391     * @param alpha The new value for the alpha property
12392     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
12393     *         the new value for the alpha property is different from the old value
12394     */
12395    boolean setAlphaNoInvalidation(float alpha) {
12396        ensureTransformationInfo();
12397        if (mTransformationInfo.mAlpha != alpha) {
12398            mTransformationInfo.mAlpha = alpha;
12399            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
12400            if (subclassHandlesAlpha) {
12401                mPrivateFlags |= PFLAG_ALPHA_SET;
12402                return true;
12403            } else {
12404                mPrivateFlags &= ~PFLAG_ALPHA_SET;
12405                mRenderNode.setAlpha(getFinalAlpha());
12406            }
12407        }
12408        return false;
12409    }
12410
12411    /**
12412     * This property is hidden and intended only for use by the Fade transition, which
12413     * animates it to produce a visual translucency that does not side-effect (or get
12414     * affected by) the real alpha property. This value is composited with the other
12415     * alpha value (and the AlphaAnimation value, when that is present) to produce
12416     * a final visual translucency result, which is what is passed into the DisplayList.
12417     *
12418     * @hide
12419     */
12420    public void setTransitionAlpha(float alpha) {
12421        ensureTransformationInfo();
12422        if (mTransformationInfo.mTransitionAlpha != alpha) {
12423            mTransformationInfo.mTransitionAlpha = alpha;
12424            mPrivateFlags &= ~PFLAG_ALPHA_SET;
12425            invalidateViewProperty(true, false);
12426            mRenderNode.setAlpha(getFinalAlpha());
12427        }
12428    }
12429
12430    /**
12431     * Calculates the visual alpha of this view, which is a combination of the actual
12432     * alpha value and the transitionAlpha value (if set).
12433     */
12434    private float getFinalAlpha() {
12435        if (mTransformationInfo != null) {
12436            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
12437        }
12438        return 1;
12439    }
12440
12441    /**
12442     * This property is hidden and intended only for use by the Fade transition, which
12443     * animates it to produce a visual translucency that does not side-effect (or get
12444     * affected by) the real alpha property. This value is composited with the other
12445     * alpha value (and the AlphaAnimation value, when that is present) to produce
12446     * a final visual translucency result, which is what is passed into the DisplayList.
12447     *
12448     * @hide
12449     */
12450    @ViewDebug.ExportedProperty(category = "drawing")
12451    public float getTransitionAlpha() {
12452        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
12453    }
12454
12455    /**
12456     * Top position of this view relative to its parent.
12457     *
12458     * @return The top of this view, in pixels.
12459     */
12460    @ViewDebug.CapturedViewProperty
12461    public final int getTop() {
12462        return mTop;
12463    }
12464
12465    /**
12466     * Sets the top position of this view relative to its parent. This method is meant to be called
12467     * by the layout system and should not generally be called otherwise, because the property
12468     * may be changed at any time by the layout.
12469     *
12470     * @param top The top of this view, in pixels.
12471     */
12472    public final void setTop(int top) {
12473        if (top != mTop) {
12474            final boolean matrixIsIdentity = hasIdentityMatrix();
12475            if (matrixIsIdentity) {
12476                if (mAttachInfo != null) {
12477                    int minTop;
12478                    int yLoc;
12479                    if (top < mTop) {
12480                        minTop = top;
12481                        yLoc = top - mTop;
12482                    } else {
12483                        minTop = mTop;
12484                        yLoc = 0;
12485                    }
12486                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
12487                }
12488            } else {
12489                // Double-invalidation is necessary to capture view's old and new areas
12490                invalidate(true);
12491            }
12492
12493            int width = mRight - mLeft;
12494            int oldHeight = mBottom - mTop;
12495
12496            mTop = top;
12497            mRenderNode.setTop(mTop);
12498
12499            sizeChange(width, mBottom - mTop, width, oldHeight);
12500
12501            if (!matrixIsIdentity) {
12502                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12503                invalidate(true);
12504            }
12505            mBackgroundSizeChanged = true;
12506            if (mForegroundInfo != null) {
12507                mForegroundInfo.mBoundsChanged = true;
12508            }
12509            invalidateParentIfNeeded();
12510            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12511                // View was rejected last time it was drawn by its parent; this may have changed
12512                invalidateParentIfNeeded();
12513            }
12514        }
12515    }
12516
12517    /**
12518     * Bottom position of this view relative to its parent.
12519     *
12520     * @return The bottom of this view, in pixels.
12521     */
12522    @ViewDebug.CapturedViewProperty
12523    public final int getBottom() {
12524        return mBottom;
12525    }
12526
12527    /**
12528     * True if this view has changed since the last time being drawn.
12529     *
12530     * @return The dirty state of this view.
12531     */
12532    public boolean isDirty() {
12533        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
12534    }
12535
12536    /**
12537     * Sets the bottom position of this view relative to its parent. This method is meant to be
12538     * called by the layout system and should not generally be called otherwise, because the
12539     * property may be changed at any time by the layout.
12540     *
12541     * @param bottom The bottom of this view, in pixels.
12542     */
12543    public final void setBottom(int bottom) {
12544        if (bottom != mBottom) {
12545            final boolean matrixIsIdentity = hasIdentityMatrix();
12546            if (matrixIsIdentity) {
12547                if (mAttachInfo != null) {
12548                    int maxBottom;
12549                    if (bottom < mBottom) {
12550                        maxBottom = mBottom;
12551                    } else {
12552                        maxBottom = bottom;
12553                    }
12554                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
12555                }
12556            } else {
12557                // Double-invalidation is necessary to capture view's old and new areas
12558                invalidate(true);
12559            }
12560
12561            int width = mRight - mLeft;
12562            int oldHeight = mBottom - mTop;
12563
12564            mBottom = bottom;
12565            mRenderNode.setBottom(mBottom);
12566
12567            sizeChange(width, mBottom - mTop, width, oldHeight);
12568
12569            if (!matrixIsIdentity) {
12570                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12571                invalidate(true);
12572            }
12573            mBackgroundSizeChanged = true;
12574            if (mForegroundInfo != null) {
12575                mForegroundInfo.mBoundsChanged = true;
12576            }
12577            invalidateParentIfNeeded();
12578            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12579                // View was rejected last time it was drawn by its parent; this may have changed
12580                invalidateParentIfNeeded();
12581            }
12582        }
12583    }
12584
12585    /**
12586     * Left position of this view relative to its parent.
12587     *
12588     * @return The left edge of this view, in pixels.
12589     */
12590    @ViewDebug.CapturedViewProperty
12591    public final int getLeft() {
12592        return mLeft;
12593    }
12594
12595    /**
12596     * Sets the left position of this view relative to its parent. This method is meant to be called
12597     * by the layout system and should not generally be called otherwise, because the property
12598     * may be changed at any time by the layout.
12599     *
12600     * @param left The left of this view, in pixels.
12601     */
12602    public final void setLeft(int left) {
12603        if (left != mLeft) {
12604            final boolean matrixIsIdentity = hasIdentityMatrix();
12605            if (matrixIsIdentity) {
12606                if (mAttachInfo != null) {
12607                    int minLeft;
12608                    int xLoc;
12609                    if (left < mLeft) {
12610                        minLeft = left;
12611                        xLoc = left - mLeft;
12612                    } else {
12613                        minLeft = mLeft;
12614                        xLoc = 0;
12615                    }
12616                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
12617                }
12618            } else {
12619                // Double-invalidation is necessary to capture view's old and new areas
12620                invalidate(true);
12621            }
12622
12623            int oldWidth = mRight - mLeft;
12624            int height = mBottom - mTop;
12625
12626            mLeft = left;
12627            mRenderNode.setLeft(left);
12628
12629            sizeChange(mRight - mLeft, height, oldWidth, height);
12630
12631            if (!matrixIsIdentity) {
12632                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12633                invalidate(true);
12634            }
12635            mBackgroundSizeChanged = true;
12636            if (mForegroundInfo != null) {
12637                mForegroundInfo.mBoundsChanged = true;
12638            }
12639            invalidateParentIfNeeded();
12640            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12641                // View was rejected last time it was drawn by its parent; this may have changed
12642                invalidateParentIfNeeded();
12643            }
12644        }
12645    }
12646
12647    /**
12648     * Right position of this view relative to its parent.
12649     *
12650     * @return The right edge of this view, in pixels.
12651     */
12652    @ViewDebug.CapturedViewProperty
12653    public final int getRight() {
12654        return mRight;
12655    }
12656
12657    /**
12658     * Sets the right position of this view relative to its parent. This method is meant to be called
12659     * by the layout system and should not generally be called otherwise, because the property
12660     * may be changed at any time by the layout.
12661     *
12662     * @param right The right of this view, in pixels.
12663     */
12664    public final void setRight(int right) {
12665        if (right != mRight) {
12666            final boolean matrixIsIdentity = hasIdentityMatrix();
12667            if (matrixIsIdentity) {
12668                if (mAttachInfo != null) {
12669                    int maxRight;
12670                    if (right < mRight) {
12671                        maxRight = mRight;
12672                    } else {
12673                        maxRight = right;
12674                    }
12675                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
12676                }
12677            } else {
12678                // Double-invalidation is necessary to capture view's old and new areas
12679                invalidate(true);
12680            }
12681
12682            int oldWidth = mRight - mLeft;
12683            int height = mBottom - mTop;
12684
12685            mRight = right;
12686            mRenderNode.setRight(mRight);
12687
12688            sizeChange(mRight - mLeft, height, oldWidth, height);
12689
12690            if (!matrixIsIdentity) {
12691                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12692                invalidate(true);
12693            }
12694            mBackgroundSizeChanged = true;
12695            if (mForegroundInfo != null) {
12696                mForegroundInfo.mBoundsChanged = true;
12697            }
12698            invalidateParentIfNeeded();
12699            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12700                // View was rejected last time it was drawn by its parent; this may have changed
12701                invalidateParentIfNeeded();
12702            }
12703        }
12704    }
12705
12706    /**
12707     * The visual x position of this view, in pixels. This is equivalent to the
12708     * {@link #setTranslationX(float) translationX} property plus the current
12709     * {@link #getLeft() left} property.
12710     *
12711     * @return The visual x position of this view, in pixels.
12712     */
12713    @ViewDebug.ExportedProperty(category = "drawing")
12714    public float getX() {
12715        return mLeft + getTranslationX();
12716    }
12717
12718    /**
12719     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
12720     * {@link #setTranslationX(float) translationX} property to be the difference between
12721     * the x value passed in and the current {@link #getLeft() left} property.
12722     *
12723     * @param x The visual x position of this view, in pixels.
12724     */
12725    public void setX(float x) {
12726        setTranslationX(x - mLeft);
12727    }
12728
12729    /**
12730     * The visual y position of this view, in pixels. This is equivalent to the
12731     * {@link #setTranslationY(float) translationY} property plus the current
12732     * {@link #getTop() top} property.
12733     *
12734     * @return The visual y position of this view, in pixels.
12735     */
12736    @ViewDebug.ExportedProperty(category = "drawing")
12737    public float getY() {
12738        return mTop + getTranslationY();
12739    }
12740
12741    /**
12742     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
12743     * {@link #setTranslationY(float) translationY} property to be the difference between
12744     * the y value passed in and the current {@link #getTop() top} property.
12745     *
12746     * @param y The visual y position of this view, in pixels.
12747     */
12748    public void setY(float y) {
12749        setTranslationY(y - mTop);
12750    }
12751
12752    /**
12753     * The visual z position of this view, in pixels. This is equivalent to the
12754     * {@link #setTranslationZ(float) translationZ} property plus the current
12755     * {@link #getElevation() elevation} property.
12756     *
12757     * @return The visual z position of this view, in pixels.
12758     */
12759    @ViewDebug.ExportedProperty(category = "drawing")
12760    public float getZ() {
12761        return getElevation() + getTranslationZ();
12762    }
12763
12764    /**
12765     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
12766     * {@link #setTranslationZ(float) translationZ} property to be the difference between
12767     * the x value passed in and the current {@link #getElevation() elevation} property.
12768     *
12769     * @param z The visual z position of this view, in pixels.
12770     */
12771    public void setZ(float z) {
12772        setTranslationZ(z - getElevation());
12773    }
12774
12775    /**
12776     * The base elevation of this view relative to its parent, in pixels.
12777     *
12778     * @return The base depth position of the view, in pixels.
12779     */
12780    @ViewDebug.ExportedProperty(category = "drawing")
12781    public float getElevation() {
12782        return mRenderNode.getElevation();
12783    }
12784
12785    /**
12786     * Sets the base elevation of this view, in pixels.
12787     *
12788     * @attr ref android.R.styleable#View_elevation
12789     */
12790    public void setElevation(float elevation) {
12791        if (elevation != getElevation()) {
12792            invalidateViewProperty(true, false);
12793            mRenderNode.setElevation(elevation);
12794            invalidateViewProperty(false, true);
12795
12796            invalidateParentIfNeededAndWasQuickRejected();
12797        }
12798    }
12799
12800    /**
12801     * The horizontal location of this view relative to its {@link #getLeft() left} position.
12802     * This position is post-layout, in addition to wherever the object's
12803     * layout placed it.
12804     *
12805     * @return The horizontal position of this view relative to its left position, in pixels.
12806     */
12807    @ViewDebug.ExportedProperty(category = "drawing")
12808    public float getTranslationX() {
12809        return mRenderNode.getTranslationX();
12810    }
12811
12812    /**
12813     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12814     * This effectively positions the object post-layout, in addition to wherever the object's
12815     * layout placed it.
12816     *
12817     * @param translationX The horizontal position of this view relative to its left position,
12818     * in pixels.
12819     *
12820     * @attr ref android.R.styleable#View_translationX
12821     */
12822    public void setTranslationX(float translationX) {
12823        if (translationX != getTranslationX()) {
12824            invalidateViewProperty(true, false);
12825            mRenderNode.setTranslationX(translationX);
12826            invalidateViewProperty(false, true);
12827
12828            invalidateParentIfNeededAndWasQuickRejected();
12829            notifySubtreeAccessibilityStateChangedIfNeeded();
12830        }
12831    }
12832
12833    /**
12834     * The vertical location of this view relative to its {@link #getTop() top} position.
12835     * This position is post-layout, in addition to wherever the object's
12836     * layout placed it.
12837     *
12838     * @return The vertical position of this view relative to its top position,
12839     * in pixels.
12840     */
12841    @ViewDebug.ExportedProperty(category = "drawing")
12842    public float getTranslationY() {
12843        return mRenderNode.getTranslationY();
12844    }
12845
12846    /**
12847     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12848     * This effectively positions the object post-layout, in addition to wherever the object's
12849     * layout placed it.
12850     *
12851     * @param translationY The vertical position of this view relative to its top position,
12852     * in pixels.
12853     *
12854     * @attr ref android.R.styleable#View_translationY
12855     */
12856    public void setTranslationY(float translationY) {
12857        if (translationY != getTranslationY()) {
12858            invalidateViewProperty(true, false);
12859            mRenderNode.setTranslationY(translationY);
12860            invalidateViewProperty(false, true);
12861
12862            invalidateParentIfNeededAndWasQuickRejected();
12863            notifySubtreeAccessibilityStateChangedIfNeeded();
12864        }
12865    }
12866
12867    /**
12868     * The depth location of this view relative to its {@link #getElevation() elevation}.
12869     *
12870     * @return The depth of this view relative to its elevation.
12871     */
12872    @ViewDebug.ExportedProperty(category = "drawing")
12873    public float getTranslationZ() {
12874        return mRenderNode.getTranslationZ();
12875    }
12876
12877    /**
12878     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12879     *
12880     * @attr ref android.R.styleable#View_translationZ
12881     */
12882    public void setTranslationZ(float translationZ) {
12883        if (translationZ != getTranslationZ()) {
12884            invalidateViewProperty(true, false);
12885            mRenderNode.setTranslationZ(translationZ);
12886            invalidateViewProperty(false, true);
12887
12888            invalidateParentIfNeededAndWasQuickRejected();
12889        }
12890    }
12891
12892    /** @hide */
12893    public void setAnimationMatrix(Matrix matrix) {
12894        invalidateViewProperty(true, false);
12895        mRenderNode.setAnimationMatrix(matrix);
12896        invalidateViewProperty(false, true);
12897
12898        invalidateParentIfNeededAndWasQuickRejected();
12899    }
12900
12901    /**
12902     * Returns the current StateListAnimator if exists.
12903     *
12904     * @return StateListAnimator or null if it does not exists
12905     * @see    #setStateListAnimator(android.animation.StateListAnimator)
12906     */
12907    public StateListAnimator getStateListAnimator() {
12908        return mStateListAnimator;
12909    }
12910
12911    /**
12912     * Attaches the provided StateListAnimator to this View.
12913     * <p>
12914     * Any previously attached StateListAnimator will be detached.
12915     *
12916     * @param stateListAnimator The StateListAnimator to update the view
12917     * @see {@link android.animation.StateListAnimator}
12918     */
12919    public void setStateListAnimator(StateListAnimator stateListAnimator) {
12920        if (mStateListAnimator == stateListAnimator) {
12921            return;
12922        }
12923        if (mStateListAnimator != null) {
12924            mStateListAnimator.setTarget(null);
12925        }
12926        mStateListAnimator = stateListAnimator;
12927        if (stateListAnimator != null) {
12928            stateListAnimator.setTarget(this);
12929            if (isAttachedToWindow()) {
12930                stateListAnimator.setState(getDrawableState());
12931            }
12932        }
12933    }
12934
12935    /**
12936     * Returns whether the Outline should be used to clip the contents of the View.
12937     * <p>
12938     * Note that this flag will only be respected if the View's Outline returns true from
12939     * {@link Outline#canClip()}.
12940     *
12941     * @see #setOutlineProvider(ViewOutlineProvider)
12942     * @see #setClipToOutline(boolean)
12943     */
12944    public final boolean getClipToOutline() {
12945        return mRenderNode.getClipToOutline();
12946    }
12947
12948    /**
12949     * Sets whether the View's Outline should be used to clip the contents of the View.
12950     * <p>
12951     * Only a single non-rectangular clip can be applied on a View at any time.
12952     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12953     * circular reveal} animation take priority over Outline clipping, and
12954     * child Outline clipping takes priority over Outline clipping done by a
12955     * parent.
12956     * <p>
12957     * Note that this flag will only be respected if the View's Outline returns true from
12958     * {@link Outline#canClip()}.
12959     *
12960     * @see #setOutlineProvider(ViewOutlineProvider)
12961     * @see #getClipToOutline()
12962     */
12963    public void setClipToOutline(boolean clipToOutline) {
12964        damageInParent();
12965        if (getClipToOutline() != clipToOutline) {
12966            mRenderNode.setClipToOutline(clipToOutline);
12967        }
12968    }
12969
12970    // correspond to the enum values of View_outlineProvider
12971    private static final int PROVIDER_BACKGROUND = 0;
12972    private static final int PROVIDER_NONE = 1;
12973    private static final int PROVIDER_BOUNDS = 2;
12974    private static final int PROVIDER_PADDED_BOUNDS = 3;
12975    private void setOutlineProviderFromAttribute(int providerInt) {
12976        switch (providerInt) {
12977            case PROVIDER_BACKGROUND:
12978                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12979                break;
12980            case PROVIDER_NONE:
12981                setOutlineProvider(null);
12982                break;
12983            case PROVIDER_BOUNDS:
12984                setOutlineProvider(ViewOutlineProvider.BOUNDS);
12985                break;
12986            case PROVIDER_PADDED_BOUNDS:
12987                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12988                break;
12989        }
12990    }
12991
12992    /**
12993     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12994     * the shape of the shadow it casts, and enables outline clipping.
12995     * <p>
12996     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12997     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12998     * outline provider with this method allows this behavior to be overridden.
12999     * <p>
13000     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
13001     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
13002     * <p>
13003     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
13004     *
13005     * @see #setClipToOutline(boolean)
13006     * @see #getClipToOutline()
13007     * @see #getOutlineProvider()
13008     */
13009    public void setOutlineProvider(ViewOutlineProvider provider) {
13010        mOutlineProvider = provider;
13011        invalidateOutline();
13012    }
13013
13014    /**
13015     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
13016     * that defines the shape of the shadow it casts, and enables outline clipping.
13017     *
13018     * @see #setOutlineProvider(ViewOutlineProvider)
13019     */
13020    public ViewOutlineProvider getOutlineProvider() {
13021        return mOutlineProvider;
13022    }
13023
13024    /**
13025     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
13026     *
13027     * @see #setOutlineProvider(ViewOutlineProvider)
13028     */
13029    public void invalidateOutline() {
13030        rebuildOutline();
13031
13032        notifySubtreeAccessibilityStateChangedIfNeeded();
13033        invalidateViewProperty(false, false);
13034    }
13035
13036    /**
13037     * Internal version of {@link #invalidateOutline()} which invalidates the
13038     * outline without invalidating the view itself. This is intended to be called from
13039     * within methods in the View class itself which are the result of the view being
13040     * invalidated already. For example, when we are drawing the background of a View,
13041     * we invalidate the outline in case it changed in the meantime, but we do not
13042     * need to invalidate the view because we're already drawing the background as part
13043     * of drawing the view in response to an earlier invalidation of the view.
13044     */
13045    private void rebuildOutline() {
13046        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
13047        if (mAttachInfo == null) return;
13048
13049        if (mOutlineProvider == null) {
13050            // no provider, remove outline
13051            mRenderNode.setOutline(null);
13052        } else {
13053            final Outline outline = mAttachInfo.mTmpOutline;
13054            outline.setEmpty();
13055            outline.setAlpha(1.0f);
13056
13057            mOutlineProvider.getOutline(this, outline);
13058            mRenderNode.setOutline(outline);
13059        }
13060    }
13061
13062    /**
13063     * HierarchyViewer only
13064     *
13065     * @hide
13066     */
13067    @ViewDebug.ExportedProperty(category = "drawing")
13068    public boolean hasShadow() {
13069        return mRenderNode.hasShadow();
13070    }
13071
13072
13073    /** @hide */
13074    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
13075        mRenderNode.setRevealClip(shouldClip, x, y, radius);
13076        invalidateViewProperty(false, false);
13077    }
13078
13079    /**
13080     * Hit rectangle in parent's coordinates
13081     *
13082     * @param outRect The hit rectangle of the view.
13083     */
13084    public void getHitRect(Rect outRect) {
13085        if (hasIdentityMatrix() || mAttachInfo == null) {
13086            outRect.set(mLeft, mTop, mRight, mBottom);
13087        } else {
13088            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
13089            tmpRect.set(0, 0, getWidth(), getHeight());
13090            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
13091            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
13092                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
13093        }
13094    }
13095
13096    /**
13097     * Determines whether the given point, in local coordinates is inside the view.
13098     */
13099    /*package*/ final boolean pointInView(float localX, float localY) {
13100        return pointInView(localX, localY, 0);
13101    }
13102
13103    /**
13104     * Utility method to determine whether the given point, in local coordinates,
13105     * is inside the view, where the area of the view is expanded by the slop factor.
13106     * This method is called while processing touch-move events to determine if the event
13107     * is still within the view.
13108     *
13109     * @hide
13110     */
13111    public boolean pointInView(float localX, float localY, float slop) {
13112        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
13113                localY < ((mBottom - mTop) + slop);
13114    }
13115
13116    /**
13117     * When a view has focus and the user navigates away from it, the next view is searched for
13118     * starting from the rectangle filled in by this method.
13119     *
13120     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
13121     * of the view.  However, if your view maintains some idea of internal selection,
13122     * such as a cursor, or a selected row or column, you should override this method and
13123     * fill in a more specific rectangle.
13124     *
13125     * @param r The rectangle to fill in, in this view's coordinates.
13126     */
13127    public void getFocusedRect(Rect r) {
13128        getDrawingRect(r);
13129    }
13130
13131    /**
13132     * If some part of this view is not clipped by any of its parents, then
13133     * return that area in r in global (root) coordinates. To convert r to local
13134     * coordinates (without taking possible View rotations into account), offset
13135     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
13136     * If the view is completely clipped or translated out, return false.
13137     *
13138     * @param r If true is returned, r holds the global coordinates of the
13139     *        visible portion of this view.
13140     * @param globalOffset If true is returned, globalOffset holds the dx,dy
13141     *        between this view and its root. globalOffet may be null.
13142     * @return true if r is non-empty (i.e. part of the view is visible at the
13143     *         root level.
13144     */
13145    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
13146        int width = mRight - mLeft;
13147        int height = mBottom - mTop;
13148        if (width > 0 && height > 0) {
13149            r.set(0, 0, width, height);
13150            if (globalOffset != null) {
13151                globalOffset.set(-mScrollX, -mScrollY);
13152            }
13153            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
13154        }
13155        return false;
13156    }
13157
13158    public final boolean getGlobalVisibleRect(Rect r) {
13159        return getGlobalVisibleRect(r, null);
13160    }
13161
13162    public final boolean getLocalVisibleRect(Rect r) {
13163        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
13164        if (getGlobalVisibleRect(r, offset)) {
13165            r.offset(-offset.x, -offset.y); // make r local
13166            return true;
13167        }
13168        return false;
13169    }
13170
13171    /**
13172     * Offset this view's vertical location by the specified number of pixels.
13173     *
13174     * @param offset the number of pixels to offset the view by
13175     */
13176    public void offsetTopAndBottom(int offset) {
13177        if (offset != 0) {
13178            final boolean matrixIsIdentity = hasIdentityMatrix();
13179            if (matrixIsIdentity) {
13180                if (isHardwareAccelerated()) {
13181                    invalidateViewProperty(false, false);
13182                } else {
13183                    final ViewParent p = mParent;
13184                    if (p != null && mAttachInfo != null) {
13185                        final Rect r = mAttachInfo.mTmpInvalRect;
13186                        int minTop;
13187                        int maxBottom;
13188                        int yLoc;
13189                        if (offset < 0) {
13190                            minTop = mTop + offset;
13191                            maxBottom = mBottom;
13192                            yLoc = offset;
13193                        } else {
13194                            minTop = mTop;
13195                            maxBottom = mBottom + offset;
13196                            yLoc = 0;
13197                        }
13198                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
13199                        p.invalidateChild(this, r);
13200                    }
13201                }
13202            } else {
13203                invalidateViewProperty(false, false);
13204            }
13205
13206            mTop += offset;
13207            mBottom += offset;
13208            mRenderNode.offsetTopAndBottom(offset);
13209            if (isHardwareAccelerated()) {
13210                invalidateViewProperty(false, false);
13211                invalidateParentIfNeededAndWasQuickRejected();
13212            } else {
13213                if (!matrixIsIdentity) {
13214                    invalidateViewProperty(false, true);
13215                }
13216                invalidateParentIfNeeded();
13217            }
13218            notifySubtreeAccessibilityStateChangedIfNeeded();
13219        }
13220    }
13221
13222    /**
13223     * Offset this view's horizontal location by the specified amount of pixels.
13224     *
13225     * @param offset the number of pixels to offset the view by
13226     */
13227    public void offsetLeftAndRight(int offset) {
13228        if (offset != 0) {
13229            final boolean matrixIsIdentity = hasIdentityMatrix();
13230            if (matrixIsIdentity) {
13231                if (isHardwareAccelerated()) {
13232                    invalidateViewProperty(false, false);
13233                } else {
13234                    final ViewParent p = mParent;
13235                    if (p != null && mAttachInfo != null) {
13236                        final Rect r = mAttachInfo.mTmpInvalRect;
13237                        int minLeft;
13238                        int maxRight;
13239                        if (offset < 0) {
13240                            minLeft = mLeft + offset;
13241                            maxRight = mRight;
13242                        } else {
13243                            minLeft = mLeft;
13244                            maxRight = mRight + offset;
13245                        }
13246                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
13247                        p.invalidateChild(this, r);
13248                    }
13249                }
13250            } else {
13251                invalidateViewProperty(false, false);
13252            }
13253
13254            mLeft += offset;
13255            mRight += offset;
13256            mRenderNode.offsetLeftAndRight(offset);
13257            if (isHardwareAccelerated()) {
13258                invalidateViewProperty(false, false);
13259                invalidateParentIfNeededAndWasQuickRejected();
13260            } else {
13261                if (!matrixIsIdentity) {
13262                    invalidateViewProperty(false, true);
13263                }
13264                invalidateParentIfNeeded();
13265            }
13266            notifySubtreeAccessibilityStateChangedIfNeeded();
13267        }
13268    }
13269
13270    /**
13271     * Get the LayoutParams associated with this view. All views should have
13272     * layout parameters. These supply parameters to the <i>parent</i> of this
13273     * view specifying how it should be arranged. There are many subclasses of
13274     * ViewGroup.LayoutParams, and these correspond to the different subclasses
13275     * of ViewGroup that are responsible for arranging their children.
13276     *
13277     * This method may return null if this View is not attached to a parent
13278     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
13279     * was not invoked successfully. When a View is attached to a parent
13280     * ViewGroup, this method must not return null.
13281     *
13282     * @return The LayoutParams associated with this view, or null if no
13283     *         parameters have been set yet
13284     */
13285    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
13286    public ViewGroup.LayoutParams getLayoutParams() {
13287        return mLayoutParams;
13288    }
13289
13290    /**
13291     * Set the layout parameters associated with this view. These supply
13292     * parameters to the <i>parent</i> of this view specifying how it should be
13293     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
13294     * correspond to the different subclasses of ViewGroup that are responsible
13295     * for arranging their children.
13296     *
13297     * @param params The layout parameters for this view, cannot be null
13298     */
13299    public void setLayoutParams(ViewGroup.LayoutParams params) {
13300        if (params == null) {
13301            throw new NullPointerException("Layout parameters cannot be null");
13302        }
13303        mLayoutParams = params;
13304        resolveLayoutParams();
13305        if (mParent instanceof ViewGroup) {
13306            ((ViewGroup) mParent).onSetLayoutParams(this, params);
13307        }
13308        requestLayout();
13309    }
13310
13311    /**
13312     * Resolve the layout parameters depending on the resolved layout direction
13313     *
13314     * @hide
13315     */
13316    public void resolveLayoutParams() {
13317        if (mLayoutParams != null) {
13318            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
13319        }
13320    }
13321
13322    /**
13323     * Set the scrolled position of your view. This will cause a call to
13324     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13325     * invalidated.
13326     * @param x the x position to scroll to
13327     * @param y the y position to scroll to
13328     */
13329    public void scrollTo(int x, int y) {
13330        if (mScrollX != x || mScrollY != y) {
13331            int oldX = mScrollX;
13332            int oldY = mScrollY;
13333            mScrollX = x;
13334            mScrollY = y;
13335            invalidateParentCaches();
13336            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
13337            if (!awakenScrollBars()) {
13338                postInvalidateOnAnimation();
13339            }
13340        }
13341    }
13342
13343    /**
13344     * Move the scrolled position of your view. This will cause a call to
13345     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13346     * invalidated.
13347     * @param x the amount of pixels to scroll by horizontally
13348     * @param y the amount of pixels to scroll by vertically
13349     */
13350    public void scrollBy(int x, int y) {
13351        scrollTo(mScrollX + x, mScrollY + y);
13352    }
13353
13354    /**
13355     * <p>Trigger the scrollbars to draw. When invoked this method starts an
13356     * animation to fade the scrollbars out after a default delay. If a subclass
13357     * provides animated scrolling, the start delay should equal the duration
13358     * of the scrolling animation.</p>
13359     *
13360     * <p>The animation starts only if at least one of the scrollbars is
13361     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
13362     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13363     * this method returns true, and false otherwise. If the animation is
13364     * started, this method calls {@link #invalidate()}; in that case the
13365     * caller should not call {@link #invalidate()}.</p>
13366     *
13367     * <p>This method should be invoked every time a subclass directly updates
13368     * the scroll parameters.</p>
13369     *
13370     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
13371     * and {@link #scrollTo(int, int)}.</p>
13372     *
13373     * @return true if the animation is played, false otherwise
13374     *
13375     * @see #awakenScrollBars(int)
13376     * @see #scrollBy(int, int)
13377     * @see #scrollTo(int, int)
13378     * @see #isHorizontalScrollBarEnabled()
13379     * @see #isVerticalScrollBarEnabled()
13380     * @see #setHorizontalScrollBarEnabled(boolean)
13381     * @see #setVerticalScrollBarEnabled(boolean)
13382     */
13383    protected boolean awakenScrollBars() {
13384        return mScrollCache != null &&
13385                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
13386    }
13387
13388    /**
13389     * Trigger the scrollbars to draw.
13390     * This method differs from awakenScrollBars() only in its default duration.
13391     * initialAwakenScrollBars() will show the scroll bars for longer than
13392     * usual to give the user more of a chance to notice them.
13393     *
13394     * @return true if the animation is played, false otherwise.
13395     */
13396    private boolean initialAwakenScrollBars() {
13397        return mScrollCache != null &&
13398                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
13399    }
13400
13401    /**
13402     * <p>
13403     * Trigger the scrollbars to draw. When invoked this method starts an
13404     * animation to fade the scrollbars out after a fixed delay. If a subclass
13405     * provides animated scrolling, the start delay should equal the duration of
13406     * the scrolling animation.
13407     * </p>
13408     *
13409     * <p>
13410     * The animation starts only if at least one of the scrollbars is enabled,
13411     * as specified by {@link #isHorizontalScrollBarEnabled()} and
13412     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13413     * this method returns true, and false otherwise. If the animation is
13414     * started, this method calls {@link #invalidate()}; in that case the caller
13415     * should not call {@link #invalidate()}.
13416     * </p>
13417     *
13418     * <p>
13419     * This method should be invoked every time a subclass directly updates the
13420     * scroll parameters.
13421     * </p>
13422     *
13423     * @param startDelay the delay, in milliseconds, after which the animation
13424     *        should start; when the delay is 0, the animation starts
13425     *        immediately
13426     * @return true if the animation is played, false otherwise
13427     *
13428     * @see #scrollBy(int, int)
13429     * @see #scrollTo(int, int)
13430     * @see #isHorizontalScrollBarEnabled()
13431     * @see #isVerticalScrollBarEnabled()
13432     * @see #setHorizontalScrollBarEnabled(boolean)
13433     * @see #setVerticalScrollBarEnabled(boolean)
13434     */
13435    protected boolean awakenScrollBars(int startDelay) {
13436        return awakenScrollBars(startDelay, true);
13437    }
13438
13439    /**
13440     * <p>
13441     * Trigger the scrollbars to draw. When invoked this method starts an
13442     * animation to fade the scrollbars out after a fixed delay. If a subclass
13443     * provides animated scrolling, the start delay should equal the duration of
13444     * the scrolling animation.
13445     * </p>
13446     *
13447     * <p>
13448     * The animation starts only if at least one of the scrollbars is enabled,
13449     * as specified by {@link #isHorizontalScrollBarEnabled()} and
13450     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13451     * this method returns true, and false otherwise. If the animation is
13452     * started, this method calls {@link #invalidate()} if the invalidate parameter
13453     * is set to true; in that case the caller
13454     * should not call {@link #invalidate()}.
13455     * </p>
13456     *
13457     * <p>
13458     * This method should be invoked every time a subclass directly updates the
13459     * scroll parameters.
13460     * </p>
13461     *
13462     * @param startDelay the delay, in milliseconds, after which the animation
13463     *        should start; when the delay is 0, the animation starts
13464     *        immediately
13465     *
13466     * @param invalidate Whether this method should call invalidate
13467     *
13468     * @return true if the animation is played, false otherwise
13469     *
13470     * @see #scrollBy(int, int)
13471     * @see #scrollTo(int, int)
13472     * @see #isHorizontalScrollBarEnabled()
13473     * @see #isVerticalScrollBarEnabled()
13474     * @see #setHorizontalScrollBarEnabled(boolean)
13475     * @see #setVerticalScrollBarEnabled(boolean)
13476     */
13477    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
13478        final ScrollabilityCache scrollCache = mScrollCache;
13479
13480        if (scrollCache == null || !scrollCache.fadeScrollBars) {
13481            return false;
13482        }
13483
13484        if (scrollCache.scrollBar == null) {
13485            scrollCache.scrollBar = new ScrollBarDrawable();
13486            scrollCache.scrollBar.setState(getDrawableState());
13487            scrollCache.scrollBar.setCallback(this);
13488        }
13489
13490        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
13491
13492            if (invalidate) {
13493                // Invalidate to show the scrollbars
13494                postInvalidateOnAnimation();
13495            }
13496
13497            if (scrollCache.state == ScrollabilityCache.OFF) {
13498                // FIXME: this is copied from WindowManagerService.
13499                // We should get this value from the system when it
13500                // is possible to do so.
13501                final int KEY_REPEAT_FIRST_DELAY = 750;
13502                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
13503            }
13504
13505            // Tell mScrollCache when we should start fading. This may
13506            // extend the fade start time if one was already scheduled
13507            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
13508            scrollCache.fadeStartTime = fadeStartTime;
13509            scrollCache.state = ScrollabilityCache.ON;
13510
13511            // Schedule our fader to run, unscheduling any old ones first
13512            if (mAttachInfo != null) {
13513                mAttachInfo.mHandler.removeCallbacks(scrollCache);
13514                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
13515            }
13516
13517            return true;
13518        }
13519
13520        return false;
13521    }
13522
13523    /**
13524     * Do not invalidate views which are not visible and which are not running an animation. They
13525     * will not get drawn and they should not set dirty flags as if they will be drawn
13526     */
13527    private boolean skipInvalidate() {
13528        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
13529                (!(mParent instanceof ViewGroup) ||
13530                        !((ViewGroup) mParent).isViewTransitioning(this));
13531    }
13532
13533    /**
13534     * Mark the area defined by dirty as needing to be drawn. If the view is
13535     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13536     * point in the future.
13537     * <p>
13538     * This must be called from a UI thread. To call from a non-UI thread, call
13539     * {@link #postInvalidate()}.
13540     * <p>
13541     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
13542     * {@code dirty}.
13543     *
13544     * @param dirty the rectangle representing the bounds of the dirty region
13545     */
13546    public void invalidate(Rect dirty) {
13547        final int scrollX = mScrollX;
13548        final int scrollY = mScrollY;
13549        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
13550                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
13551    }
13552
13553    /**
13554     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
13555     * coordinates of the dirty rect are relative to the view. If the view is
13556     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13557     * point in the future.
13558     * <p>
13559     * This must be called from a UI thread. To call from a non-UI thread, call
13560     * {@link #postInvalidate()}.
13561     *
13562     * @param l the left position of the dirty region
13563     * @param t the top position of the dirty region
13564     * @param r the right position of the dirty region
13565     * @param b the bottom position of the dirty region
13566     */
13567    public void invalidate(int l, int t, int r, int b) {
13568        final int scrollX = mScrollX;
13569        final int scrollY = mScrollY;
13570        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
13571    }
13572
13573    /**
13574     * Invalidate the whole view. If the view is visible,
13575     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
13576     * the future.
13577     * <p>
13578     * This must be called from a UI thread. To call from a non-UI thread, call
13579     * {@link #postInvalidate()}.
13580     */
13581    public void invalidate() {
13582        invalidate(true);
13583    }
13584
13585    /**
13586     * This is where the invalidate() work actually happens. A full invalidate()
13587     * causes the drawing cache to be invalidated, but this function can be
13588     * called with invalidateCache set to false to skip that invalidation step
13589     * for cases that do not need it (for example, a component that remains at
13590     * the same dimensions with the same content).
13591     *
13592     * @param invalidateCache Whether the drawing cache for this view should be
13593     *            invalidated as well. This is usually true for a full
13594     *            invalidate, but may be set to false if the View's contents or
13595     *            dimensions have not changed.
13596     */
13597    void invalidate(boolean invalidateCache) {
13598        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
13599    }
13600
13601    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
13602            boolean fullInvalidate) {
13603        if (mGhostView != null) {
13604            mGhostView.invalidate(true);
13605            return;
13606        }
13607
13608        if (skipInvalidate()) {
13609            return;
13610        }
13611
13612        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
13613                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
13614                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
13615                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
13616            if (fullInvalidate) {
13617                mLastIsOpaque = isOpaque();
13618                mPrivateFlags &= ~PFLAG_DRAWN;
13619            }
13620
13621            mPrivateFlags |= PFLAG_DIRTY;
13622
13623            if (invalidateCache) {
13624                mPrivateFlags |= PFLAG_INVALIDATED;
13625                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13626            }
13627
13628            // Propagate the damage rectangle to the parent view.
13629            final AttachInfo ai = mAttachInfo;
13630            final ViewParent p = mParent;
13631            if (p != null && ai != null && l < r && t < b) {
13632                final Rect damage = ai.mTmpInvalRect;
13633                damage.set(l, t, r, b);
13634                p.invalidateChild(this, damage);
13635            }
13636
13637            // Damage the entire projection receiver, if necessary.
13638            if (mBackground != null && mBackground.isProjected()) {
13639                final View receiver = getProjectionReceiver();
13640                if (receiver != null) {
13641                    receiver.damageInParent();
13642                }
13643            }
13644
13645            // Damage the entire IsolatedZVolume receiving this view's shadow.
13646            if (isHardwareAccelerated() && getZ() != 0) {
13647                damageShadowReceiver();
13648            }
13649        }
13650    }
13651
13652    /**
13653     * @return this view's projection receiver, or {@code null} if none exists
13654     */
13655    private View getProjectionReceiver() {
13656        ViewParent p = getParent();
13657        while (p != null && p instanceof View) {
13658            final View v = (View) p;
13659            if (v.isProjectionReceiver()) {
13660                return v;
13661            }
13662            p = p.getParent();
13663        }
13664
13665        return null;
13666    }
13667
13668    /**
13669     * @return whether the view is a projection receiver
13670     */
13671    private boolean isProjectionReceiver() {
13672        return mBackground != null;
13673    }
13674
13675    /**
13676     * Damage area of the screen that can be covered by this View's shadow.
13677     *
13678     * This method will guarantee that any changes to shadows cast by a View
13679     * are damaged on the screen for future redraw.
13680     */
13681    private void damageShadowReceiver() {
13682        final AttachInfo ai = mAttachInfo;
13683        if (ai != null) {
13684            ViewParent p = getParent();
13685            if (p != null && p instanceof ViewGroup) {
13686                final ViewGroup vg = (ViewGroup) p;
13687                vg.damageInParent();
13688            }
13689        }
13690    }
13691
13692    /**
13693     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
13694     * set any flags or handle all of the cases handled by the default invalidation methods.
13695     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
13696     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
13697     * walk up the hierarchy, transforming the dirty rect as necessary.
13698     *
13699     * The method also handles normal invalidation logic if display list properties are not
13700     * being used in this view. The invalidateParent and forceRedraw flags are used by that
13701     * backup approach, to handle these cases used in the various property-setting methods.
13702     *
13703     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
13704     * are not being used in this view
13705     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
13706     * list properties are not being used in this view
13707     */
13708    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
13709        if (!isHardwareAccelerated()
13710                || !mRenderNode.isValid()
13711                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
13712            if (invalidateParent) {
13713                invalidateParentCaches();
13714            }
13715            if (forceRedraw) {
13716                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13717            }
13718            invalidate(false);
13719        } else {
13720            damageInParent();
13721        }
13722        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
13723            damageShadowReceiver();
13724        }
13725    }
13726
13727    /**
13728     * Tells the parent view to damage this view's bounds.
13729     *
13730     * @hide
13731     */
13732    protected void damageInParent() {
13733        final AttachInfo ai = mAttachInfo;
13734        final ViewParent p = mParent;
13735        if (p != null && ai != null) {
13736            final Rect r = ai.mTmpInvalRect;
13737            r.set(0, 0, mRight - mLeft, mBottom - mTop);
13738            if (mParent instanceof ViewGroup) {
13739                ((ViewGroup) mParent).damageChild(this, r);
13740            } else {
13741                mParent.invalidateChild(this, r);
13742            }
13743        }
13744    }
13745
13746    /**
13747     * Utility method to transform a given Rect by the current matrix of this view.
13748     */
13749    void transformRect(final Rect rect) {
13750        if (!getMatrix().isIdentity()) {
13751            RectF boundingRect = mAttachInfo.mTmpTransformRect;
13752            boundingRect.set(rect);
13753            getMatrix().mapRect(boundingRect);
13754            rect.set((int) Math.floor(boundingRect.left),
13755                    (int) Math.floor(boundingRect.top),
13756                    (int) Math.ceil(boundingRect.right),
13757                    (int) Math.ceil(boundingRect.bottom));
13758        }
13759    }
13760
13761    /**
13762     * Used to indicate that the parent of this view should clear its caches. This functionality
13763     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13764     * which is necessary when various parent-managed properties of the view change, such as
13765     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
13766     * clears the parent caches and does not causes an invalidate event.
13767     *
13768     * @hide
13769     */
13770    protected void invalidateParentCaches() {
13771        if (mParent instanceof View) {
13772            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
13773        }
13774    }
13775
13776    /**
13777     * Used to indicate that the parent of this view should be invalidated. This functionality
13778     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13779     * which is necessary when various parent-managed properties of the view change, such as
13780     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
13781     * an invalidation event to the parent.
13782     *
13783     * @hide
13784     */
13785    protected void invalidateParentIfNeeded() {
13786        if (isHardwareAccelerated() && mParent instanceof View) {
13787            ((View) mParent).invalidate(true);
13788        }
13789    }
13790
13791    /**
13792     * @hide
13793     */
13794    protected void invalidateParentIfNeededAndWasQuickRejected() {
13795        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
13796            // View was rejected last time it was drawn by its parent; this may have changed
13797            invalidateParentIfNeeded();
13798        }
13799    }
13800
13801    /**
13802     * Indicates whether this View is opaque. An opaque View guarantees that it will
13803     * draw all the pixels overlapping its bounds using a fully opaque color.
13804     *
13805     * Subclasses of View should override this method whenever possible to indicate
13806     * whether an instance is opaque. Opaque Views are treated in a special way by
13807     * the View hierarchy, possibly allowing it to perform optimizations during
13808     * invalidate/draw passes.
13809     *
13810     * @return True if this View is guaranteed to be fully opaque, false otherwise.
13811     */
13812    @ViewDebug.ExportedProperty(category = "drawing")
13813    public boolean isOpaque() {
13814        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13815                getFinalAlpha() >= 1.0f;
13816    }
13817
13818    /**
13819     * @hide
13820     */
13821    protected void computeOpaqueFlags() {
13822        // Opaque if:
13823        //   - Has a background
13824        //   - Background is opaque
13825        //   - Doesn't have scrollbars or scrollbars overlay
13826
13827        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13828            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13829        } else {
13830            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13831        }
13832
13833        final int flags = mViewFlags;
13834        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13835                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13836                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13837            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13838        } else {
13839            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13840        }
13841    }
13842
13843    /**
13844     * @hide
13845     */
13846    protected boolean hasOpaqueScrollbars() {
13847        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13848    }
13849
13850    /**
13851     * @return A handler associated with the thread running the View. This
13852     * handler can be used to pump events in the UI events queue.
13853     */
13854    public Handler getHandler() {
13855        final AttachInfo attachInfo = mAttachInfo;
13856        if (attachInfo != null) {
13857            return attachInfo.mHandler;
13858        }
13859        return null;
13860    }
13861
13862    /**
13863     * Returns the queue of runnable for this view.
13864     *
13865     * @return the queue of runnables for this view
13866     */
13867    private HandlerActionQueue getRunQueue() {
13868        if (mRunQueue == null) {
13869            mRunQueue = new HandlerActionQueue();
13870        }
13871        return mRunQueue;
13872    }
13873
13874    /**
13875     * Gets the view root associated with the View.
13876     * @return The view root, or null if none.
13877     * @hide
13878     */
13879    public ViewRootImpl getViewRootImpl() {
13880        if (mAttachInfo != null) {
13881            return mAttachInfo.mViewRootImpl;
13882        }
13883        return null;
13884    }
13885
13886    /**
13887     * @hide
13888     */
13889    public ThreadedRenderer getThreadedRenderer() {
13890        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
13891    }
13892
13893    /**
13894     * <p>Causes the Runnable to be added to the message queue.
13895     * The runnable will be run on the user interface thread.</p>
13896     *
13897     * @param action The Runnable that will be executed.
13898     *
13899     * @return Returns true if the Runnable was successfully placed in to the
13900     *         message queue.  Returns false on failure, usually because the
13901     *         looper processing the message queue is exiting.
13902     *
13903     * @see #postDelayed
13904     * @see #removeCallbacks
13905     */
13906    public boolean post(Runnable action) {
13907        final AttachInfo attachInfo = mAttachInfo;
13908        if (attachInfo != null) {
13909            return attachInfo.mHandler.post(action);
13910        }
13911
13912        // Postpone the runnable until we know on which thread it needs to run.
13913        // Assume that the runnable will be successfully placed after attach.
13914        getRunQueue().post(action);
13915        return true;
13916    }
13917
13918    /**
13919     * <p>Causes the Runnable to be added to the message queue, to be run
13920     * after the specified amount of time elapses.
13921     * The runnable will be run on the user interface thread.</p>
13922     *
13923     * @param action The Runnable that will be executed.
13924     * @param delayMillis The delay (in milliseconds) until the Runnable
13925     *        will be executed.
13926     *
13927     * @return true if the Runnable was successfully placed in to the
13928     *         message queue.  Returns false on failure, usually because the
13929     *         looper processing the message queue is exiting.  Note that a
13930     *         result of true does not mean the Runnable will be processed --
13931     *         if the looper is quit before the delivery time of the message
13932     *         occurs then the message will be dropped.
13933     *
13934     * @see #post
13935     * @see #removeCallbacks
13936     */
13937    public boolean postDelayed(Runnable action, long delayMillis) {
13938        final AttachInfo attachInfo = mAttachInfo;
13939        if (attachInfo != null) {
13940            return attachInfo.mHandler.postDelayed(action, delayMillis);
13941        }
13942
13943        // Postpone the runnable until we know on which thread it needs to run.
13944        // Assume that the runnable will be successfully placed after attach.
13945        getRunQueue().postDelayed(action, delayMillis);
13946        return true;
13947    }
13948
13949    /**
13950     * <p>Causes the Runnable to execute on the next animation time step.
13951     * The runnable will be run on the user interface thread.</p>
13952     *
13953     * @param action The Runnable that will be executed.
13954     *
13955     * @see #postOnAnimationDelayed
13956     * @see #removeCallbacks
13957     */
13958    public void postOnAnimation(Runnable action) {
13959        final AttachInfo attachInfo = mAttachInfo;
13960        if (attachInfo != null) {
13961            attachInfo.mViewRootImpl.mChoreographer.postCallback(
13962                    Choreographer.CALLBACK_ANIMATION, action, null);
13963        } else {
13964            // Postpone the runnable until we know
13965            // on which thread it needs to run.
13966            getRunQueue().post(action);
13967        }
13968    }
13969
13970    /**
13971     * <p>Causes the Runnable to execute on the next animation time step,
13972     * after the specified amount of time elapses.
13973     * The runnable will be run on the user interface thread.</p>
13974     *
13975     * @param action The Runnable that will be executed.
13976     * @param delayMillis The delay (in milliseconds) until the Runnable
13977     *        will be executed.
13978     *
13979     * @see #postOnAnimation
13980     * @see #removeCallbacks
13981     */
13982    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13983        final AttachInfo attachInfo = mAttachInfo;
13984        if (attachInfo != null) {
13985            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13986                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13987        } else {
13988            // Postpone the runnable until we know
13989            // on which thread it needs to run.
13990            getRunQueue().postDelayed(action, delayMillis);
13991        }
13992    }
13993
13994    /**
13995     * <p>Removes the specified Runnable from the message queue.</p>
13996     *
13997     * @param action The Runnable to remove from the message handling queue
13998     *
13999     * @return true if this view could ask the Handler to remove the Runnable,
14000     *         false otherwise. When the returned value is true, the Runnable
14001     *         may or may not have been actually removed from the message queue
14002     *         (for instance, if the Runnable was not in the queue already.)
14003     *
14004     * @see #post
14005     * @see #postDelayed
14006     * @see #postOnAnimation
14007     * @see #postOnAnimationDelayed
14008     */
14009    public boolean removeCallbacks(Runnable action) {
14010        if (action != null) {
14011            final AttachInfo attachInfo = mAttachInfo;
14012            if (attachInfo != null) {
14013                attachInfo.mHandler.removeCallbacks(action);
14014                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14015                        Choreographer.CALLBACK_ANIMATION, action, null);
14016            }
14017            getRunQueue().removeCallbacks(action);
14018        }
14019        return true;
14020    }
14021
14022    /**
14023     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
14024     * Use this to invalidate the View from a non-UI thread.</p>
14025     *
14026     * <p>This method can be invoked from outside of the UI thread
14027     * only when this View is attached to a window.</p>
14028     *
14029     * @see #invalidate()
14030     * @see #postInvalidateDelayed(long)
14031     */
14032    public void postInvalidate() {
14033        postInvalidateDelayed(0);
14034    }
14035
14036    /**
14037     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14038     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
14039     *
14040     * <p>This method can be invoked from outside of the UI thread
14041     * only when this View is attached to a window.</p>
14042     *
14043     * @param left The left coordinate of the rectangle to invalidate.
14044     * @param top The top coordinate of the rectangle to invalidate.
14045     * @param right The right coordinate of the rectangle to invalidate.
14046     * @param bottom The bottom coordinate of the rectangle to invalidate.
14047     *
14048     * @see #invalidate(int, int, int, int)
14049     * @see #invalidate(Rect)
14050     * @see #postInvalidateDelayed(long, int, int, int, int)
14051     */
14052    public void postInvalidate(int left, int top, int right, int bottom) {
14053        postInvalidateDelayed(0, left, top, right, bottom);
14054    }
14055
14056    /**
14057     * <p>Cause an invalidate to happen on a subsequent cycle through the event
14058     * loop. Waits for the specified amount of time.</p>
14059     *
14060     * <p>This method can be invoked from outside of the UI thread
14061     * only when this View is attached to a window.</p>
14062     *
14063     * @param delayMilliseconds the duration in milliseconds to delay the
14064     *         invalidation by
14065     *
14066     * @see #invalidate()
14067     * @see #postInvalidate()
14068     */
14069    public void postInvalidateDelayed(long delayMilliseconds) {
14070        // We try only with the AttachInfo because there's no point in invalidating
14071        // if we are not attached to our window
14072        final AttachInfo attachInfo = mAttachInfo;
14073        if (attachInfo != null) {
14074            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
14075        }
14076    }
14077
14078    /**
14079     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14080     * through the event loop. Waits for the specified amount of time.</p>
14081     *
14082     * <p>This method can be invoked from outside of the UI thread
14083     * only when this View is attached to a window.</p>
14084     *
14085     * @param delayMilliseconds the duration in milliseconds to delay the
14086     *         invalidation by
14087     * @param left The left coordinate of the rectangle to invalidate.
14088     * @param top The top coordinate of the rectangle to invalidate.
14089     * @param right The right coordinate of the rectangle to invalidate.
14090     * @param bottom The bottom coordinate of the rectangle to invalidate.
14091     *
14092     * @see #invalidate(int, int, int, int)
14093     * @see #invalidate(Rect)
14094     * @see #postInvalidate(int, int, int, int)
14095     */
14096    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
14097            int right, int bottom) {
14098
14099        // We try only with the AttachInfo because there's no point in invalidating
14100        // if we are not attached to our window
14101        final AttachInfo attachInfo = mAttachInfo;
14102        if (attachInfo != null) {
14103            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14104            info.target = this;
14105            info.left = left;
14106            info.top = top;
14107            info.right = right;
14108            info.bottom = bottom;
14109
14110            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
14111        }
14112    }
14113
14114    /**
14115     * <p>Cause an invalidate to happen on the next animation time step, typically the
14116     * next display frame.</p>
14117     *
14118     * <p>This method can be invoked from outside of the UI thread
14119     * only when this View is attached to a window.</p>
14120     *
14121     * @see #invalidate()
14122     */
14123    public void postInvalidateOnAnimation() {
14124        // We try only with the AttachInfo because there's no point in invalidating
14125        // if we are not attached to our window
14126        final AttachInfo attachInfo = mAttachInfo;
14127        if (attachInfo != null) {
14128            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
14129        }
14130    }
14131
14132    /**
14133     * <p>Cause an invalidate of the specified area to happen on the next animation
14134     * time step, typically the next display frame.</p>
14135     *
14136     * <p>This method can be invoked from outside of the UI thread
14137     * only when this View is attached to a window.</p>
14138     *
14139     * @param left The left coordinate of the rectangle to invalidate.
14140     * @param top The top coordinate of the rectangle to invalidate.
14141     * @param right The right coordinate of the rectangle to invalidate.
14142     * @param bottom The bottom coordinate of the rectangle to invalidate.
14143     *
14144     * @see #invalidate(int, int, int, int)
14145     * @see #invalidate(Rect)
14146     */
14147    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
14148        // We try only with the AttachInfo because there's no point in invalidating
14149        // if we are not attached to our window
14150        final AttachInfo attachInfo = mAttachInfo;
14151        if (attachInfo != null) {
14152            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14153            info.target = this;
14154            info.left = left;
14155            info.top = top;
14156            info.right = right;
14157            info.bottom = bottom;
14158
14159            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
14160        }
14161    }
14162
14163    /**
14164     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
14165     * This event is sent at most once every
14166     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
14167     */
14168    private void postSendViewScrolledAccessibilityEventCallback() {
14169        if (mSendViewScrolledAccessibilityEvent == null) {
14170            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
14171        }
14172        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
14173            mSendViewScrolledAccessibilityEvent.mIsPending = true;
14174            postDelayed(mSendViewScrolledAccessibilityEvent,
14175                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
14176        }
14177    }
14178
14179    /**
14180     * Called by a parent to request that a child update its values for mScrollX
14181     * and mScrollY if necessary. This will typically be done if the child is
14182     * animating a scroll using a {@link android.widget.Scroller Scroller}
14183     * object.
14184     */
14185    public void computeScroll() {
14186    }
14187
14188    /**
14189     * <p>Indicate whether the horizontal edges are faded when the view is
14190     * scrolled horizontally.</p>
14191     *
14192     * @return true if the horizontal edges should are faded on scroll, false
14193     *         otherwise
14194     *
14195     * @see #setHorizontalFadingEdgeEnabled(boolean)
14196     *
14197     * @attr ref android.R.styleable#View_requiresFadingEdge
14198     */
14199    public boolean isHorizontalFadingEdgeEnabled() {
14200        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
14201    }
14202
14203    /**
14204     * <p>Define whether the horizontal edges should be faded when this view
14205     * is scrolled horizontally.</p>
14206     *
14207     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
14208     *                                    be faded when the view is scrolled
14209     *                                    horizontally
14210     *
14211     * @see #isHorizontalFadingEdgeEnabled()
14212     *
14213     * @attr ref android.R.styleable#View_requiresFadingEdge
14214     */
14215    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
14216        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
14217            if (horizontalFadingEdgeEnabled) {
14218                initScrollCache();
14219            }
14220
14221            mViewFlags ^= FADING_EDGE_HORIZONTAL;
14222        }
14223    }
14224
14225    /**
14226     * <p>Indicate whether the vertical edges are faded when the view is
14227     * scrolled horizontally.</p>
14228     *
14229     * @return true if the vertical edges should are faded on scroll, false
14230     *         otherwise
14231     *
14232     * @see #setVerticalFadingEdgeEnabled(boolean)
14233     *
14234     * @attr ref android.R.styleable#View_requiresFadingEdge
14235     */
14236    public boolean isVerticalFadingEdgeEnabled() {
14237        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
14238    }
14239
14240    /**
14241     * <p>Define whether the vertical edges should be faded when this view
14242     * is scrolled vertically.</p>
14243     *
14244     * @param verticalFadingEdgeEnabled true if the vertical edges should
14245     *                                  be faded when the view is scrolled
14246     *                                  vertically
14247     *
14248     * @see #isVerticalFadingEdgeEnabled()
14249     *
14250     * @attr ref android.R.styleable#View_requiresFadingEdge
14251     */
14252    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
14253        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
14254            if (verticalFadingEdgeEnabled) {
14255                initScrollCache();
14256            }
14257
14258            mViewFlags ^= FADING_EDGE_VERTICAL;
14259        }
14260    }
14261
14262    /**
14263     * Returns the strength, or intensity, of the top faded edge. The strength is
14264     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14265     * returns 0.0 or 1.0 but no value in between.
14266     *
14267     * Subclasses should override this method to provide a smoother fade transition
14268     * when scrolling occurs.
14269     *
14270     * @return the intensity of the top fade as a float between 0.0f and 1.0f
14271     */
14272    protected float getTopFadingEdgeStrength() {
14273        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
14274    }
14275
14276    /**
14277     * Returns the strength, or intensity, of the bottom faded edge. The strength is
14278     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14279     * returns 0.0 or 1.0 but no value in between.
14280     *
14281     * Subclasses should override this method to provide a smoother fade transition
14282     * when scrolling occurs.
14283     *
14284     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
14285     */
14286    protected float getBottomFadingEdgeStrength() {
14287        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
14288                computeVerticalScrollRange() ? 1.0f : 0.0f;
14289    }
14290
14291    /**
14292     * Returns the strength, or intensity, of the left faded edge. The strength is
14293     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14294     * returns 0.0 or 1.0 but no value in between.
14295     *
14296     * Subclasses should override this method to provide a smoother fade transition
14297     * when scrolling occurs.
14298     *
14299     * @return the intensity of the left fade as a float between 0.0f and 1.0f
14300     */
14301    protected float getLeftFadingEdgeStrength() {
14302        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
14303    }
14304
14305    /**
14306     * Returns the strength, or intensity, of the right faded edge. The strength is
14307     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14308     * returns 0.0 or 1.0 but no value in between.
14309     *
14310     * Subclasses should override this method to provide a smoother fade transition
14311     * when scrolling occurs.
14312     *
14313     * @return the intensity of the right fade as a float between 0.0f and 1.0f
14314     */
14315    protected float getRightFadingEdgeStrength() {
14316        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
14317                computeHorizontalScrollRange() ? 1.0f : 0.0f;
14318    }
14319
14320    /**
14321     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
14322     * scrollbar is not drawn by default.</p>
14323     *
14324     * @return true if the horizontal scrollbar should be painted, false
14325     *         otherwise
14326     *
14327     * @see #setHorizontalScrollBarEnabled(boolean)
14328     */
14329    public boolean isHorizontalScrollBarEnabled() {
14330        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14331    }
14332
14333    /**
14334     * <p>Define whether the horizontal scrollbar should be drawn or not. The
14335     * scrollbar is not drawn by default.</p>
14336     *
14337     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
14338     *                                   be painted
14339     *
14340     * @see #isHorizontalScrollBarEnabled()
14341     */
14342    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
14343        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
14344            mViewFlags ^= SCROLLBARS_HORIZONTAL;
14345            computeOpaqueFlags();
14346            resolvePadding();
14347        }
14348    }
14349
14350    /**
14351     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
14352     * scrollbar is not drawn by default.</p>
14353     *
14354     * @return true if the vertical scrollbar should be painted, false
14355     *         otherwise
14356     *
14357     * @see #setVerticalScrollBarEnabled(boolean)
14358     */
14359    public boolean isVerticalScrollBarEnabled() {
14360        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
14361    }
14362
14363    /**
14364     * <p>Define whether the vertical scrollbar should be drawn or not. The
14365     * scrollbar is not drawn by default.</p>
14366     *
14367     * @param verticalScrollBarEnabled true if the vertical scrollbar should
14368     *                                 be painted
14369     *
14370     * @see #isVerticalScrollBarEnabled()
14371     */
14372    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
14373        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
14374            mViewFlags ^= SCROLLBARS_VERTICAL;
14375            computeOpaqueFlags();
14376            resolvePadding();
14377        }
14378    }
14379
14380    /**
14381     * @hide
14382     */
14383    protected void recomputePadding() {
14384        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14385    }
14386
14387    /**
14388     * Define whether scrollbars will fade when the view is not scrolling.
14389     *
14390     * @param fadeScrollbars whether to enable fading
14391     *
14392     * @attr ref android.R.styleable#View_fadeScrollbars
14393     */
14394    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
14395        initScrollCache();
14396        final ScrollabilityCache scrollabilityCache = mScrollCache;
14397        scrollabilityCache.fadeScrollBars = fadeScrollbars;
14398        if (fadeScrollbars) {
14399            scrollabilityCache.state = ScrollabilityCache.OFF;
14400        } else {
14401            scrollabilityCache.state = ScrollabilityCache.ON;
14402        }
14403    }
14404
14405    /**
14406     *
14407     * Returns true if scrollbars will fade when this view is not scrolling
14408     *
14409     * @return true if scrollbar fading is enabled
14410     *
14411     * @attr ref android.R.styleable#View_fadeScrollbars
14412     */
14413    public boolean isScrollbarFadingEnabled() {
14414        return mScrollCache != null && mScrollCache.fadeScrollBars;
14415    }
14416
14417    /**
14418     *
14419     * Returns the delay before scrollbars fade.
14420     *
14421     * @return the delay before scrollbars fade
14422     *
14423     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14424     */
14425    public int getScrollBarDefaultDelayBeforeFade() {
14426        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
14427                mScrollCache.scrollBarDefaultDelayBeforeFade;
14428    }
14429
14430    /**
14431     * Define the delay before scrollbars fade.
14432     *
14433     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
14434     *
14435     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14436     */
14437    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
14438        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
14439    }
14440
14441    /**
14442     *
14443     * Returns the scrollbar fade duration.
14444     *
14445     * @return the scrollbar fade duration
14446     *
14447     * @attr ref android.R.styleable#View_scrollbarFadeDuration
14448     */
14449    public int getScrollBarFadeDuration() {
14450        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
14451                mScrollCache.scrollBarFadeDuration;
14452    }
14453
14454    /**
14455     * Define the scrollbar fade duration.
14456     *
14457     * @param scrollBarFadeDuration - the scrollbar fade duration
14458     *
14459     * @attr ref android.R.styleable#View_scrollbarFadeDuration
14460     */
14461    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
14462        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
14463    }
14464
14465    /**
14466     *
14467     * Returns the scrollbar size.
14468     *
14469     * @return the scrollbar size
14470     *
14471     * @attr ref android.R.styleable#View_scrollbarSize
14472     */
14473    public int getScrollBarSize() {
14474        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
14475                mScrollCache.scrollBarSize;
14476    }
14477
14478    /**
14479     * Define the scrollbar size.
14480     *
14481     * @param scrollBarSize - the scrollbar size
14482     *
14483     * @attr ref android.R.styleable#View_scrollbarSize
14484     */
14485    public void setScrollBarSize(int scrollBarSize) {
14486        getScrollCache().scrollBarSize = scrollBarSize;
14487    }
14488
14489    /**
14490     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
14491     * inset. When inset, they add to the padding of the view. And the scrollbars
14492     * can be drawn inside the padding area or on the edge of the view. For example,
14493     * if a view has a background drawable and you want to draw the scrollbars
14494     * inside the padding specified by the drawable, you can use
14495     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
14496     * appear at the edge of the view, ignoring the padding, then you can use
14497     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
14498     * @param style the style of the scrollbars. Should be one of
14499     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
14500     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
14501     * @see #SCROLLBARS_INSIDE_OVERLAY
14502     * @see #SCROLLBARS_INSIDE_INSET
14503     * @see #SCROLLBARS_OUTSIDE_OVERLAY
14504     * @see #SCROLLBARS_OUTSIDE_INSET
14505     *
14506     * @attr ref android.R.styleable#View_scrollbarStyle
14507     */
14508    public void setScrollBarStyle(@ScrollBarStyle int style) {
14509        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
14510            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
14511            computeOpaqueFlags();
14512            resolvePadding();
14513        }
14514    }
14515
14516    /**
14517     * <p>Returns the current scrollbar style.</p>
14518     * @return the current scrollbar style
14519     * @see #SCROLLBARS_INSIDE_OVERLAY
14520     * @see #SCROLLBARS_INSIDE_INSET
14521     * @see #SCROLLBARS_OUTSIDE_OVERLAY
14522     * @see #SCROLLBARS_OUTSIDE_INSET
14523     *
14524     * @attr ref android.R.styleable#View_scrollbarStyle
14525     */
14526    @ViewDebug.ExportedProperty(mapping = {
14527            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
14528            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
14529            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
14530            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
14531    })
14532    @ScrollBarStyle
14533    public int getScrollBarStyle() {
14534        return mViewFlags & SCROLLBARS_STYLE_MASK;
14535    }
14536
14537    /**
14538     * <p>Compute the horizontal range that the horizontal scrollbar
14539     * represents.</p>
14540     *
14541     * <p>The range is expressed in arbitrary units that must be the same as the
14542     * units used by {@link #computeHorizontalScrollExtent()} and
14543     * {@link #computeHorizontalScrollOffset()}.</p>
14544     *
14545     * <p>The default range is the drawing width of this view.</p>
14546     *
14547     * @return the total horizontal range represented by the horizontal
14548     *         scrollbar
14549     *
14550     * @see #computeHorizontalScrollExtent()
14551     * @see #computeHorizontalScrollOffset()
14552     * @see android.widget.ScrollBarDrawable
14553     */
14554    protected int computeHorizontalScrollRange() {
14555        return getWidth();
14556    }
14557
14558    /**
14559     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
14560     * within the horizontal range. This value is used to compute the position
14561     * of the thumb within the scrollbar's track.</p>
14562     *
14563     * <p>The range is expressed in arbitrary units that must be the same as the
14564     * units used by {@link #computeHorizontalScrollRange()} and
14565     * {@link #computeHorizontalScrollExtent()}.</p>
14566     *
14567     * <p>The default offset is the scroll offset of this view.</p>
14568     *
14569     * @return the horizontal offset of the scrollbar's thumb
14570     *
14571     * @see #computeHorizontalScrollRange()
14572     * @see #computeHorizontalScrollExtent()
14573     * @see android.widget.ScrollBarDrawable
14574     */
14575    protected int computeHorizontalScrollOffset() {
14576        return mScrollX;
14577    }
14578
14579    /**
14580     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
14581     * within the horizontal range. This value is used to compute the length
14582     * of the thumb within the scrollbar's track.</p>
14583     *
14584     * <p>The range is expressed in arbitrary units that must be the same as the
14585     * units used by {@link #computeHorizontalScrollRange()} and
14586     * {@link #computeHorizontalScrollOffset()}.</p>
14587     *
14588     * <p>The default extent is the drawing width of this view.</p>
14589     *
14590     * @return the horizontal extent of the scrollbar's thumb
14591     *
14592     * @see #computeHorizontalScrollRange()
14593     * @see #computeHorizontalScrollOffset()
14594     * @see android.widget.ScrollBarDrawable
14595     */
14596    protected int computeHorizontalScrollExtent() {
14597        return getWidth();
14598    }
14599
14600    /**
14601     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
14602     *
14603     * <p>The range is expressed in arbitrary units that must be the same as the
14604     * units used by {@link #computeVerticalScrollExtent()} and
14605     * {@link #computeVerticalScrollOffset()}.</p>
14606     *
14607     * @return the total vertical range represented by the vertical scrollbar
14608     *
14609     * <p>The default range is the drawing height of this view.</p>
14610     *
14611     * @see #computeVerticalScrollExtent()
14612     * @see #computeVerticalScrollOffset()
14613     * @see android.widget.ScrollBarDrawable
14614     */
14615    protected int computeVerticalScrollRange() {
14616        return getHeight();
14617    }
14618
14619    /**
14620     * <p>Compute the vertical offset of the vertical scrollbar's thumb
14621     * within the horizontal range. This value is used to compute the position
14622     * of the thumb within the scrollbar's track.</p>
14623     *
14624     * <p>The range is expressed in arbitrary units that must be the same as the
14625     * units used by {@link #computeVerticalScrollRange()} and
14626     * {@link #computeVerticalScrollExtent()}.</p>
14627     *
14628     * <p>The default offset is the scroll offset of this view.</p>
14629     *
14630     * @return the vertical offset of the scrollbar's thumb
14631     *
14632     * @see #computeVerticalScrollRange()
14633     * @see #computeVerticalScrollExtent()
14634     * @see android.widget.ScrollBarDrawable
14635     */
14636    protected int computeVerticalScrollOffset() {
14637        return mScrollY;
14638    }
14639
14640    /**
14641     * <p>Compute the vertical extent of the vertical scrollbar's thumb
14642     * within the vertical range. This value is used to compute the length
14643     * of the thumb within the scrollbar's track.</p>
14644     *
14645     * <p>The range is expressed in arbitrary units that must be the same as the
14646     * units used by {@link #computeVerticalScrollRange()} and
14647     * {@link #computeVerticalScrollOffset()}.</p>
14648     *
14649     * <p>The default extent is the drawing height of this view.</p>
14650     *
14651     * @return the vertical extent of the scrollbar's thumb
14652     *
14653     * @see #computeVerticalScrollRange()
14654     * @see #computeVerticalScrollOffset()
14655     * @see android.widget.ScrollBarDrawable
14656     */
14657    protected int computeVerticalScrollExtent() {
14658        return getHeight();
14659    }
14660
14661    /**
14662     * Check if this view can be scrolled horizontally in a certain direction.
14663     *
14664     * @param direction Negative to check scrolling left, positive to check scrolling right.
14665     * @return true if this view can be scrolled in the specified direction, false otherwise.
14666     */
14667    public boolean canScrollHorizontally(int direction) {
14668        final int offset = computeHorizontalScrollOffset();
14669        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
14670        if (range == 0) return false;
14671        if (direction < 0) {
14672            return offset > 0;
14673        } else {
14674            return offset < range - 1;
14675        }
14676    }
14677
14678    /**
14679     * Check if this view can be scrolled vertically in a certain direction.
14680     *
14681     * @param direction Negative to check scrolling up, positive to check scrolling down.
14682     * @return true if this view can be scrolled in the specified direction, false otherwise.
14683     */
14684    public boolean canScrollVertically(int direction) {
14685        final int offset = computeVerticalScrollOffset();
14686        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
14687        if (range == 0) return false;
14688        if (direction < 0) {
14689            return offset > 0;
14690        } else {
14691            return offset < range - 1;
14692        }
14693    }
14694
14695    void getScrollIndicatorBounds(@NonNull Rect out) {
14696        out.left = mScrollX;
14697        out.right = mScrollX + mRight - mLeft;
14698        out.top = mScrollY;
14699        out.bottom = mScrollY + mBottom - mTop;
14700    }
14701
14702    private void onDrawScrollIndicators(Canvas c) {
14703        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
14704            // No scroll indicators enabled.
14705            return;
14706        }
14707
14708        final Drawable dr = mScrollIndicatorDrawable;
14709        if (dr == null) {
14710            // Scroll indicators aren't supported here.
14711            return;
14712        }
14713
14714        final int h = dr.getIntrinsicHeight();
14715        final int w = dr.getIntrinsicWidth();
14716        final Rect rect = mAttachInfo.mTmpInvalRect;
14717        getScrollIndicatorBounds(rect);
14718
14719        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
14720            final boolean canScrollUp = canScrollVertically(-1);
14721            if (canScrollUp) {
14722                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
14723                dr.draw(c);
14724            }
14725        }
14726
14727        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
14728            final boolean canScrollDown = canScrollVertically(1);
14729            if (canScrollDown) {
14730                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
14731                dr.draw(c);
14732            }
14733        }
14734
14735        final int leftRtl;
14736        final int rightRtl;
14737        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14738            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
14739            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
14740        } else {
14741            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
14742            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
14743        }
14744
14745        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
14746        if ((mPrivateFlags3 & leftMask) != 0) {
14747            final boolean canScrollLeft = canScrollHorizontally(-1);
14748            if (canScrollLeft) {
14749                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
14750                dr.draw(c);
14751            }
14752        }
14753
14754        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
14755        if ((mPrivateFlags3 & rightMask) != 0) {
14756            final boolean canScrollRight = canScrollHorizontally(1);
14757            if (canScrollRight) {
14758                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
14759                dr.draw(c);
14760            }
14761        }
14762    }
14763
14764    private void getHorizontalScrollBarBounds(Rect bounds) {
14765        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14766        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14767                && !isVerticalScrollBarHidden();
14768        final int size = getHorizontalScrollbarHeight();
14769        final int verticalScrollBarGap = drawVerticalScrollBar ?
14770                getVerticalScrollbarWidth() : 0;
14771        final int width = mRight - mLeft;
14772        final int height = mBottom - mTop;
14773        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
14774        bounds.left = mScrollX + (mPaddingLeft & inside);
14775        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14776        bounds.bottom = bounds.top + size;
14777    }
14778
14779    private void getVerticalScrollBarBounds(Rect bounds) {
14780        if (mRoundScrollbarRenderer == null) {
14781            getStraightVerticalScrollBarBounds(bounds);
14782        } else {
14783            getRoundVerticalScrollBarBounds(bounds);
14784        }
14785    }
14786
14787    private void getRoundVerticalScrollBarBounds(Rect bounds) {
14788        final int width = mRight - mLeft;
14789        final int height = mBottom - mTop;
14790        // Do not take padding into account as we always want the scrollbars
14791        // to hug the screen for round wearable devices.
14792        bounds.left = mScrollX;
14793        bounds.top = mScrollY;
14794        bounds.right = bounds.left + width;
14795        bounds.bottom = mScrollY + height;
14796    }
14797
14798    private void getStraightVerticalScrollBarBounds(Rect bounds) {
14799        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14800        final int size = getVerticalScrollbarWidth();
14801        int verticalScrollbarPosition = mVerticalScrollbarPosition;
14802        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14803            verticalScrollbarPosition = isLayoutRtl() ?
14804                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14805        }
14806        final int width = mRight - mLeft;
14807        final int height = mBottom - mTop;
14808        switch (verticalScrollbarPosition) {
14809            default:
14810            case SCROLLBAR_POSITION_RIGHT:
14811                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
14812                break;
14813            case SCROLLBAR_POSITION_LEFT:
14814                bounds.left = mScrollX + (mUserPaddingLeft & inside);
14815                break;
14816        }
14817        bounds.top = mScrollY + (mPaddingTop & inside);
14818        bounds.right = bounds.left + size;
14819        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
14820    }
14821
14822    /**
14823     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
14824     * scrollbars are painted only if they have been awakened first.</p>
14825     *
14826     * @param canvas the canvas on which to draw the scrollbars
14827     *
14828     * @see #awakenScrollBars(int)
14829     */
14830    protected final void onDrawScrollBars(Canvas canvas) {
14831        // scrollbars are drawn only when the animation is running
14832        final ScrollabilityCache cache = mScrollCache;
14833
14834        if (cache != null) {
14835
14836            int state = cache.state;
14837
14838            if (state == ScrollabilityCache.OFF) {
14839                return;
14840            }
14841
14842            boolean invalidate = false;
14843
14844            if (state == ScrollabilityCache.FADING) {
14845                // We're fading -- get our fade interpolation
14846                if (cache.interpolatorValues == null) {
14847                    cache.interpolatorValues = new float[1];
14848                }
14849
14850                float[] values = cache.interpolatorValues;
14851
14852                // Stops the animation if we're done
14853                if (cache.scrollBarInterpolator.timeToValues(values) ==
14854                        Interpolator.Result.FREEZE_END) {
14855                    cache.state = ScrollabilityCache.OFF;
14856                } else {
14857                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14858                }
14859
14860                // This will make the scroll bars inval themselves after
14861                // drawing. We only want this when we're fading so that
14862                // we prevent excessive redraws
14863                invalidate = true;
14864            } else {
14865                // We're just on -- but we may have been fading before so
14866                // reset alpha
14867                cache.scrollBar.mutate().setAlpha(255);
14868            }
14869
14870            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
14871            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14872                    && !isVerticalScrollBarHidden();
14873
14874            // Fork out the scroll bar drawing for round wearable devices.
14875            if (mRoundScrollbarRenderer != null) {
14876                if (drawVerticalScrollBar) {
14877                    final Rect bounds = cache.mScrollBarBounds;
14878                    getVerticalScrollBarBounds(bounds);
14879                    mRoundScrollbarRenderer.drawRoundScrollbars(
14880                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
14881                    if (invalidate) {
14882                        invalidate();
14883                    }
14884                }
14885                // Do not draw horizontal scroll bars for round wearable devices.
14886            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14887                final ScrollBarDrawable scrollBar = cache.scrollBar;
14888
14889                if (drawHorizontalScrollBar) {
14890                    scrollBar.setParameters(computeHorizontalScrollRange(),
14891                            computeHorizontalScrollOffset(),
14892                            computeHorizontalScrollExtent(), false);
14893                    final Rect bounds = cache.mScrollBarBounds;
14894                    getHorizontalScrollBarBounds(bounds);
14895                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14896                            bounds.right, bounds.bottom);
14897                    if (invalidate) {
14898                        invalidate(bounds);
14899                    }
14900                }
14901
14902                if (drawVerticalScrollBar) {
14903                    scrollBar.setParameters(computeVerticalScrollRange(),
14904                            computeVerticalScrollOffset(),
14905                            computeVerticalScrollExtent(), true);
14906                    final Rect bounds = cache.mScrollBarBounds;
14907                    getVerticalScrollBarBounds(bounds);
14908                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14909                            bounds.right, bounds.bottom);
14910                    if (invalidate) {
14911                        invalidate(bounds);
14912                    }
14913                }
14914            }
14915        }
14916    }
14917
14918    /**
14919     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14920     * FastScroller is visible.
14921     * @return whether to temporarily hide the vertical scrollbar
14922     * @hide
14923     */
14924    protected boolean isVerticalScrollBarHidden() {
14925        return false;
14926    }
14927
14928    /**
14929     * <p>Draw the horizontal scrollbar if
14930     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14931     *
14932     * @param canvas the canvas on which to draw the scrollbar
14933     * @param scrollBar the scrollbar's drawable
14934     *
14935     * @see #isHorizontalScrollBarEnabled()
14936     * @see #computeHorizontalScrollRange()
14937     * @see #computeHorizontalScrollExtent()
14938     * @see #computeHorizontalScrollOffset()
14939     * @see android.widget.ScrollBarDrawable
14940     * @hide
14941     */
14942    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14943            int l, int t, int r, int b) {
14944        scrollBar.setBounds(l, t, r, b);
14945        scrollBar.draw(canvas);
14946    }
14947
14948    /**
14949     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14950     * returns true.</p>
14951     *
14952     * @param canvas the canvas on which to draw the scrollbar
14953     * @param scrollBar the scrollbar's drawable
14954     *
14955     * @see #isVerticalScrollBarEnabled()
14956     * @see #computeVerticalScrollRange()
14957     * @see #computeVerticalScrollExtent()
14958     * @see #computeVerticalScrollOffset()
14959     * @see android.widget.ScrollBarDrawable
14960     * @hide
14961     */
14962    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14963            int l, int t, int r, int b) {
14964        scrollBar.setBounds(l, t, r, b);
14965        scrollBar.draw(canvas);
14966    }
14967
14968    /**
14969     * Implement this to do your drawing.
14970     *
14971     * @param canvas the canvas on which the background will be drawn
14972     */
14973    protected void onDraw(Canvas canvas) {
14974    }
14975
14976    /*
14977     * Caller is responsible for calling requestLayout if necessary.
14978     * (This allows addViewInLayout to not request a new layout.)
14979     */
14980    void assignParent(ViewParent parent) {
14981        if (mParent == null) {
14982            mParent = parent;
14983        } else if (parent == null) {
14984            mParent = null;
14985        } else {
14986            throw new RuntimeException("view " + this + " being added, but"
14987                    + " it already has a parent");
14988        }
14989    }
14990
14991    /**
14992     * This is called when the view is attached to a window.  At this point it
14993     * has a Surface and will start drawing.  Note that this function is
14994     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14995     * however it may be called any time before the first onDraw -- including
14996     * before or after {@link #onMeasure(int, int)}.
14997     *
14998     * @see #onDetachedFromWindow()
14999     */
15000    @CallSuper
15001    protected void onAttachedToWindow() {
15002        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
15003            mParent.requestTransparentRegion(this);
15004        }
15005
15006        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15007
15008        jumpDrawablesToCurrentState();
15009
15010        resetSubtreeAccessibilityStateChanged();
15011
15012        // rebuild, since Outline not maintained while View is detached
15013        rebuildOutline();
15014
15015        if (isFocused()) {
15016            InputMethodManager imm = InputMethodManager.peekInstance();
15017            if (imm != null) {
15018                imm.focusIn(this);
15019            }
15020        }
15021    }
15022
15023    /**
15024     * Resolve all RTL related properties.
15025     *
15026     * @return true if resolution of RTL properties has been done
15027     *
15028     * @hide
15029     */
15030    public boolean resolveRtlPropertiesIfNeeded() {
15031        if (!needRtlPropertiesResolution()) return false;
15032
15033        // Order is important here: LayoutDirection MUST be resolved first
15034        if (!isLayoutDirectionResolved()) {
15035            resolveLayoutDirection();
15036            resolveLayoutParams();
15037        }
15038        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
15039        if (!isTextDirectionResolved()) {
15040            resolveTextDirection();
15041        }
15042        if (!isTextAlignmentResolved()) {
15043            resolveTextAlignment();
15044        }
15045        // Should resolve Drawables before Padding because we need the layout direction of the
15046        // Drawable to correctly resolve Padding.
15047        if (!areDrawablesResolved()) {
15048            resolveDrawables();
15049        }
15050        if (!isPaddingResolved()) {
15051            resolvePadding();
15052        }
15053        onRtlPropertiesChanged(getLayoutDirection());
15054        return true;
15055    }
15056
15057    /**
15058     * Reset resolution of all RTL related properties.
15059     *
15060     * @hide
15061     */
15062    public void resetRtlProperties() {
15063        resetResolvedLayoutDirection();
15064        resetResolvedTextDirection();
15065        resetResolvedTextAlignment();
15066        resetResolvedPadding();
15067        resetResolvedDrawables();
15068    }
15069
15070    /**
15071     * @see #onScreenStateChanged(int)
15072     */
15073    void dispatchScreenStateChanged(int screenState) {
15074        onScreenStateChanged(screenState);
15075    }
15076
15077    /**
15078     * This method is called whenever the state of the screen this view is
15079     * attached to changes. A state change will usually occurs when the screen
15080     * turns on or off (whether it happens automatically or the user does it
15081     * manually.)
15082     *
15083     * @param screenState The new state of the screen. Can be either
15084     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
15085     */
15086    public void onScreenStateChanged(int screenState) {
15087    }
15088
15089    /**
15090     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
15091     */
15092    private boolean hasRtlSupport() {
15093        return mContext.getApplicationInfo().hasRtlSupport();
15094    }
15095
15096    /**
15097     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
15098     * RTL not supported)
15099     */
15100    private boolean isRtlCompatibilityMode() {
15101        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
15102        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
15103    }
15104
15105    /**
15106     * @return true if RTL properties need resolution.
15107     *
15108     */
15109    private boolean needRtlPropertiesResolution() {
15110        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
15111    }
15112
15113    /**
15114     * Called when any RTL property (layout direction or text direction or text alignment) has
15115     * been changed.
15116     *
15117     * Subclasses need to override this method to take care of cached information that depends on the
15118     * resolved layout direction, or to inform child views that inherit their layout direction.
15119     *
15120     * The default implementation does nothing.
15121     *
15122     * @param layoutDirection the direction of the layout
15123     *
15124     * @see #LAYOUT_DIRECTION_LTR
15125     * @see #LAYOUT_DIRECTION_RTL
15126     */
15127    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
15128    }
15129
15130    /**
15131     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
15132     * that the parent directionality can and will be resolved before its children.
15133     *
15134     * @return true if resolution has been done, false otherwise.
15135     *
15136     * @hide
15137     */
15138    public boolean resolveLayoutDirection() {
15139        // Clear any previous layout direction resolution
15140        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15141
15142        if (hasRtlSupport()) {
15143            // Set resolved depending on layout direction
15144            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
15145                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
15146                case LAYOUT_DIRECTION_INHERIT:
15147                    // We cannot resolve yet. LTR is by default and let the resolution happen again
15148                    // later to get the correct resolved value
15149                    if (!canResolveLayoutDirection()) return false;
15150
15151                    // Parent has not yet resolved, LTR is still the default
15152                    try {
15153                        if (!mParent.isLayoutDirectionResolved()) return false;
15154
15155                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15156                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15157                        }
15158                    } catch (AbstractMethodError e) {
15159                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15160                                " does not fully implement ViewParent", e);
15161                    }
15162                    break;
15163                case LAYOUT_DIRECTION_RTL:
15164                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15165                    break;
15166                case LAYOUT_DIRECTION_LOCALE:
15167                    if((LAYOUT_DIRECTION_RTL ==
15168                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
15169                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15170                    }
15171                    break;
15172                default:
15173                    // Nothing to do, LTR by default
15174            }
15175        }
15176
15177        // Set to resolved
15178        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15179        return true;
15180    }
15181
15182    /**
15183     * Check if layout direction resolution can be done.
15184     *
15185     * @return true if layout direction resolution can be done otherwise return false.
15186     */
15187    public boolean canResolveLayoutDirection() {
15188        switch (getRawLayoutDirection()) {
15189            case LAYOUT_DIRECTION_INHERIT:
15190                if (mParent != null) {
15191                    try {
15192                        return mParent.canResolveLayoutDirection();
15193                    } catch (AbstractMethodError e) {
15194                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15195                                " does not fully implement ViewParent", e);
15196                    }
15197                }
15198                return false;
15199
15200            default:
15201                return true;
15202        }
15203    }
15204
15205    /**
15206     * Reset the resolved layout direction. Layout direction will be resolved during a call to
15207     * {@link #onMeasure(int, int)}.
15208     *
15209     * @hide
15210     */
15211    public void resetResolvedLayoutDirection() {
15212        // Reset the current resolved bits
15213        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15214    }
15215
15216    /**
15217     * @return true if the layout direction is inherited.
15218     *
15219     * @hide
15220     */
15221    public boolean isLayoutDirectionInherited() {
15222        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
15223    }
15224
15225    /**
15226     * @return true if layout direction has been resolved.
15227     */
15228    public boolean isLayoutDirectionResolved() {
15229        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15230    }
15231
15232    /**
15233     * Return if padding has been resolved
15234     *
15235     * @hide
15236     */
15237    boolean isPaddingResolved() {
15238        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
15239    }
15240
15241    /**
15242     * Resolves padding depending on layout direction, if applicable, and
15243     * recomputes internal padding values to adjust for scroll bars.
15244     *
15245     * @hide
15246     */
15247    public void resolvePadding() {
15248        final int resolvedLayoutDirection = getLayoutDirection();
15249
15250        if (!isRtlCompatibilityMode()) {
15251            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
15252            // If start / end padding are defined, they will be resolved (hence overriding) to
15253            // left / right or right / left depending on the resolved layout direction.
15254            // If start / end padding are not defined, use the left / right ones.
15255            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
15256                Rect padding = sThreadLocal.get();
15257                if (padding == null) {
15258                    padding = new Rect();
15259                    sThreadLocal.set(padding);
15260                }
15261                mBackground.getPadding(padding);
15262                if (!mLeftPaddingDefined) {
15263                    mUserPaddingLeftInitial = padding.left;
15264                }
15265                if (!mRightPaddingDefined) {
15266                    mUserPaddingRightInitial = padding.right;
15267                }
15268            }
15269            switch (resolvedLayoutDirection) {
15270                case LAYOUT_DIRECTION_RTL:
15271                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15272                        mUserPaddingRight = mUserPaddingStart;
15273                    } else {
15274                        mUserPaddingRight = mUserPaddingRightInitial;
15275                    }
15276                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15277                        mUserPaddingLeft = mUserPaddingEnd;
15278                    } else {
15279                        mUserPaddingLeft = mUserPaddingLeftInitial;
15280                    }
15281                    break;
15282                case LAYOUT_DIRECTION_LTR:
15283                default:
15284                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15285                        mUserPaddingLeft = mUserPaddingStart;
15286                    } else {
15287                        mUserPaddingLeft = mUserPaddingLeftInitial;
15288                    }
15289                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15290                        mUserPaddingRight = mUserPaddingEnd;
15291                    } else {
15292                        mUserPaddingRight = mUserPaddingRightInitial;
15293                    }
15294            }
15295
15296            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
15297        }
15298
15299        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15300        onRtlPropertiesChanged(resolvedLayoutDirection);
15301
15302        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
15303    }
15304
15305    /**
15306     * Reset the resolved layout direction.
15307     *
15308     * @hide
15309     */
15310    public void resetResolvedPadding() {
15311        resetResolvedPaddingInternal();
15312    }
15313
15314    /**
15315     * Used when we only want to reset *this* view's padding and not trigger overrides
15316     * in ViewGroup that reset children too.
15317     */
15318    void resetResolvedPaddingInternal() {
15319        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
15320    }
15321
15322    /**
15323     * This is called when the view is detached from a window.  At this point it
15324     * no longer has a surface for drawing.
15325     *
15326     * @see #onAttachedToWindow()
15327     */
15328    @CallSuper
15329    protected void onDetachedFromWindow() {
15330    }
15331
15332    /**
15333     * This is a framework-internal mirror of onDetachedFromWindow() that's called
15334     * after onDetachedFromWindow().
15335     *
15336     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
15337     * The super method should be called at the end of the overridden method to ensure
15338     * subclasses are destroyed first
15339     *
15340     * @hide
15341     */
15342    @CallSuper
15343    protected void onDetachedFromWindowInternal() {
15344        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
15345        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15346        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
15347
15348        removeUnsetPressCallback();
15349        removeLongPressCallback();
15350        removePerformClickCallback();
15351        removeSendViewScrolledAccessibilityEventCallback();
15352        stopNestedScroll();
15353
15354        // Anything that started animating right before detach should already
15355        // be in its final state when re-attached.
15356        jumpDrawablesToCurrentState();
15357
15358        destroyDrawingCache();
15359
15360        cleanupDraw();
15361        mCurrentAnimation = null;
15362    }
15363
15364    private void cleanupDraw() {
15365        resetDisplayList();
15366        if (mAttachInfo != null) {
15367            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
15368        }
15369    }
15370
15371    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
15372    }
15373
15374    /**
15375     * @return The number of times this view has been attached to a window
15376     */
15377    protected int getWindowAttachCount() {
15378        return mWindowAttachCount;
15379    }
15380
15381    /**
15382     * Retrieve a unique token identifying the window this view is attached to.
15383     * @return Return the window's token for use in
15384     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
15385     */
15386    public IBinder getWindowToken() {
15387        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
15388    }
15389
15390    /**
15391     * Retrieve the {@link WindowId} for the window this view is
15392     * currently attached to.
15393     */
15394    public WindowId getWindowId() {
15395        if (mAttachInfo == null) {
15396            return null;
15397        }
15398        if (mAttachInfo.mWindowId == null) {
15399            try {
15400                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
15401                        mAttachInfo.mWindowToken);
15402                mAttachInfo.mWindowId = new WindowId(
15403                        mAttachInfo.mIWindowId);
15404            } catch (RemoteException e) {
15405            }
15406        }
15407        return mAttachInfo.mWindowId;
15408    }
15409
15410    /**
15411     * Retrieve a unique token identifying the top-level "real" window of
15412     * the window that this view is attached to.  That is, this is like
15413     * {@link #getWindowToken}, except if the window this view in is a panel
15414     * window (attached to another containing window), then the token of
15415     * the containing window is returned instead.
15416     *
15417     * @return Returns the associated window token, either
15418     * {@link #getWindowToken()} or the containing window's token.
15419     */
15420    public IBinder getApplicationWindowToken() {
15421        AttachInfo ai = mAttachInfo;
15422        if (ai != null) {
15423            IBinder appWindowToken = ai.mPanelParentWindowToken;
15424            if (appWindowToken == null) {
15425                appWindowToken = ai.mWindowToken;
15426            }
15427            return appWindowToken;
15428        }
15429        return null;
15430    }
15431
15432    /**
15433     * Gets the logical display to which the view's window has been attached.
15434     *
15435     * @return The logical display, or null if the view is not currently attached to a window.
15436     */
15437    public Display getDisplay() {
15438        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
15439    }
15440
15441    /**
15442     * Retrieve private session object this view hierarchy is using to
15443     * communicate with the window manager.
15444     * @return the session object to communicate with the window manager
15445     */
15446    /*package*/ IWindowSession getWindowSession() {
15447        return mAttachInfo != null ? mAttachInfo.mSession : null;
15448    }
15449
15450    /**
15451     * Return the visibility value of the least visible component passed.
15452     */
15453    int combineVisibility(int vis1, int vis2) {
15454        // This works because VISIBLE < INVISIBLE < GONE.
15455        return Math.max(vis1, vis2);
15456    }
15457
15458    /**
15459     * @param info the {@link android.view.View.AttachInfo} to associated with
15460     *        this view
15461     */
15462    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
15463        mAttachInfo = info;
15464        if (mOverlay != null) {
15465            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
15466        }
15467        mWindowAttachCount++;
15468        // We will need to evaluate the drawable state at least once.
15469        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15470        if (mFloatingTreeObserver != null) {
15471            info.mTreeObserver.merge(mFloatingTreeObserver);
15472            mFloatingTreeObserver = null;
15473        }
15474
15475        registerPendingFrameMetricsObservers();
15476
15477        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
15478            mAttachInfo.mScrollContainers.add(this);
15479            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
15480        }
15481        // Transfer all pending runnables.
15482        if (mRunQueue != null) {
15483            mRunQueue.executeActions(info.mHandler);
15484            mRunQueue = null;
15485        }
15486        performCollectViewAttributes(mAttachInfo, visibility);
15487        onAttachedToWindow();
15488
15489        ListenerInfo li = mListenerInfo;
15490        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15491                li != null ? li.mOnAttachStateChangeListeners : null;
15492        if (listeners != null && listeners.size() > 0) {
15493            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15494            // perform the dispatching. The iterator is a safe guard against listeners that
15495            // could mutate the list by calling the various add/remove methods. This prevents
15496            // the array from being modified while we iterate it.
15497            for (OnAttachStateChangeListener listener : listeners) {
15498                listener.onViewAttachedToWindow(this);
15499            }
15500        }
15501
15502        int vis = info.mWindowVisibility;
15503        if (vis != GONE) {
15504            onWindowVisibilityChanged(vis);
15505            if (isShown()) {
15506                // Calling onVisibilityChanged directly here since the subtree will also
15507                // receive dispatchAttachedToWindow and this same call
15508                onVisibilityAggregated(vis == VISIBLE);
15509            }
15510        }
15511
15512        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
15513        // As all views in the subtree will already receive dispatchAttachedToWindow
15514        // traversing the subtree again here is not desired.
15515        onVisibilityChanged(this, visibility);
15516
15517        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
15518            // If nobody has evaluated the drawable state yet, then do it now.
15519            refreshDrawableState();
15520        }
15521        needGlobalAttributesUpdate(false);
15522    }
15523
15524    void dispatchDetachedFromWindow() {
15525        AttachInfo info = mAttachInfo;
15526        if (info != null) {
15527            int vis = info.mWindowVisibility;
15528            if (vis != GONE) {
15529                onWindowVisibilityChanged(GONE);
15530                if (isShown()) {
15531                    // Invoking onVisibilityAggregated directly here since the subtree
15532                    // will also receive detached from window
15533                    onVisibilityAggregated(false);
15534                }
15535            }
15536        }
15537
15538        onDetachedFromWindow();
15539        onDetachedFromWindowInternal();
15540
15541        InputMethodManager imm = InputMethodManager.peekInstance();
15542        if (imm != null) {
15543            imm.onViewDetachedFromWindow(this);
15544        }
15545
15546        ListenerInfo li = mListenerInfo;
15547        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15548                li != null ? li.mOnAttachStateChangeListeners : null;
15549        if (listeners != null && listeners.size() > 0) {
15550            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15551            // perform the dispatching. The iterator is a safe guard against listeners that
15552            // could mutate the list by calling the various add/remove methods. This prevents
15553            // the array from being modified while we iterate it.
15554            for (OnAttachStateChangeListener listener : listeners) {
15555                listener.onViewDetachedFromWindow(this);
15556            }
15557        }
15558
15559        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
15560            mAttachInfo.mScrollContainers.remove(this);
15561            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
15562        }
15563
15564        mAttachInfo = null;
15565        if (mOverlay != null) {
15566            mOverlay.getOverlayView().dispatchDetachedFromWindow();
15567        }
15568    }
15569
15570    /**
15571     * Cancel any deferred high-level input events that were previously posted to the event queue.
15572     *
15573     * <p>Many views post high-level events such as click handlers to the event queue
15574     * to run deferred in order to preserve a desired user experience - clearing visible
15575     * pressed states before executing, etc. This method will abort any events of this nature
15576     * that are currently in flight.</p>
15577     *
15578     * <p>Custom views that generate their own high-level deferred input events should override
15579     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
15580     *
15581     * <p>This will also cancel pending input events for any child views.</p>
15582     *
15583     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
15584     * This will not impact newer events posted after this call that may occur as a result of
15585     * lower-level input events still waiting in the queue. If you are trying to prevent
15586     * double-submitted  events for the duration of some sort of asynchronous transaction
15587     * you should also take other steps to protect against unexpected double inputs e.g. calling
15588     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
15589     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
15590     */
15591    public final void cancelPendingInputEvents() {
15592        dispatchCancelPendingInputEvents();
15593    }
15594
15595    /**
15596     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
15597     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
15598     */
15599    void dispatchCancelPendingInputEvents() {
15600        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
15601        onCancelPendingInputEvents();
15602        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
15603            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
15604                    " did not call through to super.onCancelPendingInputEvents()");
15605        }
15606    }
15607
15608    /**
15609     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
15610     * a parent view.
15611     *
15612     * <p>This method is responsible for removing any pending high-level input events that were
15613     * posted to the event queue to run later. Custom view classes that post their own deferred
15614     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
15615     * {@link android.os.Handler} should override this method, call
15616     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
15617     * </p>
15618     */
15619    public void onCancelPendingInputEvents() {
15620        removePerformClickCallback();
15621        cancelLongPress();
15622        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
15623    }
15624
15625    /**
15626     * Store this view hierarchy's frozen state into the given container.
15627     *
15628     * @param container The SparseArray in which to save the view's state.
15629     *
15630     * @see #restoreHierarchyState(android.util.SparseArray)
15631     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15632     * @see #onSaveInstanceState()
15633     */
15634    public void saveHierarchyState(SparseArray<Parcelable> container) {
15635        dispatchSaveInstanceState(container);
15636    }
15637
15638    /**
15639     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
15640     * this view and its children. May be overridden to modify how freezing happens to a
15641     * view's children; for example, some views may want to not store state for their children.
15642     *
15643     * @param container The SparseArray in which to save the view's state.
15644     *
15645     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15646     * @see #saveHierarchyState(android.util.SparseArray)
15647     * @see #onSaveInstanceState()
15648     */
15649    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
15650        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
15651            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15652            Parcelable state = onSaveInstanceState();
15653            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15654                throw new IllegalStateException(
15655                        "Derived class did not call super.onSaveInstanceState()");
15656            }
15657            if (state != null) {
15658                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
15659                // + ": " + state);
15660                container.put(mID, state);
15661            }
15662        }
15663    }
15664
15665    /**
15666     * Hook allowing a view to generate a representation of its internal state
15667     * that can later be used to create a new instance with that same state.
15668     * This state should only contain information that is not persistent or can
15669     * not be reconstructed later. For example, you will never store your
15670     * current position on screen because that will be computed again when a
15671     * new instance of the view is placed in its view hierarchy.
15672     * <p>
15673     * Some examples of things you may store here: the current cursor position
15674     * in a text view (but usually not the text itself since that is stored in a
15675     * content provider or other persistent storage), the currently selected
15676     * item in a list view.
15677     *
15678     * @return Returns a Parcelable object containing the view's current dynamic
15679     *         state, or null if there is nothing interesting to save. The
15680     *         default implementation returns null.
15681     * @see #onRestoreInstanceState(android.os.Parcelable)
15682     * @see #saveHierarchyState(android.util.SparseArray)
15683     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15684     * @see #setSaveEnabled(boolean)
15685     */
15686    @CallSuper
15687    protected Parcelable onSaveInstanceState() {
15688        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15689        if (mStartActivityRequestWho != null) {
15690            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
15691            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
15692            return state;
15693        }
15694        return BaseSavedState.EMPTY_STATE;
15695    }
15696
15697    /**
15698     * Restore this view hierarchy's frozen state from the given container.
15699     *
15700     * @param container The SparseArray which holds previously frozen states.
15701     *
15702     * @see #saveHierarchyState(android.util.SparseArray)
15703     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15704     * @see #onRestoreInstanceState(android.os.Parcelable)
15705     */
15706    public void restoreHierarchyState(SparseArray<Parcelable> container) {
15707        dispatchRestoreInstanceState(container);
15708    }
15709
15710    /**
15711     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
15712     * state for this view and its children. May be overridden to modify how restoring
15713     * happens to a view's children; for example, some views may want to not store state
15714     * for their children.
15715     *
15716     * @param container The SparseArray which holds previously saved state.
15717     *
15718     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15719     * @see #restoreHierarchyState(android.util.SparseArray)
15720     * @see #onRestoreInstanceState(android.os.Parcelable)
15721     */
15722    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
15723        if (mID != NO_ID) {
15724            Parcelable state = container.get(mID);
15725            if (state != null) {
15726                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
15727                // + ": " + state);
15728                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15729                onRestoreInstanceState(state);
15730                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15731                    throw new IllegalStateException(
15732                            "Derived class did not call super.onRestoreInstanceState()");
15733                }
15734            }
15735        }
15736    }
15737
15738    /**
15739     * Hook allowing a view to re-apply a representation of its internal state that had previously
15740     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
15741     * null state.
15742     *
15743     * @param state The frozen state that had previously been returned by
15744     *        {@link #onSaveInstanceState}.
15745     *
15746     * @see #onSaveInstanceState()
15747     * @see #restoreHierarchyState(android.util.SparseArray)
15748     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15749     */
15750    @CallSuper
15751    protected void onRestoreInstanceState(Parcelable state) {
15752        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15753        if (state != null && !(state instanceof AbsSavedState)) {
15754            throw new IllegalArgumentException("Wrong state class, expecting View State but "
15755                    + "received " + state.getClass().toString() + " instead. This usually happens "
15756                    + "when two views of different type have the same id in the same hierarchy. "
15757                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
15758                    + "other views do not use the same id.");
15759        }
15760        if (state != null && state instanceof BaseSavedState) {
15761            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
15762        }
15763    }
15764
15765    /**
15766     * <p>Return the time at which the drawing of the view hierarchy started.</p>
15767     *
15768     * @return the drawing start time in milliseconds
15769     */
15770    public long getDrawingTime() {
15771        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
15772    }
15773
15774    /**
15775     * <p>Enables or disables the duplication of the parent's state into this view. When
15776     * duplication is enabled, this view gets its drawable state from its parent rather
15777     * than from its own internal properties.</p>
15778     *
15779     * <p>Note: in the current implementation, setting this property to true after the
15780     * view was added to a ViewGroup might have no effect at all. This property should
15781     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
15782     *
15783     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
15784     * property is enabled, an exception will be thrown.</p>
15785     *
15786     * <p>Note: if the child view uses and updates additional states which are unknown to the
15787     * parent, these states should not be affected by this method.</p>
15788     *
15789     * @param enabled True to enable duplication of the parent's drawable state, false
15790     *                to disable it.
15791     *
15792     * @see #getDrawableState()
15793     * @see #isDuplicateParentStateEnabled()
15794     */
15795    public void setDuplicateParentStateEnabled(boolean enabled) {
15796        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
15797    }
15798
15799    /**
15800     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
15801     *
15802     * @return True if this view's drawable state is duplicated from the parent,
15803     *         false otherwise
15804     *
15805     * @see #getDrawableState()
15806     * @see #setDuplicateParentStateEnabled(boolean)
15807     */
15808    public boolean isDuplicateParentStateEnabled() {
15809        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
15810    }
15811
15812    /**
15813     * <p>Specifies the type of layer backing this view. The layer can be
15814     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15815     * {@link #LAYER_TYPE_HARDWARE}.</p>
15816     *
15817     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15818     * instance that controls how the layer is composed on screen. The following
15819     * properties of the paint are taken into account when composing the layer:</p>
15820     * <ul>
15821     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15822     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15823     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15824     * </ul>
15825     *
15826     * <p>If this view has an alpha value set to < 1.0 by calling
15827     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
15828     * by this view's alpha value.</p>
15829     *
15830     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
15831     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
15832     * for more information on when and how to use layers.</p>
15833     *
15834     * @param layerType The type of layer to use with this view, must be one of
15835     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15836     *        {@link #LAYER_TYPE_HARDWARE}
15837     * @param paint The paint used to compose the layer. This argument is optional
15838     *        and can be null. It is ignored when the layer type is
15839     *        {@link #LAYER_TYPE_NONE}
15840     *
15841     * @see #getLayerType()
15842     * @see #LAYER_TYPE_NONE
15843     * @see #LAYER_TYPE_SOFTWARE
15844     * @see #LAYER_TYPE_HARDWARE
15845     * @see #setAlpha(float)
15846     *
15847     * @attr ref android.R.styleable#View_layerType
15848     */
15849    public void setLayerType(int layerType, @Nullable Paint paint) {
15850        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15851            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15852                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15853        }
15854
15855        boolean typeChanged = mRenderNode.setLayerType(layerType);
15856
15857        if (!typeChanged) {
15858            setLayerPaint(paint);
15859            return;
15860        }
15861
15862        if (layerType != LAYER_TYPE_SOFTWARE) {
15863            // Destroy any previous software drawing cache if present
15864            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
15865            // drawing cache created in View#draw when drawing to a SW canvas.
15866            destroyDrawingCache();
15867        }
15868
15869        mLayerType = layerType;
15870        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
15871        mRenderNode.setLayerPaint(mLayerPaint);
15872
15873        // draw() behaves differently if we are on a layer, so we need to
15874        // invalidate() here
15875        invalidateParentCaches();
15876        invalidate(true);
15877    }
15878
15879    /**
15880     * Updates the {@link Paint} object used with the current layer (used only if the current
15881     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15882     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15883     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15884     * ensure that the view gets redrawn immediately.
15885     *
15886     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15887     * instance that controls how the layer is composed on screen. The following
15888     * properties of the paint are taken into account when composing the layer:</p>
15889     * <ul>
15890     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15891     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15892     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15893     * </ul>
15894     *
15895     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15896     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15897     *
15898     * @param paint The paint used to compose the layer. This argument is optional
15899     *        and can be null. It is ignored when the layer type is
15900     *        {@link #LAYER_TYPE_NONE}
15901     *
15902     * @see #setLayerType(int, android.graphics.Paint)
15903     */
15904    public void setLayerPaint(@Nullable Paint paint) {
15905        int layerType = getLayerType();
15906        if (layerType != LAYER_TYPE_NONE) {
15907            mLayerPaint = paint;
15908            if (layerType == LAYER_TYPE_HARDWARE) {
15909                if (mRenderNode.setLayerPaint(paint)) {
15910                    invalidateViewProperty(false, false);
15911                }
15912            } else {
15913                invalidate();
15914            }
15915        }
15916    }
15917
15918    /**
15919     * Indicates what type of layer is currently associated with this view. By default
15920     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15921     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15922     * for more information on the different types of layers.
15923     *
15924     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15925     *         {@link #LAYER_TYPE_HARDWARE}
15926     *
15927     * @see #setLayerType(int, android.graphics.Paint)
15928     * @see #buildLayer()
15929     * @see #LAYER_TYPE_NONE
15930     * @see #LAYER_TYPE_SOFTWARE
15931     * @see #LAYER_TYPE_HARDWARE
15932     */
15933    public int getLayerType() {
15934        return mLayerType;
15935    }
15936
15937    /**
15938     * Forces this view's layer to be created and this view to be rendered
15939     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15940     * invoking this method will have no effect.
15941     *
15942     * This method can for instance be used to render a view into its layer before
15943     * starting an animation. If this view is complex, rendering into the layer
15944     * before starting the animation will avoid skipping frames.
15945     *
15946     * @throws IllegalStateException If this view is not attached to a window
15947     *
15948     * @see #setLayerType(int, android.graphics.Paint)
15949     */
15950    public void buildLayer() {
15951        if (mLayerType == LAYER_TYPE_NONE) return;
15952
15953        final AttachInfo attachInfo = mAttachInfo;
15954        if (attachInfo == null) {
15955            throw new IllegalStateException("This view must be attached to a window first");
15956        }
15957
15958        if (getWidth() == 0 || getHeight() == 0) {
15959            return;
15960        }
15961
15962        switch (mLayerType) {
15963            case LAYER_TYPE_HARDWARE:
15964                updateDisplayListIfDirty();
15965                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
15966                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
15967                }
15968                break;
15969            case LAYER_TYPE_SOFTWARE:
15970                buildDrawingCache(true);
15971                break;
15972        }
15973    }
15974
15975    /**
15976     * Destroys all hardware rendering resources. This method is invoked
15977     * when the system needs to reclaim resources. Upon execution of this
15978     * method, you should free any OpenGL resources created by the view.
15979     *
15980     * Note: you <strong>must</strong> call
15981     * <code>super.destroyHardwareResources()</code> when overriding
15982     * this method.
15983     *
15984     * @hide
15985     */
15986    @CallSuper
15987    protected void destroyHardwareResources() {
15988        // Although the Layer will be destroyed by RenderNode, we want to release
15989        // the staging display list, which is also a signal to RenderNode that it's
15990        // safe to free its copy of the display list as it knows that we will
15991        // push an updated DisplayList if we try to draw again
15992        resetDisplayList();
15993    }
15994
15995    /**
15996     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
15997     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
15998     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
15999     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
16000     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
16001     * null.</p>
16002     *
16003     * <p>Enabling the drawing cache is similar to
16004     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
16005     * acceleration is turned off. When hardware acceleration is turned on, enabling the
16006     * drawing cache has no effect on rendering because the system uses a different mechanism
16007     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
16008     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
16009     * for information on how to enable software and hardware layers.</p>
16010     *
16011     * <p>This API can be used to manually generate
16012     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
16013     * {@link #getDrawingCache()}.</p>
16014     *
16015     * @param enabled true to enable the drawing cache, false otherwise
16016     *
16017     * @see #isDrawingCacheEnabled()
16018     * @see #getDrawingCache()
16019     * @see #buildDrawingCache()
16020     * @see #setLayerType(int, android.graphics.Paint)
16021     */
16022    public void setDrawingCacheEnabled(boolean enabled) {
16023        mCachingFailed = false;
16024        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
16025    }
16026
16027    /**
16028     * <p>Indicates whether the drawing cache is enabled for this view.</p>
16029     *
16030     * @return true if the drawing cache is enabled
16031     *
16032     * @see #setDrawingCacheEnabled(boolean)
16033     * @see #getDrawingCache()
16034     */
16035    @ViewDebug.ExportedProperty(category = "drawing")
16036    public boolean isDrawingCacheEnabled() {
16037        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
16038    }
16039
16040    /**
16041     * Debugging utility which recursively outputs the dirty state of a view and its
16042     * descendants.
16043     *
16044     * @hide
16045     */
16046    @SuppressWarnings({"UnusedDeclaration"})
16047    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
16048        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
16049                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
16050                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
16051                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
16052        if (clear) {
16053            mPrivateFlags &= clearMask;
16054        }
16055        if (this instanceof ViewGroup) {
16056            ViewGroup parent = (ViewGroup) this;
16057            final int count = parent.getChildCount();
16058            for (int i = 0; i < count; i++) {
16059                final View child = parent.getChildAt(i);
16060                child.outputDirtyFlags(indent + "  ", clear, clearMask);
16061            }
16062        }
16063    }
16064
16065    /**
16066     * This method is used by ViewGroup to cause its children to restore or recreate their
16067     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
16068     * to recreate its own display list, which would happen if it went through the normal
16069     * draw/dispatchDraw mechanisms.
16070     *
16071     * @hide
16072     */
16073    protected void dispatchGetDisplayList() {}
16074
16075    /**
16076     * A view that is not attached or hardware accelerated cannot create a display list.
16077     * This method checks these conditions and returns the appropriate result.
16078     *
16079     * @return true if view has the ability to create a display list, false otherwise.
16080     *
16081     * @hide
16082     */
16083    public boolean canHaveDisplayList() {
16084        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
16085    }
16086
16087    /**
16088     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
16089     * @hide
16090     */
16091    @NonNull
16092    public RenderNode updateDisplayListIfDirty() {
16093        final RenderNode renderNode = mRenderNode;
16094        if (!canHaveDisplayList()) {
16095            // can't populate RenderNode, don't try
16096            return renderNode;
16097        }
16098
16099        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
16100                || !renderNode.isValid()
16101                || (mRecreateDisplayList)) {
16102            // Don't need to recreate the display list, just need to tell our
16103            // children to restore/recreate theirs
16104            if (renderNode.isValid()
16105                    && !mRecreateDisplayList) {
16106                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16107                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16108                dispatchGetDisplayList();
16109
16110                return renderNode; // no work needed
16111            }
16112
16113            // If we got here, we're recreating it. Mark it as such to ensure that
16114            // we copy in child display lists into ours in drawChild()
16115            mRecreateDisplayList = true;
16116
16117            int width = mRight - mLeft;
16118            int height = mBottom - mTop;
16119            int layerType = getLayerType();
16120
16121            final DisplayListCanvas canvas = renderNode.start(width, height);
16122            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
16123
16124            try {
16125                if (layerType == LAYER_TYPE_SOFTWARE) {
16126                    buildDrawingCache(true);
16127                    Bitmap cache = getDrawingCache(true);
16128                    if (cache != null) {
16129                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
16130                    }
16131                } else {
16132                    computeScroll();
16133
16134                    canvas.translate(-mScrollX, -mScrollY);
16135                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16136                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16137
16138                    // Fast path for layouts with no backgrounds
16139                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16140                        dispatchDraw(canvas);
16141                        if (mOverlay != null && !mOverlay.isEmpty()) {
16142                            mOverlay.getOverlayView().draw(canvas);
16143                        }
16144                    } else {
16145                        draw(canvas);
16146                    }
16147                }
16148            } finally {
16149                renderNode.end(canvas);
16150                setDisplayListProperties(renderNode);
16151            }
16152        } else {
16153            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16154            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16155        }
16156        return renderNode;
16157    }
16158
16159    private void resetDisplayList() {
16160        if (mRenderNode.isValid()) {
16161            mRenderNode.discardDisplayList();
16162        }
16163
16164        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
16165            mBackgroundRenderNode.discardDisplayList();
16166        }
16167    }
16168
16169    /**
16170     * Called when the passed RenderNode is removed from the draw tree
16171     * @hide
16172     */
16173    public void onRenderNodeDetached(RenderNode renderNode) {
16174    }
16175
16176    /**
16177     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
16178     *
16179     * @return A non-scaled bitmap representing this view or null if cache is disabled.
16180     *
16181     * @see #getDrawingCache(boolean)
16182     */
16183    public Bitmap getDrawingCache() {
16184        return getDrawingCache(false);
16185    }
16186
16187    /**
16188     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
16189     * is null when caching is disabled. If caching is enabled and the cache is not ready,
16190     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
16191     * draw from the cache when the cache is enabled. To benefit from the cache, you must
16192     * request the drawing cache by calling this method and draw it on screen if the
16193     * returned bitmap is not null.</p>
16194     *
16195     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16196     * this method will create a bitmap of the same size as this view. Because this bitmap
16197     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16198     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16199     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16200     * size than the view. This implies that your application must be able to handle this
16201     * size.</p>
16202     *
16203     * @param autoScale Indicates whether the generated bitmap should be scaled based on
16204     *        the current density of the screen when the application is in compatibility
16205     *        mode.
16206     *
16207     * @return A bitmap representing this view or null if cache is disabled.
16208     *
16209     * @see #setDrawingCacheEnabled(boolean)
16210     * @see #isDrawingCacheEnabled()
16211     * @see #buildDrawingCache(boolean)
16212     * @see #destroyDrawingCache()
16213     */
16214    public Bitmap getDrawingCache(boolean autoScale) {
16215        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
16216            return null;
16217        }
16218        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
16219            buildDrawingCache(autoScale);
16220        }
16221        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
16222    }
16223
16224    /**
16225     * <p>Frees the resources used by the drawing cache. If you call
16226     * {@link #buildDrawingCache()} manually without calling
16227     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16228     * should cleanup the cache with this method afterwards.</p>
16229     *
16230     * @see #setDrawingCacheEnabled(boolean)
16231     * @see #buildDrawingCache()
16232     * @see #getDrawingCache()
16233     */
16234    public void destroyDrawingCache() {
16235        if (mDrawingCache != null) {
16236            mDrawingCache.recycle();
16237            mDrawingCache = null;
16238        }
16239        if (mUnscaledDrawingCache != null) {
16240            mUnscaledDrawingCache.recycle();
16241            mUnscaledDrawingCache = null;
16242        }
16243    }
16244
16245    /**
16246     * Setting a solid background color for the drawing cache's bitmaps will improve
16247     * performance and memory usage. Note, though that this should only be used if this
16248     * view will always be drawn on top of a solid color.
16249     *
16250     * @param color The background color to use for the drawing cache's bitmap
16251     *
16252     * @see #setDrawingCacheEnabled(boolean)
16253     * @see #buildDrawingCache()
16254     * @see #getDrawingCache()
16255     */
16256    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
16257        if (color != mDrawingCacheBackgroundColor) {
16258            mDrawingCacheBackgroundColor = color;
16259            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16260        }
16261    }
16262
16263    /**
16264     * @see #setDrawingCacheBackgroundColor(int)
16265     *
16266     * @return The background color to used for the drawing cache's bitmap
16267     */
16268    @ColorInt
16269    public int getDrawingCacheBackgroundColor() {
16270        return mDrawingCacheBackgroundColor;
16271    }
16272
16273    /**
16274     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
16275     *
16276     * @see #buildDrawingCache(boolean)
16277     */
16278    public void buildDrawingCache() {
16279        buildDrawingCache(false);
16280    }
16281
16282    /**
16283     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
16284     *
16285     * <p>If you call {@link #buildDrawingCache()} manually without calling
16286     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16287     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
16288     *
16289     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16290     * this method will create a bitmap of the same size as this view. Because this bitmap
16291     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16292     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16293     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16294     * size than the view. This implies that your application must be able to handle this
16295     * size.</p>
16296     *
16297     * <p>You should avoid calling this method when hardware acceleration is enabled. If
16298     * you do not need the drawing cache bitmap, calling this method will increase memory
16299     * usage and cause the view to be rendered in software once, thus negatively impacting
16300     * performance.</p>
16301     *
16302     * @see #getDrawingCache()
16303     * @see #destroyDrawingCache()
16304     */
16305    public void buildDrawingCache(boolean autoScale) {
16306        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
16307                mDrawingCache == null : mUnscaledDrawingCache == null)) {
16308            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
16309                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
16310                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
16311            }
16312            try {
16313                buildDrawingCacheImpl(autoScale);
16314            } finally {
16315                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
16316            }
16317        }
16318    }
16319
16320    /**
16321     * private, internal implementation of buildDrawingCache, used to enable tracing
16322     */
16323    private void buildDrawingCacheImpl(boolean autoScale) {
16324        mCachingFailed = false;
16325
16326        int width = mRight - mLeft;
16327        int height = mBottom - mTop;
16328
16329        final AttachInfo attachInfo = mAttachInfo;
16330        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
16331
16332        if (autoScale && scalingRequired) {
16333            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
16334            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
16335        }
16336
16337        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
16338        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
16339        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
16340
16341        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
16342        final long drawingCacheSize =
16343                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
16344        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
16345            if (width > 0 && height > 0) {
16346                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
16347                        + " too large to fit into a software layer (or drawing cache), needs "
16348                        + projectedBitmapSize + " bytes, only "
16349                        + drawingCacheSize + " available");
16350            }
16351            destroyDrawingCache();
16352            mCachingFailed = true;
16353            return;
16354        }
16355
16356        boolean clear = true;
16357        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
16358
16359        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
16360            Bitmap.Config quality;
16361            if (!opaque) {
16362                // Never pick ARGB_4444 because it looks awful
16363                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
16364                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
16365                    case DRAWING_CACHE_QUALITY_AUTO:
16366                    case DRAWING_CACHE_QUALITY_LOW:
16367                    case DRAWING_CACHE_QUALITY_HIGH:
16368                    default:
16369                        quality = Bitmap.Config.ARGB_8888;
16370                        break;
16371                }
16372            } else {
16373                // Optimization for translucent windows
16374                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
16375                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
16376            }
16377
16378            // Try to cleanup memory
16379            if (bitmap != null) bitmap.recycle();
16380
16381            try {
16382                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16383                        width, height, quality);
16384                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
16385                if (autoScale) {
16386                    mDrawingCache = bitmap;
16387                } else {
16388                    mUnscaledDrawingCache = bitmap;
16389                }
16390                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
16391            } catch (OutOfMemoryError e) {
16392                // If there is not enough memory to create the bitmap cache, just
16393                // ignore the issue as bitmap caches are not required to draw the
16394                // view hierarchy
16395                if (autoScale) {
16396                    mDrawingCache = null;
16397                } else {
16398                    mUnscaledDrawingCache = null;
16399                }
16400                mCachingFailed = true;
16401                return;
16402            }
16403
16404            clear = drawingCacheBackgroundColor != 0;
16405        }
16406
16407        Canvas canvas;
16408        if (attachInfo != null) {
16409            canvas = attachInfo.mCanvas;
16410            if (canvas == null) {
16411                canvas = new Canvas();
16412            }
16413            canvas.setBitmap(bitmap);
16414            // Temporarily clobber the cached Canvas in case one of our children
16415            // is also using a drawing cache. Without this, the children would
16416            // steal the canvas by attaching their own bitmap to it and bad, bad
16417            // thing would happen (invisible views, corrupted drawings, etc.)
16418            attachInfo.mCanvas = null;
16419        } else {
16420            // This case should hopefully never or seldom happen
16421            canvas = new Canvas(bitmap);
16422        }
16423
16424        if (clear) {
16425            bitmap.eraseColor(drawingCacheBackgroundColor);
16426        }
16427
16428        computeScroll();
16429        final int restoreCount = canvas.save();
16430
16431        if (autoScale && scalingRequired) {
16432            final float scale = attachInfo.mApplicationScale;
16433            canvas.scale(scale, scale);
16434        }
16435
16436        canvas.translate(-mScrollX, -mScrollY);
16437
16438        mPrivateFlags |= PFLAG_DRAWN;
16439        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
16440                mLayerType != LAYER_TYPE_NONE) {
16441            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
16442        }
16443
16444        // Fast path for layouts with no backgrounds
16445        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16446            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16447            dispatchDraw(canvas);
16448            if (mOverlay != null && !mOverlay.isEmpty()) {
16449                mOverlay.getOverlayView().draw(canvas);
16450            }
16451        } else {
16452            draw(canvas);
16453        }
16454
16455        canvas.restoreToCount(restoreCount);
16456        canvas.setBitmap(null);
16457
16458        if (attachInfo != null) {
16459            // Restore the cached Canvas for our siblings
16460            attachInfo.mCanvas = canvas;
16461        }
16462    }
16463
16464    /**
16465     * Create a snapshot of the view into a bitmap.  We should probably make
16466     * some form of this public, but should think about the API.
16467     *
16468     * @hide
16469     */
16470    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
16471        int width = mRight - mLeft;
16472        int height = mBottom - mTop;
16473
16474        final AttachInfo attachInfo = mAttachInfo;
16475        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
16476        width = (int) ((width * scale) + 0.5f);
16477        height = (int) ((height * scale) + 0.5f);
16478
16479        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16480                width > 0 ? width : 1, height > 0 ? height : 1, quality);
16481        if (bitmap == null) {
16482            throw new OutOfMemoryError();
16483        }
16484
16485        Resources resources = getResources();
16486        if (resources != null) {
16487            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
16488        }
16489
16490        Canvas canvas;
16491        if (attachInfo != null) {
16492            canvas = attachInfo.mCanvas;
16493            if (canvas == null) {
16494                canvas = new Canvas();
16495            }
16496            canvas.setBitmap(bitmap);
16497            // Temporarily clobber the cached Canvas in case one of our children
16498            // is also using a drawing cache. Without this, the children would
16499            // steal the canvas by attaching their own bitmap to it and bad, bad
16500            // things would happen (invisible views, corrupted drawings, etc.)
16501            attachInfo.mCanvas = null;
16502        } else {
16503            // This case should hopefully never or seldom happen
16504            canvas = new Canvas(bitmap);
16505        }
16506
16507        if ((backgroundColor & 0xff000000) != 0) {
16508            bitmap.eraseColor(backgroundColor);
16509        }
16510
16511        computeScroll();
16512        final int restoreCount = canvas.save();
16513        canvas.scale(scale, scale);
16514        canvas.translate(-mScrollX, -mScrollY);
16515
16516        // Temporarily remove the dirty mask
16517        int flags = mPrivateFlags;
16518        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16519
16520        // Fast path for layouts with no backgrounds
16521        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16522            dispatchDraw(canvas);
16523            if (mOverlay != null && !mOverlay.isEmpty()) {
16524                mOverlay.getOverlayView().draw(canvas);
16525            }
16526        } else {
16527            draw(canvas);
16528        }
16529
16530        mPrivateFlags = flags;
16531
16532        canvas.restoreToCount(restoreCount);
16533        canvas.setBitmap(null);
16534
16535        if (attachInfo != null) {
16536            // Restore the cached Canvas for our siblings
16537            attachInfo.mCanvas = canvas;
16538        }
16539
16540        return bitmap;
16541    }
16542
16543    /**
16544     * Indicates whether this View is currently in edit mode. A View is usually
16545     * in edit mode when displayed within a developer tool. For instance, if
16546     * this View is being drawn by a visual user interface builder, this method
16547     * should return true.
16548     *
16549     * Subclasses should check the return value of this method to provide
16550     * different behaviors if their normal behavior might interfere with the
16551     * host environment. For instance: the class spawns a thread in its
16552     * constructor, the drawing code relies on device-specific features, etc.
16553     *
16554     * This method is usually checked in the drawing code of custom widgets.
16555     *
16556     * @return True if this View is in edit mode, false otherwise.
16557     */
16558    public boolean isInEditMode() {
16559        return false;
16560    }
16561
16562    /**
16563     * If the View draws content inside its padding and enables fading edges,
16564     * it needs to support padding offsets. Padding offsets are added to the
16565     * fading edges to extend the length of the fade so that it covers pixels
16566     * drawn inside the padding.
16567     *
16568     * Subclasses of this class should override this method if they need
16569     * to draw content inside the padding.
16570     *
16571     * @return True if padding offset must be applied, false otherwise.
16572     *
16573     * @see #getLeftPaddingOffset()
16574     * @see #getRightPaddingOffset()
16575     * @see #getTopPaddingOffset()
16576     * @see #getBottomPaddingOffset()
16577     *
16578     * @since CURRENT
16579     */
16580    protected boolean isPaddingOffsetRequired() {
16581        return false;
16582    }
16583
16584    /**
16585     * Amount by which to extend the left fading region. Called only when
16586     * {@link #isPaddingOffsetRequired()} returns true.
16587     *
16588     * @return The left padding offset in pixels.
16589     *
16590     * @see #isPaddingOffsetRequired()
16591     *
16592     * @since CURRENT
16593     */
16594    protected int getLeftPaddingOffset() {
16595        return 0;
16596    }
16597
16598    /**
16599     * Amount by which to extend the right fading region. Called only when
16600     * {@link #isPaddingOffsetRequired()} returns true.
16601     *
16602     * @return The right padding offset in pixels.
16603     *
16604     * @see #isPaddingOffsetRequired()
16605     *
16606     * @since CURRENT
16607     */
16608    protected int getRightPaddingOffset() {
16609        return 0;
16610    }
16611
16612    /**
16613     * Amount by which to extend the top fading region. Called only when
16614     * {@link #isPaddingOffsetRequired()} returns true.
16615     *
16616     * @return The top padding offset in pixels.
16617     *
16618     * @see #isPaddingOffsetRequired()
16619     *
16620     * @since CURRENT
16621     */
16622    protected int getTopPaddingOffset() {
16623        return 0;
16624    }
16625
16626    /**
16627     * Amount by which to extend the bottom fading region. Called only when
16628     * {@link #isPaddingOffsetRequired()} returns true.
16629     *
16630     * @return The bottom padding offset in pixels.
16631     *
16632     * @see #isPaddingOffsetRequired()
16633     *
16634     * @since CURRENT
16635     */
16636    protected int getBottomPaddingOffset() {
16637        return 0;
16638    }
16639
16640    /**
16641     * @hide
16642     * @param offsetRequired
16643     */
16644    protected int getFadeTop(boolean offsetRequired) {
16645        int top = mPaddingTop;
16646        if (offsetRequired) top += getTopPaddingOffset();
16647        return top;
16648    }
16649
16650    /**
16651     * @hide
16652     * @param offsetRequired
16653     */
16654    protected int getFadeHeight(boolean offsetRequired) {
16655        int padding = mPaddingTop;
16656        if (offsetRequired) padding += getTopPaddingOffset();
16657        return mBottom - mTop - mPaddingBottom - padding;
16658    }
16659
16660    /**
16661     * <p>Indicates whether this view is attached to a hardware accelerated
16662     * window or not.</p>
16663     *
16664     * <p>Even if this method returns true, it does not mean that every call
16665     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
16666     * accelerated {@link android.graphics.Canvas}. For instance, if this view
16667     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
16668     * window is hardware accelerated,
16669     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
16670     * return false, and this method will return true.</p>
16671     *
16672     * @return True if the view is attached to a window and the window is
16673     *         hardware accelerated; false in any other case.
16674     */
16675    @ViewDebug.ExportedProperty(category = "drawing")
16676    public boolean isHardwareAccelerated() {
16677        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
16678    }
16679
16680    /**
16681     * Sets a rectangular area on this view to which the view will be clipped
16682     * when it is drawn. Setting the value to null will remove the clip bounds
16683     * and the view will draw normally, using its full bounds.
16684     *
16685     * @param clipBounds The rectangular area, in the local coordinates of
16686     * this view, to which future drawing operations will be clipped.
16687     */
16688    public void setClipBounds(Rect clipBounds) {
16689        if (clipBounds == mClipBounds
16690                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
16691            return;
16692        }
16693        if (clipBounds != null) {
16694            if (mClipBounds == null) {
16695                mClipBounds = new Rect(clipBounds);
16696            } else {
16697                mClipBounds.set(clipBounds);
16698            }
16699        } else {
16700            mClipBounds = null;
16701        }
16702        mRenderNode.setClipBounds(mClipBounds);
16703        invalidateViewProperty(false, false);
16704    }
16705
16706    /**
16707     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
16708     *
16709     * @return A copy of the current clip bounds if clip bounds are set,
16710     * otherwise null.
16711     */
16712    public Rect getClipBounds() {
16713        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
16714    }
16715
16716
16717    /**
16718     * Populates an output rectangle with the clip bounds of the view,
16719     * returning {@code true} if successful or {@code false} if the view's
16720     * clip bounds are {@code null}.
16721     *
16722     * @param outRect rectangle in which to place the clip bounds of the view
16723     * @return {@code true} if successful or {@code false} if the view's
16724     *         clip bounds are {@code null}
16725     */
16726    public boolean getClipBounds(Rect outRect) {
16727        if (mClipBounds != null) {
16728            outRect.set(mClipBounds);
16729            return true;
16730        }
16731        return false;
16732    }
16733
16734    /**
16735     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
16736     * case of an active Animation being run on the view.
16737     */
16738    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
16739            Animation a, boolean scalingRequired) {
16740        Transformation invalidationTransform;
16741        final int flags = parent.mGroupFlags;
16742        final boolean initialized = a.isInitialized();
16743        if (!initialized) {
16744            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
16745            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
16746            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
16747            onAnimationStart();
16748        }
16749
16750        final Transformation t = parent.getChildTransformation();
16751        boolean more = a.getTransformation(drawingTime, t, 1f);
16752        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
16753            if (parent.mInvalidationTransformation == null) {
16754                parent.mInvalidationTransformation = new Transformation();
16755            }
16756            invalidationTransform = parent.mInvalidationTransformation;
16757            a.getTransformation(drawingTime, invalidationTransform, 1f);
16758        } else {
16759            invalidationTransform = t;
16760        }
16761
16762        if (more) {
16763            if (!a.willChangeBounds()) {
16764                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
16765                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
16766                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
16767                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
16768                    // The child need to draw an animation, potentially offscreen, so
16769                    // make sure we do not cancel invalidate requests
16770                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16771                    parent.invalidate(mLeft, mTop, mRight, mBottom);
16772                }
16773            } else {
16774                if (parent.mInvalidateRegion == null) {
16775                    parent.mInvalidateRegion = new RectF();
16776                }
16777                final RectF region = parent.mInvalidateRegion;
16778                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
16779                        invalidationTransform);
16780
16781                // The child need to draw an animation, potentially offscreen, so
16782                // make sure we do not cancel invalidate requests
16783                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16784
16785                final int left = mLeft + (int) region.left;
16786                final int top = mTop + (int) region.top;
16787                parent.invalidate(left, top, left + (int) (region.width() + .5f),
16788                        top + (int) (region.height() + .5f));
16789            }
16790        }
16791        return more;
16792    }
16793
16794    /**
16795     * This method is called by getDisplayList() when a display list is recorded for a View.
16796     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
16797     */
16798    void setDisplayListProperties(RenderNode renderNode) {
16799        if (renderNode != null) {
16800            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
16801            renderNode.setClipToBounds(mParent instanceof ViewGroup
16802                    && ((ViewGroup) mParent).getClipChildren());
16803
16804            float alpha = 1;
16805            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
16806                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16807                ViewGroup parentVG = (ViewGroup) mParent;
16808                final Transformation t = parentVG.getChildTransformation();
16809                if (parentVG.getChildStaticTransformation(this, t)) {
16810                    final int transformType = t.getTransformationType();
16811                    if (transformType != Transformation.TYPE_IDENTITY) {
16812                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
16813                            alpha = t.getAlpha();
16814                        }
16815                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
16816                            renderNode.setStaticMatrix(t.getMatrix());
16817                        }
16818                    }
16819                }
16820            }
16821            if (mTransformationInfo != null) {
16822                alpha *= getFinalAlpha();
16823                if (alpha < 1) {
16824                    final int multipliedAlpha = (int) (255 * alpha);
16825                    if (onSetAlpha(multipliedAlpha)) {
16826                        alpha = 1;
16827                    }
16828                }
16829                renderNode.setAlpha(alpha);
16830            } else if (alpha < 1) {
16831                renderNode.setAlpha(alpha);
16832            }
16833        }
16834    }
16835
16836    /**
16837     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
16838     *
16839     * This is where the View specializes rendering behavior based on layer type,
16840     * and hardware acceleration.
16841     */
16842    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
16843        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
16844        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
16845         *
16846         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
16847         * HW accelerated, it can't handle drawing RenderNodes.
16848         */
16849        boolean drawingWithRenderNode = mAttachInfo != null
16850                && mAttachInfo.mHardwareAccelerated
16851                && hardwareAcceleratedCanvas;
16852
16853        boolean more = false;
16854        final boolean childHasIdentityMatrix = hasIdentityMatrix();
16855        final int parentFlags = parent.mGroupFlags;
16856
16857        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16858            parent.getChildTransformation().clear();
16859            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16860        }
16861
16862        Transformation transformToApply = null;
16863        boolean concatMatrix = false;
16864        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16865        final Animation a = getAnimation();
16866        if (a != null) {
16867            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16868            concatMatrix = a.willChangeTransformationMatrix();
16869            if (concatMatrix) {
16870                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16871            }
16872            transformToApply = parent.getChildTransformation();
16873        } else {
16874            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16875                // No longer animating: clear out old animation matrix
16876                mRenderNode.setAnimationMatrix(null);
16877                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16878            }
16879            if (!drawingWithRenderNode
16880                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16881                final Transformation t = parent.getChildTransformation();
16882                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16883                if (hasTransform) {
16884                    final int transformType = t.getTransformationType();
16885                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16886                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16887                }
16888            }
16889        }
16890
16891        concatMatrix |= !childHasIdentityMatrix;
16892
16893        // Sets the flag as early as possible to allow draw() implementations
16894        // to call invalidate() successfully when doing animations
16895        mPrivateFlags |= PFLAG_DRAWN;
16896
16897        if (!concatMatrix &&
16898                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16899                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16900                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16901                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16902            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16903            return more;
16904        }
16905        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16906
16907        if (hardwareAcceleratedCanvas) {
16908            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16909            // retain the flag's value temporarily in the mRecreateDisplayList flag
16910            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16911            mPrivateFlags &= ~PFLAG_INVALIDATED;
16912        }
16913
16914        RenderNode renderNode = null;
16915        Bitmap cache = null;
16916        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16917        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
16918             if (layerType != LAYER_TYPE_NONE) {
16919                 // If not drawing with RenderNode, treat HW layers as SW
16920                 layerType = LAYER_TYPE_SOFTWARE;
16921                 buildDrawingCache(true);
16922            }
16923            cache = getDrawingCache(true);
16924        }
16925
16926        if (drawingWithRenderNode) {
16927            // Delay getting the display list until animation-driven alpha values are
16928            // set up and possibly passed on to the view
16929            renderNode = updateDisplayListIfDirty();
16930            if (!renderNode.isValid()) {
16931                // Uncommon, but possible. If a view is removed from the hierarchy during the call
16932                // to getDisplayList(), the display list will be marked invalid and we should not
16933                // try to use it again.
16934                renderNode = null;
16935                drawingWithRenderNode = false;
16936            }
16937        }
16938
16939        int sx = 0;
16940        int sy = 0;
16941        if (!drawingWithRenderNode) {
16942            computeScroll();
16943            sx = mScrollX;
16944            sy = mScrollY;
16945        }
16946
16947        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16948        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16949
16950        int restoreTo = -1;
16951        if (!drawingWithRenderNode || transformToApply != null) {
16952            restoreTo = canvas.save();
16953        }
16954        if (offsetForScroll) {
16955            canvas.translate(mLeft - sx, mTop - sy);
16956        } else {
16957            if (!drawingWithRenderNode) {
16958                canvas.translate(mLeft, mTop);
16959            }
16960            if (scalingRequired) {
16961                if (drawingWithRenderNode) {
16962                    // TODO: Might not need this if we put everything inside the DL
16963                    restoreTo = canvas.save();
16964                }
16965                // mAttachInfo cannot be null, otherwise scalingRequired == false
16966                final float scale = 1.0f / mAttachInfo.mApplicationScale;
16967                canvas.scale(scale, scale);
16968            }
16969        }
16970
16971        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16972        if (transformToApply != null
16973                || alpha < 1
16974                || !hasIdentityMatrix()
16975                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16976            if (transformToApply != null || !childHasIdentityMatrix) {
16977                int transX = 0;
16978                int transY = 0;
16979
16980                if (offsetForScroll) {
16981                    transX = -sx;
16982                    transY = -sy;
16983                }
16984
16985                if (transformToApply != null) {
16986                    if (concatMatrix) {
16987                        if (drawingWithRenderNode) {
16988                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
16989                        } else {
16990                            // Undo the scroll translation, apply the transformation matrix,
16991                            // then redo the scroll translate to get the correct result.
16992                            canvas.translate(-transX, -transY);
16993                            canvas.concat(transformToApply.getMatrix());
16994                            canvas.translate(transX, transY);
16995                        }
16996                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16997                    }
16998
16999                    float transformAlpha = transformToApply.getAlpha();
17000                    if (transformAlpha < 1) {
17001                        alpha *= transformAlpha;
17002                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17003                    }
17004                }
17005
17006                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
17007                    canvas.translate(-transX, -transY);
17008                    canvas.concat(getMatrix());
17009                    canvas.translate(transX, transY);
17010                }
17011            }
17012
17013            // Deal with alpha if it is or used to be <1
17014            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17015                if (alpha < 1) {
17016                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17017                } else {
17018                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17019                }
17020                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17021                if (!drawingWithDrawingCache) {
17022                    final int multipliedAlpha = (int) (255 * alpha);
17023                    if (!onSetAlpha(multipliedAlpha)) {
17024                        if (drawingWithRenderNode) {
17025                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
17026                        } else if (layerType == LAYER_TYPE_NONE) {
17027                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
17028                                    multipliedAlpha);
17029                        }
17030                    } else {
17031                        // Alpha is handled by the child directly, clobber the layer's alpha
17032                        mPrivateFlags |= PFLAG_ALPHA_SET;
17033                    }
17034                }
17035            }
17036        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17037            onSetAlpha(255);
17038            mPrivateFlags &= ~PFLAG_ALPHA_SET;
17039        }
17040
17041        if (!drawingWithRenderNode) {
17042            // apply clips directly, since RenderNode won't do it for this draw
17043            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
17044                if (offsetForScroll) {
17045                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
17046                } else {
17047                    if (!scalingRequired || cache == null) {
17048                        canvas.clipRect(0, 0, getWidth(), getHeight());
17049                    } else {
17050                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
17051                    }
17052                }
17053            }
17054
17055            if (mClipBounds != null) {
17056                // clip bounds ignore scroll
17057                canvas.clipRect(mClipBounds);
17058            }
17059        }
17060
17061        if (!drawingWithDrawingCache) {
17062            if (drawingWithRenderNode) {
17063                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17064                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17065            } else {
17066                // Fast path for layouts with no backgrounds
17067                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17068                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17069                    dispatchDraw(canvas);
17070                } else {
17071                    draw(canvas);
17072                }
17073            }
17074        } else if (cache != null) {
17075            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17076            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
17077                // no layer paint, use temporary paint to draw bitmap
17078                Paint cachePaint = parent.mCachePaint;
17079                if (cachePaint == null) {
17080                    cachePaint = new Paint();
17081                    cachePaint.setDither(false);
17082                    parent.mCachePaint = cachePaint;
17083                }
17084                cachePaint.setAlpha((int) (alpha * 255));
17085                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
17086            } else {
17087                // use layer paint to draw the bitmap, merging the two alphas, but also restore
17088                int layerPaintAlpha = mLayerPaint.getAlpha();
17089                if (alpha < 1) {
17090                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
17091                }
17092                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
17093                if (alpha < 1) {
17094                    mLayerPaint.setAlpha(layerPaintAlpha);
17095                }
17096            }
17097        }
17098
17099        if (restoreTo >= 0) {
17100            canvas.restoreToCount(restoreTo);
17101        }
17102
17103        if (a != null && !more) {
17104            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
17105                onSetAlpha(255);
17106            }
17107            parent.finishAnimatingView(this, a);
17108        }
17109
17110        if (more && hardwareAcceleratedCanvas) {
17111            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17112                // alpha animations should cause the child to recreate its display list
17113                invalidate(true);
17114            }
17115        }
17116
17117        mRecreateDisplayList = false;
17118
17119        return more;
17120    }
17121
17122    /**
17123     * Manually render this view (and all of its children) to the given Canvas.
17124     * The view must have already done a full layout before this function is
17125     * called.  When implementing a view, implement
17126     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
17127     * If you do need to override this method, call the superclass version.
17128     *
17129     * @param canvas The Canvas to which the View is rendered.
17130     */
17131    @CallSuper
17132    public void draw(Canvas canvas) {
17133        final int privateFlags = mPrivateFlags;
17134        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
17135                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
17136        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
17137
17138        /*
17139         * Draw traversal performs several drawing steps which must be executed
17140         * in the appropriate order:
17141         *
17142         *      1. Draw the background
17143         *      2. If necessary, save the canvas' layers to prepare for fading
17144         *      3. Draw view's content
17145         *      4. Draw children
17146         *      5. If necessary, draw the fading edges and restore layers
17147         *      6. Draw decorations (scrollbars for instance)
17148         */
17149
17150        // Step 1, draw the background, if needed
17151        int saveCount;
17152
17153        if (!dirtyOpaque) {
17154            drawBackground(canvas);
17155        }
17156
17157        // skip step 2 & 5 if possible (common case)
17158        final int viewFlags = mViewFlags;
17159        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
17160        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
17161        if (!verticalEdges && !horizontalEdges) {
17162            // Step 3, draw the content
17163            if (!dirtyOpaque) onDraw(canvas);
17164
17165            // Step 4, draw the children
17166            dispatchDraw(canvas);
17167
17168            // Overlay is part of the content and draws beneath Foreground
17169            if (mOverlay != null && !mOverlay.isEmpty()) {
17170                mOverlay.getOverlayView().dispatchDraw(canvas);
17171            }
17172
17173            // Step 6, draw decorations (foreground, scrollbars)
17174            onDrawForeground(canvas);
17175
17176            // we're done...
17177            return;
17178        }
17179
17180        /*
17181         * Here we do the full fledged routine...
17182         * (this is an uncommon case where speed matters less,
17183         * this is why we repeat some of the tests that have been
17184         * done above)
17185         */
17186
17187        boolean drawTop = false;
17188        boolean drawBottom = false;
17189        boolean drawLeft = false;
17190        boolean drawRight = false;
17191
17192        float topFadeStrength = 0.0f;
17193        float bottomFadeStrength = 0.0f;
17194        float leftFadeStrength = 0.0f;
17195        float rightFadeStrength = 0.0f;
17196
17197        // Step 2, save the canvas' layers
17198        int paddingLeft = mPaddingLeft;
17199
17200        final boolean offsetRequired = isPaddingOffsetRequired();
17201        if (offsetRequired) {
17202            paddingLeft += getLeftPaddingOffset();
17203        }
17204
17205        int left = mScrollX + paddingLeft;
17206        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
17207        int top = mScrollY + getFadeTop(offsetRequired);
17208        int bottom = top + getFadeHeight(offsetRequired);
17209
17210        if (offsetRequired) {
17211            right += getRightPaddingOffset();
17212            bottom += getBottomPaddingOffset();
17213        }
17214
17215        final ScrollabilityCache scrollabilityCache = mScrollCache;
17216        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
17217        int length = (int) fadeHeight;
17218
17219        // clip the fade length if top and bottom fades overlap
17220        // overlapping fades produce odd-looking artifacts
17221        if (verticalEdges && (top + length > bottom - length)) {
17222            length = (bottom - top) / 2;
17223        }
17224
17225        // also clip horizontal fades if necessary
17226        if (horizontalEdges && (left + length > right - length)) {
17227            length = (right - left) / 2;
17228        }
17229
17230        if (verticalEdges) {
17231            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
17232            drawTop = topFadeStrength * fadeHeight > 1.0f;
17233            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
17234            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
17235        }
17236
17237        if (horizontalEdges) {
17238            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
17239            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
17240            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
17241            drawRight = rightFadeStrength * fadeHeight > 1.0f;
17242        }
17243
17244        saveCount = canvas.getSaveCount();
17245
17246        int solidColor = getSolidColor();
17247        if (solidColor == 0) {
17248            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
17249
17250            if (drawTop) {
17251                canvas.saveLayer(left, top, right, top + length, null, flags);
17252            }
17253
17254            if (drawBottom) {
17255                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
17256            }
17257
17258            if (drawLeft) {
17259                canvas.saveLayer(left, top, left + length, bottom, null, flags);
17260            }
17261
17262            if (drawRight) {
17263                canvas.saveLayer(right - length, top, right, bottom, null, flags);
17264            }
17265        } else {
17266            scrollabilityCache.setFadeColor(solidColor);
17267        }
17268
17269        // Step 3, draw the content
17270        if (!dirtyOpaque) onDraw(canvas);
17271
17272        // Step 4, draw the children
17273        dispatchDraw(canvas);
17274
17275        // Step 5, draw the fade effect and restore layers
17276        final Paint p = scrollabilityCache.paint;
17277        final Matrix matrix = scrollabilityCache.matrix;
17278        final Shader fade = scrollabilityCache.shader;
17279
17280        if (drawTop) {
17281            matrix.setScale(1, fadeHeight * topFadeStrength);
17282            matrix.postTranslate(left, top);
17283            fade.setLocalMatrix(matrix);
17284            p.setShader(fade);
17285            canvas.drawRect(left, top, right, top + length, p);
17286        }
17287
17288        if (drawBottom) {
17289            matrix.setScale(1, fadeHeight * bottomFadeStrength);
17290            matrix.postRotate(180);
17291            matrix.postTranslate(left, bottom);
17292            fade.setLocalMatrix(matrix);
17293            p.setShader(fade);
17294            canvas.drawRect(left, bottom - length, right, bottom, p);
17295        }
17296
17297        if (drawLeft) {
17298            matrix.setScale(1, fadeHeight * leftFadeStrength);
17299            matrix.postRotate(-90);
17300            matrix.postTranslate(left, top);
17301            fade.setLocalMatrix(matrix);
17302            p.setShader(fade);
17303            canvas.drawRect(left, top, left + length, bottom, p);
17304        }
17305
17306        if (drawRight) {
17307            matrix.setScale(1, fadeHeight * rightFadeStrength);
17308            matrix.postRotate(90);
17309            matrix.postTranslate(right, top);
17310            fade.setLocalMatrix(matrix);
17311            p.setShader(fade);
17312            canvas.drawRect(right - length, top, right, bottom, p);
17313        }
17314
17315        canvas.restoreToCount(saveCount);
17316
17317        // Overlay is part of the content and draws beneath Foreground
17318        if (mOverlay != null && !mOverlay.isEmpty()) {
17319            mOverlay.getOverlayView().dispatchDraw(canvas);
17320        }
17321
17322        // Step 6, draw decorations (foreground, scrollbars)
17323        onDrawForeground(canvas);
17324    }
17325
17326    /**
17327     * Draws the background onto the specified canvas.
17328     *
17329     * @param canvas Canvas on which to draw the background
17330     */
17331    private void drawBackground(Canvas canvas) {
17332        final Drawable background = mBackground;
17333        if (background == null) {
17334            return;
17335        }
17336
17337        setBackgroundBounds();
17338
17339        // Attempt to use a display list if requested.
17340        if (canvas.isHardwareAccelerated() && mAttachInfo != null
17341                && mAttachInfo.mThreadedRenderer != null) {
17342            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
17343
17344            final RenderNode renderNode = mBackgroundRenderNode;
17345            if (renderNode != null && renderNode.isValid()) {
17346                setBackgroundRenderNodeProperties(renderNode);
17347                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17348                return;
17349            }
17350        }
17351
17352        final int scrollX = mScrollX;
17353        final int scrollY = mScrollY;
17354        if ((scrollX | scrollY) == 0) {
17355            background.draw(canvas);
17356        } else {
17357            canvas.translate(scrollX, scrollY);
17358            background.draw(canvas);
17359            canvas.translate(-scrollX, -scrollY);
17360        }
17361    }
17362
17363    /**
17364     * Sets the correct background bounds and rebuilds the outline, if needed.
17365     * <p/>
17366     * This is called by LayoutLib.
17367     */
17368    void setBackgroundBounds() {
17369        if (mBackgroundSizeChanged && mBackground != null) {
17370            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
17371            mBackgroundSizeChanged = false;
17372            rebuildOutline();
17373        }
17374    }
17375
17376    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
17377        renderNode.setTranslationX(mScrollX);
17378        renderNode.setTranslationY(mScrollY);
17379    }
17380
17381    /**
17382     * Creates a new display list or updates the existing display list for the
17383     * specified Drawable.
17384     *
17385     * @param drawable Drawable for which to create a display list
17386     * @param renderNode Existing RenderNode, or {@code null}
17387     * @return A valid display list for the specified drawable
17388     */
17389    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
17390        if (renderNode == null) {
17391            renderNode = RenderNode.create(drawable.getClass().getName(), this);
17392        }
17393
17394        final Rect bounds = drawable.getBounds();
17395        final int width = bounds.width();
17396        final int height = bounds.height();
17397        final DisplayListCanvas canvas = renderNode.start(width, height);
17398
17399        // Reverse left/top translation done by drawable canvas, which will
17400        // instead be applied by rendernode's LTRB bounds below. This way, the
17401        // drawable's bounds match with its rendernode bounds and its content
17402        // will lie within those bounds in the rendernode tree.
17403        canvas.translate(-bounds.left, -bounds.top);
17404
17405        try {
17406            drawable.draw(canvas);
17407        } finally {
17408            renderNode.end(canvas);
17409        }
17410
17411        // Set up drawable properties that are view-independent.
17412        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
17413        renderNode.setProjectBackwards(drawable.isProjected());
17414        renderNode.setProjectionReceiver(true);
17415        renderNode.setClipToBounds(false);
17416        return renderNode;
17417    }
17418
17419    /**
17420     * Returns the overlay for this view, creating it if it does not yet exist.
17421     * Adding drawables to the overlay will cause them to be displayed whenever
17422     * the view itself is redrawn. Objects in the overlay should be actively
17423     * managed: remove them when they should not be displayed anymore. The
17424     * overlay will always have the same size as its host view.
17425     *
17426     * <p>Note: Overlays do not currently work correctly with {@link
17427     * SurfaceView} or {@link TextureView}; contents in overlays for these
17428     * types of views may not display correctly.</p>
17429     *
17430     * @return The ViewOverlay object for this view.
17431     * @see ViewOverlay
17432     */
17433    public ViewOverlay getOverlay() {
17434        if (mOverlay == null) {
17435            mOverlay = new ViewOverlay(mContext, this);
17436        }
17437        return mOverlay;
17438    }
17439
17440    /**
17441     * Override this if your view is known to always be drawn on top of a solid color background,
17442     * and needs to draw fading edges. Returning a non-zero color enables the view system to
17443     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
17444     * should be set to 0xFF.
17445     *
17446     * @see #setVerticalFadingEdgeEnabled(boolean)
17447     * @see #setHorizontalFadingEdgeEnabled(boolean)
17448     *
17449     * @return The known solid color background for this view, or 0 if the color may vary
17450     */
17451    @ViewDebug.ExportedProperty(category = "drawing")
17452    @ColorInt
17453    public int getSolidColor() {
17454        return 0;
17455    }
17456
17457    /**
17458     * Build a human readable string representation of the specified view flags.
17459     *
17460     * @param flags the view flags to convert to a string
17461     * @return a String representing the supplied flags
17462     */
17463    private static String printFlags(int flags) {
17464        String output = "";
17465        int numFlags = 0;
17466        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
17467            output += "TAKES_FOCUS";
17468            numFlags++;
17469        }
17470
17471        switch (flags & VISIBILITY_MASK) {
17472        case INVISIBLE:
17473            if (numFlags > 0) {
17474                output += " ";
17475            }
17476            output += "INVISIBLE";
17477            // USELESS HERE numFlags++;
17478            break;
17479        case GONE:
17480            if (numFlags > 0) {
17481                output += " ";
17482            }
17483            output += "GONE";
17484            // USELESS HERE numFlags++;
17485            break;
17486        default:
17487            break;
17488        }
17489        return output;
17490    }
17491
17492    /**
17493     * Build a human readable string representation of the specified private
17494     * view flags.
17495     *
17496     * @param privateFlags the private view flags to convert to a string
17497     * @return a String representing the supplied flags
17498     */
17499    private static String printPrivateFlags(int privateFlags) {
17500        String output = "";
17501        int numFlags = 0;
17502
17503        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
17504            output += "WANTS_FOCUS";
17505            numFlags++;
17506        }
17507
17508        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
17509            if (numFlags > 0) {
17510                output += " ";
17511            }
17512            output += "FOCUSED";
17513            numFlags++;
17514        }
17515
17516        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
17517            if (numFlags > 0) {
17518                output += " ";
17519            }
17520            output += "SELECTED";
17521            numFlags++;
17522        }
17523
17524        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
17525            if (numFlags > 0) {
17526                output += " ";
17527            }
17528            output += "IS_ROOT_NAMESPACE";
17529            numFlags++;
17530        }
17531
17532        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
17533            if (numFlags > 0) {
17534                output += " ";
17535            }
17536            output += "HAS_BOUNDS";
17537            numFlags++;
17538        }
17539
17540        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
17541            if (numFlags > 0) {
17542                output += " ";
17543            }
17544            output += "DRAWN";
17545            // USELESS HERE numFlags++;
17546        }
17547        return output;
17548    }
17549
17550    /**
17551     * <p>Indicates whether or not this view's layout will be requested during
17552     * the next hierarchy layout pass.</p>
17553     *
17554     * @return true if the layout will be forced during next layout pass
17555     */
17556    public boolean isLayoutRequested() {
17557        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
17558    }
17559
17560    /**
17561     * Return true if o is a ViewGroup that is laying out using optical bounds.
17562     * @hide
17563     */
17564    public static boolean isLayoutModeOptical(Object o) {
17565        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
17566    }
17567
17568    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
17569        Insets parentInsets = mParent instanceof View ?
17570                ((View) mParent).getOpticalInsets() : Insets.NONE;
17571        Insets childInsets = getOpticalInsets();
17572        return setFrame(
17573                left   + parentInsets.left - childInsets.left,
17574                top    + parentInsets.top  - childInsets.top,
17575                right  + parentInsets.left + childInsets.right,
17576                bottom + parentInsets.top  + childInsets.bottom);
17577    }
17578
17579    /**
17580     * Assign a size and position to a view and all of its
17581     * descendants
17582     *
17583     * <p>This is the second phase of the layout mechanism.
17584     * (The first is measuring). In this phase, each parent calls
17585     * layout on all of its children to position them.
17586     * This is typically done using the child measurements
17587     * that were stored in the measure pass().</p>
17588     *
17589     * <p>Derived classes should not override this method.
17590     * Derived classes with children should override
17591     * onLayout. In that method, they should
17592     * call layout on each of their children.</p>
17593     *
17594     * @param l Left position, relative to parent
17595     * @param t Top position, relative to parent
17596     * @param r Right position, relative to parent
17597     * @param b Bottom position, relative to parent
17598     */
17599    @SuppressWarnings({"unchecked"})
17600    public void layout(int l, int t, int r, int b) {
17601        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
17602            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
17603            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17604        }
17605
17606        int oldL = mLeft;
17607        int oldT = mTop;
17608        int oldB = mBottom;
17609        int oldR = mRight;
17610
17611        boolean changed = isLayoutModeOptical(mParent) ?
17612                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
17613
17614        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
17615            onLayout(changed, l, t, r, b);
17616
17617            if (shouldDrawRoundScrollbar()) {
17618                if(mRoundScrollbarRenderer == null) {
17619                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
17620                }
17621            } else {
17622                mRoundScrollbarRenderer = null;
17623            }
17624
17625            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
17626
17627            ListenerInfo li = mListenerInfo;
17628            if (li != null && li.mOnLayoutChangeListeners != null) {
17629                ArrayList<OnLayoutChangeListener> listenersCopy =
17630                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
17631                int numListeners = listenersCopy.size();
17632                for (int i = 0; i < numListeners; ++i) {
17633                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
17634                }
17635            }
17636        }
17637
17638        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
17639        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
17640    }
17641
17642    /**
17643     * Called from layout when this view should
17644     * assign a size and position to each of its children.
17645     *
17646     * Derived classes with children should override
17647     * this method and call layout on each of
17648     * their children.
17649     * @param changed This is a new size or position for this view
17650     * @param left Left position, relative to parent
17651     * @param top Top position, relative to parent
17652     * @param right Right position, relative to parent
17653     * @param bottom Bottom position, relative to parent
17654     */
17655    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
17656    }
17657
17658    /**
17659     * Assign a size and position to this view.
17660     *
17661     * This is called from layout.
17662     *
17663     * @param left Left position, relative to parent
17664     * @param top Top position, relative to parent
17665     * @param right Right position, relative to parent
17666     * @param bottom Bottom position, relative to parent
17667     * @return true if the new size and position are different than the
17668     *         previous ones
17669     * {@hide}
17670     */
17671    protected boolean setFrame(int left, int top, int right, int bottom) {
17672        boolean changed = false;
17673
17674        if (DBG) {
17675            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
17676                    + right + "," + bottom + ")");
17677        }
17678
17679        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
17680            changed = true;
17681
17682            // Remember our drawn bit
17683            int drawn = mPrivateFlags & PFLAG_DRAWN;
17684
17685            int oldWidth = mRight - mLeft;
17686            int oldHeight = mBottom - mTop;
17687            int newWidth = right - left;
17688            int newHeight = bottom - top;
17689            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
17690
17691            // Invalidate our old position
17692            invalidate(sizeChanged);
17693
17694            mLeft = left;
17695            mTop = top;
17696            mRight = right;
17697            mBottom = bottom;
17698            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
17699
17700            mPrivateFlags |= PFLAG_HAS_BOUNDS;
17701
17702
17703            if (sizeChanged) {
17704                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
17705            }
17706
17707            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
17708                // If we are visible, force the DRAWN bit to on so that
17709                // this invalidate will go through (at least to our parent).
17710                // This is because someone may have invalidated this view
17711                // before this call to setFrame came in, thereby clearing
17712                // the DRAWN bit.
17713                mPrivateFlags |= PFLAG_DRAWN;
17714                invalidate(sizeChanged);
17715                // parent display list may need to be recreated based on a change in the bounds
17716                // of any child
17717                invalidateParentCaches();
17718            }
17719
17720            // Reset drawn bit to original value (invalidate turns it off)
17721            mPrivateFlags |= drawn;
17722
17723            mBackgroundSizeChanged = true;
17724            if (mForegroundInfo != null) {
17725                mForegroundInfo.mBoundsChanged = true;
17726            }
17727
17728            notifySubtreeAccessibilityStateChangedIfNeeded();
17729        }
17730        return changed;
17731    }
17732
17733    /**
17734     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
17735     * @hide
17736     */
17737    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
17738        setFrame(left, top, right, bottom);
17739    }
17740
17741    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
17742        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
17743        if (mOverlay != null) {
17744            mOverlay.getOverlayView().setRight(newWidth);
17745            mOverlay.getOverlayView().setBottom(newHeight);
17746        }
17747        rebuildOutline();
17748    }
17749
17750    /**
17751     * Finalize inflating a view from XML.  This is called as the last phase
17752     * of inflation, after all child views have been added.
17753     *
17754     * <p>Even if the subclass overrides onFinishInflate, they should always be
17755     * sure to call the super method, so that we get called.
17756     */
17757    @CallSuper
17758    protected void onFinishInflate() {
17759    }
17760
17761    /**
17762     * Returns the resources associated with this view.
17763     *
17764     * @return Resources object.
17765     */
17766    public Resources getResources() {
17767        return mResources;
17768    }
17769
17770    /**
17771     * Invalidates the specified Drawable.
17772     *
17773     * @param drawable the drawable to invalidate
17774     */
17775    @Override
17776    public void invalidateDrawable(@NonNull Drawable drawable) {
17777        if (verifyDrawable(drawable)) {
17778            final Rect dirty = drawable.getDirtyBounds();
17779            final int scrollX = mScrollX;
17780            final int scrollY = mScrollY;
17781
17782            invalidate(dirty.left + scrollX, dirty.top + scrollY,
17783                    dirty.right + scrollX, dirty.bottom + scrollY);
17784            rebuildOutline();
17785        }
17786    }
17787
17788    /**
17789     * Schedules an action on a drawable to occur at a specified time.
17790     *
17791     * @param who the recipient of the action
17792     * @param what the action to run on the drawable
17793     * @param when the time at which the action must occur. Uses the
17794     *        {@link SystemClock#uptimeMillis} timebase.
17795     */
17796    @Override
17797    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
17798        if (verifyDrawable(who) && what != null) {
17799            final long delay = when - SystemClock.uptimeMillis();
17800            if (mAttachInfo != null) {
17801                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17802                        Choreographer.CALLBACK_ANIMATION, what, who,
17803                        Choreographer.subtractFrameDelay(delay));
17804            } else {
17805                // Postpone the runnable until we know
17806                // on which thread it needs to run.
17807                getRunQueue().postDelayed(what, delay);
17808            }
17809        }
17810    }
17811
17812    /**
17813     * Cancels a scheduled action on a drawable.
17814     *
17815     * @param who the recipient of the action
17816     * @param what the action to cancel
17817     */
17818    @Override
17819    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
17820        if (verifyDrawable(who) && what != null) {
17821            if (mAttachInfo != null) {
17822                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17823                        Choreographer.CALLBACK_ANIMATION, what, who);
17824            }
17825            getRunQueue().removeCallbacks(what);
17826        }
17827    }
17828
17829    /**
17830     * Unschedule any events associated with the given Drawable.  This can be
17831     * used when selecting a new Drawable into a view, so that the previous
17832     * one is completely unscheduled.
17833     *
17834     * @param who The Drawable to unschedule.
17835     *
17836     * @see #drawableStateChanged
17837     */
17838    public void unscheduleDrawable(Drawable who) {
17839        if (mAttachInfo != null && who != null) {
17840            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17841                    Choreographer.CALLBACK_ANIMATION, null, who);
17842        }
17843    }
17844
17845    /**
17846     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
17847     * that the View directionality can and will be resolved before its Drawables.
17848     *
17849     * Will call {@link View#onResolveDrawables} when resolution is done.
17850     *
17851     * @hide
17852     */
17853    protected void resolveDrawables() {
17854        // Drawables resolution may need to happen before resolving the layout direction (which is
17855        // done only during the measure() call).
17856        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
17857        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
17858        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
17859        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
17860        // direction to be resolved as its resolved value will be the same as its raw value.
17861        if (!isLayoutDirectionResolved() &&
17862                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17863            return;
17864        }
17865
17866        final int layoutDirection = isLayoutDirectionResolved() ?
17867                getLayoutDirection() : getRawLayoutDirection();
17868
17869        if (mBackground != null) {
17870            mBackground.setLayoutDirection(layoutDirection);
17871        }
17872        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17873            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17874        }
17875        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17876        onResolveDrawables(layoutDirection);
17877    }
17878
17879    boolean areDrawablesResolved() {
17880        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17881    }
17882
17883    /**
17884     * Called when layout direction has been resolved.
17885     *
17886     * The default implementation does nothing.
17887     *
17888     * @param layoutDirection The resolved layout direction.
17889     *
17890     * @see #LAYOUT_DIRECTION_LTR
17891     * @see #LAYOUT_DIRECTION_RTL
17892     *
17893     * @hide
17894     */
17895    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17896    }
17897
17898    /**
17899     * @hide
17900     */
17901    protected void resetResolvedDrawables() {
17902        resetResolvedDrawablesInternal();
17903    }
17904
17905    void resetResolvedDrawablesInternal() {
17906        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17907    }
17908
17909    /**
17910     * If your view subclass is displaying its own Drawable objects, it should
17911     * override this function and return true for any Drawable it is
17912     * displaying.  This allows animations for those drawables to be
17913     * scheduled.
17914     *
17915     * <p>Be sure to call through to the super class when overriding this
17916     * function.
17917     *
17918     * @param who The Drawable to verify.  Return true if it is one you are
17919     *            displaying, else return the result of calling through to the
17920     *            super class.
17921     *
17922     * @return boolean If true than the Drawable is being displayed in the
17923     *         view; else false and it is not allowed to animate.
17924     *
17925     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17926     * @see #drawableStateChanged()
17927     */
17928    @CallSuper
17929    protected boolean verifyDrawable(@NonNull Drawable who) {
17930        // Avoid verifying the scroll bar drawable so that we don't end up in
17931        // an invalidation loop. This effectively prevents the scroll bar
17932        // drawable from triggering invalidations and scheduling runnables.
17933        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17934    }
17935
17936    /**
17937     * This function is called whenever the state of the view changes in such
17938     * a way that it impacts the state of drawables being shown.
17939     * <p>
17940     * If the View has a StateListAnimator, it will also be called to run necessary state
17941     * change animations.
17942     * <p>
17943     * Be sure to call through to the superclass when overriding this function.
17944     *
17945     * @see Drawable#setState(int[])
17946     */
17947    @CallSuper
17948    protected void drawableStateChanged() {
17949        final int[] state = getDrawableState();
17950        boolean changed = false;
17951
17952        final Drawable bg = mBackground;
17953        if (bg != null && bg.isStateful()) {
17954            changed |= bg.setState(state);
17955        }
17956
17957        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17958        if (fg != null && fg.isStateful()) {
17959            changed |= fg.setState(state);
17960        }
17961
17962        if (mScrollCache != null) {
17963            final Drawable scrollBar = mScrollCache.scrollBar;
17964            if (scrollBar != null && scrollBar.isStateful()) {
17965                changed |= scrollBar.setState(state)
17966                        && mScrollCache.state != ScrollabilityCache.OFF;
17967            }
17968        }
17969
17970        if (mStateListAnimator != null) {
17971            mStateListAnimator.setState(state);
17972        }
17973
17974        if (changed) {
17975            invalidate();
17976        }
17977    }
17978
17979    /**
17980     * This function is called whenever the view hotspot changes and needs to
17981     * be propagated to drawables or child views managed by the view.
17982     * <p>
17983     * Dispatching to child views is handled by
17984     * {@link #dispatchDrawableHotspotChanged(float, float)}.
17985     * <p>
17986     * Be sure to call through to the superclass when overriding this function.
17987     *
17988     * @param x hotspot x coordinate
17989     * @param y hotspot y coordinate
17990     */
17991    @CallSuper
17992    public void drawableHotspotChanged(float x, float y) {
17993        if (mBackground != null) {
17994            mBackground.setHotspot(x, y);
17995        }
17996        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17997            mForegroundInfo.mDrawable.setHotspot(x, y);
17998        }
17999
18000        dispatchDrawableHotspotChanged(x, y);
18001    }
18002
18003    /**
18004     * Dispatches drawableHotspotChanged to all of this View's children.
18005     *
18006     * @param x hotspot x coordinate
18007     * @param y hotspot y coordinate
18008     * @see #drawableHotspotChanged(float, float)
18009     */
18010    public void dispatchDrawableHotspotChanged(float x, float y) {
18011    }
18012
18013    /**
18014     * Call this to force a view to update its drawable state. This will cause
18015     * drawableStateChanged to be called on this view. Views that are interested
18016     * in the new state should call getDrawableState.
18017     *
18018     * @see #drawableStateChanged
18019     * @see #getDrawableState
18020     */
18021    public void refreshDrawableState() {
18022        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
18023        drawableStateChanged();
18024
18025        ViewParent parent = mParent;
18026        if (parent != null) {
18027            parent.childDrawableStateChanged(this);
18028        }
18029    }
18030
18031    /**
18032     * Return an array of resource IDs of the drawable states representing the
18033     * current state of the view.
18034     *
18035     * @return The current drawable state
18036     *
18037     * @see Drawable#setState(int[])
18038     * @see #drawableStateChanged()
18039     * @see #onCreateDrawableState(int)
18040     */
18041    public final int[] getDrawableState() {
18042        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
18043            return mDrawableState;
18044        } else {
18045            mDrawableState = onCreateDrawableState(0);
18046            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
18047            return mDrawableState;
18048        }
18049    }
18050
18051    /**
18052     * Generate the new {@link android.graphics.drawable.Drawable} state for
18053     * this view. This is called by the view
18054     * system when the cached Drawable state is determined to be invalid.  To
18055     * retrieve the current state, you should use {@link #getDrawableState}.
18056     *
18057     * @param extraSpace if non-zero, this is the number of extra entries you
18058     * would like in the returned array in which you can place your own
18059     * states.
18060     *
18061     * @return Returns an array holding the current {@link Drawable} state of
18062     * the view.
18063     *
18064     * @see #mergeDrawableStates(int[], int[])
18065     */
18066    protected int[] onCreateDrawableState(int extraSpace) {
18067        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
18068                mParent instanceof View) {
18069            return ((View) mParent).onCreateDrawableState(extraSpace);
18070        }
18071
18072        int[] drawableState;
18073
18074        int privateFlags = mPrivateFlags;
18075
18076        int viewStateIndex = 0;
18077        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
18078        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
18079        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
18080        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
18081        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
18082        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
18083        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
18084                ThreadedRenderer.isAvailable()) {
18085            // This is set if HW acceleration is requested, even if the current
18086            // process doesn't allow it.  This is just to allow app preview
18087            // windows to better match their app.
18088            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
18089        }
18090        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
18091
18092        final int privateFlags2 = mPrivateFlags2;
18093        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
18094            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
18095        }
18096        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
18097            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
18098        }
18099
18100        drawableState = StateSet.get(viewStateIndex);
18101
18102        //noinspection ConstantIfStatement
18103        if (false) {
18104            Log.i("View", "drawableStateIndex=" + viewStateIndex);
18105            Log.i("View", toString()
18106                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
18107                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
18108                    + " fo=" + hasFocus()
18109                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
18110                    + " wf=" + hasWindowFocus()
18111                    + ": " + Arrays.toString(drawableState));
18112        }
18113
18114        if (extraSpace == 0) {
18115            return drawableState;
18116        }
18117
18118        final int[] fullState;
18119        if (drawableState != null) {
18120            fullState = new int[drawableState.length + extraSpace];
18121            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
18122        } else {
18123            fullState = new int[extraSpace];
18124        }
18125
18126        return fullState;
18127    }
18128
18129    /**
18130     * Merge your own state values in <var>additionalState</var> into the base
18131     * state values <var>baseState</var> that were returned by
18132     * {@link #onCreateDrawableState(int)}.
18133     *
18134     * @param baseState The base state values returned by
18135     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
18136     * own additional state values.
18137     *
18138     * @param additionalState The additional state values you would like
18139     * added to <var>baseState</var>; this array is not modified.
18140     *
18141     * @return As a convenience, the <var>baseState</var> array you originally
18142     * passed into the function is returned.
18143     *
18144     * @see #onCreateDrawableState(int)
18145     */
18146    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
18147        final int N = baseState.length;
18148        int i = N - 1;
18149        while (i >= 0 && baseState[i] == 0) {
18150            i--;
18151        }
18152        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
18153        return baseState;
18154    }
18155
18156    /**
18157     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
18158     * on all Drawable objects associated with this view.
18159     * <p>
18160     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
18161     * attached to this view.
18162     */
18163    @CallSuper
18164    public void jumpDrawablesToCurrentState() {
18165        if (mBackground != null) {
18166            mBackground.jumpToCurrentState();
18167        }
18168        if (mStateListAnimator != null) {
18169            mStateListAnimator.jumpToCurrentState();
18170        }
18171        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18172            mForegroundInfo.mDrawable.jumpToCurrentState();
18173        }
18174    }
18175
18176    /**
18177     * Sets the background color for this view.
18178     * @param color the color of the background
18179     */
18180    @RemotableViewMethod
18181    public void setBackgroundColor(@ColorInt int color) {
18182        if (mBackground instanceof ColorDrawable) {
18183            ((ColorDrawable) mBackground.mutate()).setColor(color);
18184            computeOpaqueFlags();
18185            mBackgroundResource = 0;
18186        } else {
18187            setBackground(new ColorDrawable(color));
18188        }
18189    }
18190
18191    /**
18192     * Set the background to a given resource. The resource should refer to
18193     * a Drawable object or 0 to remove the background.
18194     * @param resid The identifier of the resource.
18195     *
18196     * @attr ref android.R.styleable#View_background
18197     */
18198    @RemotableViewMethod
18199    public void setBackgroundResource(@DrawableRes int resid) {
18200        if (resid != 0 && resid == mBackgroundResource) {
18201            return;
18202        }
18203
18204        Drawable d = null;
18205        if (resid != 0) {
18206            d = mContext.getDrawable(resid);
18207        }
18208        setBackground(d);
18209
18210        mBackgroundResource = resid;
18211    }
18212
18213    /**
18214     * Set the background to a given Drawable, or remove the background. If the
18215     * background has padding, this View's padding is set to the background's
18216     * padding. However, when a background is removed, this View's padding isn't
18217     * touched. If setting the padding is desired, please use
18218     * {@link #setPadding(int, int, int, int)}.
18219     *
18220     * @param background The Drawable to use as the background, or null to remove the
18221     *        background
18222     */
18223    public void setBackground(Drawable background) {
18224        //noinspection deprecation
18225        setBackgroundDrawable(background);
18226    }
18227
18228    /**
18229     * @deprecated use {@link #setBackground(Drawable)} instead
18230     */
18231    @Deprecated
18232    public void setBackgroundDrawable(Drawable background) {
18233        computeOpaqueFlags();
18234
18235        if (background == mBackground) {
18236            return;
18237        }
18238
18239        boolean requestLayout = false;
18240
18241        mBackgroundResource = 0;
18242
18243        /*
18244         * Regardless of whether we're setting a new background or not, we want
18245         * to clear the previous drawable. setVisible first while we still have the callback set.
18246         */
18247        if (mBackground != null) {
18248            if (isAttachedToWindow()) {
18249                mBackground.setVisible(false, false);
18250            }
18251            mBackground.setCallback(null);
18252            unscheduleDrawable(mBackground);
18253        }
18254
18255        if (background != null) {
18256            Rect padding = sThreadLocal.get();
18257            if (padding == null) {
18258                padding = new Rect();
18259                sThreadLocal.set(padding);
18260            }
18261            resetResolvedDrawablesInternal();
18262            background.setLayoutDirection(getLayoutDirection());
18263            if (background.getPadding(padding)) {
18264                resetResolvedPaddingInternal();
18265                switch (background.getLayoutDirection()) {
18266                    case LAYOUT_DIRECTION_RTL:
18267                        mUserPaddingLeftInitial = padding.right;
18268                        mUserPaddingRightInitial = padding.left;
18269                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
18270                        break;
18271                    case LAYOUT_DIRECTION_LTR:
18272                    default:
18273                        mUserPaddingLeftInitial = padding.left;
18274                        mUserPaddingRightInitial = padding.right;
18275                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
18276                }
18277                mLeftPaddingDefined = false;
18278                mRightPaddingDefined = false;
18279            }
18280
18281            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
18282            // if it has a different minimum size, we should layout again
18283            if (mBackground == null
18284                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
18285                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
18286                requestLayout = true;
18287            }
18288
18289            // Set mBackground before we set this as the callback and start making other
18290            // background drawable state change calls. In particular, the setVisible call below
18291            // can result in drawables attempting to start animations or otherwise invalidate,
18292            // which requires the view set as the callback (us) to recognize the drawable as
18293            // belonging to it as per verifyDrawable.
18294            mBackground = background;
18295            if (background.isStateful()) {
18296                background.setState(getDrawableState());
18297            }
18298            if (isAttachedToWindow()) {
18299                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18300            }
18301
18302            applyBackgroundTint();
18303
18304            // Set callback last, since the view may still be initializing.
18305            background.setCallback(this);
18306
18307            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18308                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18309                requestLayout = true;
18310            }
18311        } else {
18312            /* Remove the background */
18313            mBackground = null;
18314            if ((mViewFlags & WILL_NOT_DRAW) != 0
18315                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
18316                mPrivateFlags |= PFLAG_SKIP_DRAW;
18317            }
18318
18319            /*
18320             * When the background is set, we try to apply its padding to this
18321             * View. When the background is removed, we don't touch this View's
18322             * padding. This is noted in the Javadocs. Hence, we don't need to
18323             * requestLayout(), the invalidate() below is sufficient.
18324             */
18325
18326            // The old background's minimum size could have affected this
18327            // View's layout, so let's requestLayout
18328            requestLayout = true;
18329        }
18330
18331        computeOpaqueFlags();
18332
18333        if (requestLayout) {
18334            requestLayout();
18335        }
18336
18337        mBackgroundSizeChanged = true;
18338        invalidate(true);
18339        invalidateOutline();
18340    }
18341
18342    /**
18343     * Gets the background drawable
18344     *
18345     * @return The drawable used as the background for this view, if any.
18346     *
18347     * @see #setBackground(Drawable)
18348     *
18349     * @attr ref android.R.styleable#View_background
18350     */
18351    public Drawable getBackground() {
18352        return mBackground;
18353    }
18354
18355    /**
18356     * Applies a tint to the background drawable. Does not modify the current tint
18357     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18358     * <p>
18359     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
18360     * mutate the drawable and apply the specified tint and tint mode using
18361     * {@link Drawable#setTintList(ColorStateList)}.
18362     *
18363     * @param tint the tint to apply, may be {@code null} to clear tint
18364     *
18365     * @attr ref android.R.styleable#View_backgroundTint
18366     * @see #getBackgroundTintList()
18367     * @see Drawable#setTintList(ColorStateList)
18368     */
18369    public void setBackgroundTintList(@Nullable ColorStateList tint) {
18370        if (mBackgroundTint == null) {
18371            mBackgroundTint = new TintInfo();
18372        }
18373        mBackgroundTint.mTintList = tint;
18374        mBackgroundTint.mHasTintList = true;
18375
18376        applyBackgroundTint();
18377    }
18378
18379    /**
18380     * Return the tint applied to the background drawable, if specified.
18381     *
18382     * @return the tint applied to the background drawable
18383     * @attr ref android.R.styleable#View_backgroundTint
18384     * @see #setBackgroundTintList(ColorStateList)
18385     */
18386    @Nullable
18387    public ColorStateList getBackgroundTintList() {
18388        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
18389    }
18390
18391    /**
18392     * Specifies the blending mode used to apply the tint specified by
18393     * {@link #setBackgroundTintList(ColorStateList)}} to the background
18394     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18395     *
18396     * @param tintMode the blending mode used to apply the tint, may be
18397     *                 {@code null} to clear tint
18398     * @attr ref android.R.styleable#View_backgroundTintMode
18399     * @see #getBackgroundTintMode()
18400     * @see Drawable#setTintMode(PorterDuff.Mode)
18401     */
18402    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18403        if (mBackgroundTint == null) {
18404            mBackgroundTint = new TintInfo();
18405        }
18406        mBackgroundTint.mTintMode = tintMode;
18407        mBackgroundTint.mHasTintMode = true;
18408
18409        applyBackgroundTint();
18410    }
18411
18412    /**
18413     * Return the blending mode used to apply the tint to the background
18414     * drawable, if specified.
18415     *
18416     * @return the blending mode used to apply the tint to the background
18417     *         drawable
18418     * @attr ref android.R.styleable#View_backgroundTintMode
18419     * @see #setBackgroundTintMode(PorterDuff.Mode)
18420     */
18421    @Nullable
18422    public PorterDuff.Mode getBackgroundTintMode() {
18423        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
18424    }
18425
18426    private void applyBackgroundTint() {
18427        if (mBackground != null && mBackgroundTint != null) {
18428            final TintInfo tintInfo = mBackgroundTint;
18429            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18430                mBackground = mBackground.mutate();
18431
18432                if (tintInfo.mHasTintList) {
18433                    mBackground.setTintList(tintInfo.mTintList);
18434                }
18435
18436                if (tintInfo.mHasTintMode) {
18437                    mBackground.setTintMode(tintInfo.mTintMode);
18438                }
18439
18440                // The drawable (or one of its children) may not have been
18441                // stateful before applying the tint, so let's try again.
18442                if (mBackground.isStateful()) {
18443                    mBackground.setState(getDrawableState());
18444                }
18445            }
18446        }
18447    }
18448
18449    /**
18450     * Returns the drawable used as the foreground of this View. The
18451     * foreground drawable, if non-null, is always drawn on top of the view's content.
18452     *
18453     * @return a Drawable or null if no foreground was set
18454     *
18455     * @see #onDrawForeground(Canvas)
18456     */
18457    public Drawable getForeground() {
18458        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18459    }
18460
18461    /**
18462     * Supply a Drawable that is to be rendered on top of all of the content in the view.
18463     *
18464     * @param foreground the Drawable to be drawn on top of the children
18465     *
18466     * @attr ref android.R.styleable#View_foreground
18467     */
18468    public void setForeground(Drawable foreground) {
18469        if (mForegroundInfo == null) {
18470            if (foreground == null) {
18471                // Nothing to do.
18472                return;
18473            }
18474            mForegroundInfo = new ForegroundInfo();
18475        }
18476
18477        if (foreground == mForegroundInfo.mDrawable) {
18478            // Nothing to do
18479            return;
18480        }
18481
18482        if (mForegroundInfo.mDrawable != null) {
18483            if (isAttachedToWindow()) {
18484                mForegroundInfo.mDrawable.setVisible(false, false);
18485            }
18486            mForegroundInfo.mDrawable.setCallback(null);
18487            unscheduleDrawable(mForegroundInfo.mDrawable);
18488        }
18489
18490        mForegroundInfo.mDrawable = foreground;
18491        mForegroundInfo.mBoundsChanged = true;
18492        if (foreground != null) {
18493            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18494                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18495            }
18496            foreground.setLayoutDirection(getLayoutDirection());
18497            if (foreground.isStateful()) {
18498                foreground.setState(getDrawableState());
18499            }
18500            applyForegroundTint();
18501            if (isAttachedToWindow()) {
18502                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18503            }
18504            // Set callback last, since the view may still be initializing.
18505            foreground.setCallback(this);
18506        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
18507            mPrivateFlags |= PFLAG_SKIP_DRAW;
18508        }
18509        requestLayout();
18510        invalidate();
18511    }
18512
18513    /**
18514     * Magic bit used to support features of framework-internal window decor implementation details.
18515     * This used to live exclusively in FrameLayout.
18516     *
18517     * @return true if the foreground should draw inside the padding region or false
18518     *         if it should draw inset by the view's padding
18519     * @hide internal use only; only used by FrameLayout and internal screen layouts.
18520     */
18521    public boolean isForegroundInsidePadding() {
18522        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
18523    }
18524
18525    /**
18526     * Describes how the foreground is positioned.
18527     *
18528     * @return foreground gravity.
18529     *
18530     * @see #setForegroundGravity(int)
18531     *
18532     * @attr ref android.R.styleable#View_foregroundGravity
18533     */
18534    public int getForegroundGravity() {
18535        return mForegroundInfo != null ? mForegroundInfo.mGravity
18536                : Gravity.START | Gravity.TOP;
18537    }
18538
18539    /**
18540     * Describes how the foreground is positioned. Defaults to START and TOP.
18541     *
18542     * @param gravity see {@link android.view.Gravity}
18543     *
18544     * @see #getForegroundGravity()
18545     *
18546     * @attr ref android.R.styleable#View_foregroundGravity
18547     */
18548    public void setForegroundGravity(int gravity) {
18549        if (mForegroundInfo == null) {
18550            mForegroundInfo = new ForegroundInfo();
18551        }
18552
18553        if (mForegroundInfo.mGravity != gravity) {
18554            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
18555                gravity |= Gravity.START;
18556            }
18557
18558            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
18559                gravity |= Gravity.TOP;
18560            }
18561
18562            mForegroundInfo.mGravity = gravity;
18563            requestLayout();
18564        }
18565    }
18566
18567    /**
18568     * Applies a tint to the foreground drawable. Does not modify the current tint
18569     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18570     * <p>
18571     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
18572     * mutate the drawable and apply the specified tint and tint mode using
18573     * {@link Drawable#setTintList(ColorStateList)}.
18574     *
18575     * @param tint the tint to apply, may be {@code null} to clear tint
18576     *
18577     * @attr ref android.R.styleable#View_foregroundTint
18578     * @see #getForegroundTintList()
18579     * @see Drawable#setTintList(ColorStateList)
18580     */
18581    public void setForegroundTintList(@Nullable ColorStateList tint) {
18582        if (mForegroundInfo == null) {
18583            mForegroundInfo = new ForegroundInfo();
18584        }
18585        if (mForegroundInfo.mTintInfo == null) {
18586            mForegroundInfo.mTintInfo = new TintInfo();
18587        }
18588        mForegroundInfo.mTintInfo.mTintList = tint;
18589        mForegroundInfo.mTintInfo.mHasTintList = true;
18590
18591        applyForegroundTint();
18592    }
18593
18594    /**
18595     * Return the tint applied to the foreground drawable, if specified.
18596     *
18597     * @return the tint applied to the foreground drawable
18598     * @attr ref android.R.styleable#View_foregroundTint
18599     * @see #setForegroundTintList(ColorStateList)
18600     */
18601    @Nullable
18602    public ColorStateList getForegroundTintList() {
18603        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18604                ? mForegroundInfo.mTintInfo.mTintList : null;
18605    }
18606
18607    /**
18608     * Specifies the blending mode used to apply the tint specified by
18609     * {@link #setForegroundTintList(ColorStateList)}} to the background
18610     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18611     *
18612     * @param tintMode the blending mode used to apply the tint, may be
18613     *                 {@code null} to clear tint
18614     * @attr ref android.R.styleable#View_foregroundTintMode
18615     * @see #getForegroundTintMode()
18616     * @see Drawable#setTintMode(PorterDuff.Mode)
18617     */
18618    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18619        if (mForegroundInfo == null) {
18620            mForegroundInfo = new ForegroundInfo();
18621        }
18622        if (mForegroundInfo.mTintInfo == null) {
18623            mForegroundInfo.mTintInfo = new TintInfo();
18624        }
18625        mForegroundInfo.mTintInfo.mTintMode = tintMode;
18626        mForegroundInfo.mTintInfo.mHasTintMode = true;
18627
18628        applyForegroundTint();
18629    }
18630
18631    /**
18632     * Return the blending mode used to apply the tint to the foreground
18633     * drawable, if specified.
18634     *
18635     * @return the blending mode used to apply the tint to the foreground
18636     *         drawable
18637     * @attr ref android.R.styleable#View_foregroundTintMode
18638     * @see #setForegroundTintMode(PorterDuff.Mode)
18639     */
18640    @Nullable
18641    public PorterDuff.Mode getForegroundTintMode() {
18642        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18643                ? mForegroundInfo.mTintInfo.mTintMode : null;
18644    }
18645
18646    private void applyForegroundTint() {
18647        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
18648                && mForegroundInfo.mTintInfo != null) {
18649            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
18650            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18651                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
18652
18653                if (tintInfo.mHasTintList) {
18654                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
18655                }
18656
18657                if (tintInfo.mHasTintMode) {
18658                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
18659                }
18660
18661                // The drawable (or one of its children) may not have been
18662                // stateful before applying the tint, so let's try again.
18663                if (mForegroundInfo.mDrawable.isStateful()) {
18664                    mForegroundInfo.mDrawable.setState(getDrawableState());
18665                }
18666            }
18667        }
18668    }
18669
18670    /**
18671     * Draw any foreground content for this view.
18672     *
18673     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
18674     * drawable or other view-specific decorations. The foreground is drawn on top of the
18675     * primary view content.</p>
18676     *
18677     * @param canvas canvas to draw into
18678     */
18679    public void onDrawForeground(Canvas canvas) {
18680        onDrawScrollIndicators(canvas);
18681        onDrawScrollBars(canvas);
18682
18683        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18684        if (foreground != null) {
18685            if (mForegroundInfo.mBoundsChanged) {
18686                mForegroundInfo.mBoundsChanged = false;
18687                final Rect selfBounds = mForegroundInfo.mSelfBounds;
18688                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
18689
18690                if (mForegroundInfo.mInsidePadding) {
18691                    selfBounds.set(0, 0, getWidth(), getHeight());
18692                } else {
18693                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
18694                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
18695                }
18696
18697                final int ld = getLayoutDirection();
18698                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
18699                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
18700                foreground.setBounds(overlayBounds);
18701            }
18702
18703            foreground.draw(canvas);
18704        }
18705    }
18706
18707    /**
18708     * Sets the padding. The view may add on the space required to display
18709     * the scrollbars, depending on the style and visibility of the scrollbars.
18710     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
18711     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
18712     * from the values set in this call.
18713     *
18714     * @attr ref android.R.styleable#View_padding
18715     * @attr ref android.R.styleable#View_paddingBottom
18716     * @attr ref android.R.styleable#View_paddingLeft
18717     * @attr ref android.R.styleable#View_paddingRight
18718     * @attr ref android.R.styleable#View_paddingTop
18719     * @param left the left padding in pixels
18720     * @param top the top padding in pixels
18721     * @param right the right padding in pixels
18722     * @param bottom the bottom padding in pixels
18723     */
18724    public void setPadding(int left, int top, int right, int bottom) {
18725        resetResolvedPaddingInternal();
18726
18727        mUserPaddingStart = UNDEFINED_PADDING;
18728        mUserPaddingEnd = UNDEFINED_PADDING;
18729
18730        mUserPaddingLeftInitial = left;
18731        mUserPaddingRightInitial = right;
18732
18733        mLeftPaddingDefined = true;
18734        mRightPaddingDefined = true;
18735
18736        internalSetPadding(left, top, right, bottom);
18737    }
18738
18739    /**
18740     * @hide
18741     */
18742    protected void internalSetPadding(int left, int top, int right, int bottom) {
18743        mUserPaddingLeft = left;
18744        mUserPaddingRight = right;
18745        mUserPaddingBottom = bottom;
18746
18747        final int viewFlags = mViewFlags;
18748        boolean changed = false;
18749
18750        // Common case is there are no scroll bars.
18751        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
18752            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
18753                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
18754                        ? 0 : getVerticalScrollbarWidth();
18755                switch (mVerticalScrollbarPosition) {
18756                    case SCROLLBAR_POSITION_DEFAULT:
18757                        if (isLayoutRtl()) {
18758                            left += offset;
18759                        } else {
18760                            right += offset;
18761                        }
18762                        break;
18763                    case SCROLLBAR_POSITION_RIGHT:
18764                        right += offset;
18765                        break;
18766                    case SCROLLBAR_POSITION_LEFT:
18767                        left += offset;
18768                        break;
18769                }
18770            }
18771            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
18772                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
18773                        ? 0 : getHorizontalScrollbarHeight();
18774            }
18775        }
18776
18777        if (mPaddingLeft != left) {
18778            changed = true;
18779            mPaddingLeft = left;
18780        }
18781        if (mPaddingTop != top) {
18782            changed = true;
18783            mPaddingTop = top;
18784        }
18785        if (mPaddingRight != right) {
18786            changed = true;
18787            mPaddingRight = right;
18788        }
18789        if (mPaddingBottom != bottom) {
18790            changed = true;
18791            mPaddingBottom = bottom;
18792        }
18793
18794        if (changed) {
18795            requestLayout();
18796            invalidateOutline();
18797        }
18798    }
18799
18800    /**
18801     * Sets the relative padding. The view may add on the space required to display
18802     * the scrollbars, depending on the style and visibility of the scrollbars.
18803     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
18804     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
18805     * from the values set in this call.
18806     *
18807     * @attr ref android.R.styleable#View_padding
18808     * @attr ref android.R.styleable#View_paddingBottom
18809     * @attr ref android.R.styleable#View_paddingStart
18810     * @attr ref android.R.styleable#View_paddingEnd
18811     * @attr ref android.R.styleable#View_paddingTop
18812     * @param start the start padding in pixels
18813     * @param top the top padding in pixels
18814     * @param end the end padding in pixels
18815     * @param bottom the bottom padding in pixels
18816     */
18817    public void setPaddingRelative(int start, int top, int end, int bottom) {
18818        resetResolvedPaddingInternal();
18819
18820        mUserPaddingStart = start;
18821        mUserPaddingEnd = end;
18822        mLeftPaddingDefined = true;
18823        mRightPaddingDefined = true;
18824
18825        switch(getLayoutDirection()) {
18826            case LAYOUT_DIRECTION_RTL:
18827                mUserPaddingLeftInitial = end;
18828                mUserPaddingRightInitial = start;
18829                internalSetPadding(end, top, start, bottom);
18830                break;
18831            case LAYOUT_DIRECTION_LTR:
18832            default:
18833                mUserPaddingLeftInitial = start;
18834                mUserPaddingRightInitial = end;
18835                internalSetPadding(start, top, end, bottom);
18836        }
18837    }
18838
18839    /**
18840     * Returns the top padding of this view.
18841     *
18842     * @return the top padding in pixels
18843     */
18844    public int getPaddingTop() {
18845        return mPaddingTop;
18846    }
18847
18848    /**
18849     * Returns the bottom padding of this view. If there are inset and enabled
18850     * scrollbars, this value may include the space required to display the
18851     * scrollbars as well.
18852     *
18853     * @return the bottom padding in pixels
18854     */
18855    public int getPaddingBottom() {
18856        return mPaddingBottom;
18857    }
18858
18859    /**
18860     * Returns the left padding of this view. If there are inset and enabled
18861     * scrollbars, this value may include the space required to display the
18862     * scrollbars as well.
18863     *
18864     * @return the left padding in pixels
18865     */
18866    public int getPaddingLeft() {
18867        if (!isPaddingResolved()) {
18868            resolvePadding();
18869        }
18870        return mPaddingLeft;
18871    }
18872
18873    /**
18874     * Returns the start padding of this view depending on its resolved layout direction.
18875     * If there are inset and enabled scrollbars, this value may include the space
18876     * required to display the scrollbars as well.
18877     *
18878     * @return the start padding in pixels
18879     */
18880    public int getPaddingStart() {
18881        if (!isPaddingResolved()) {
18882            resolvePadding();
18883        }
18884        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18885                mPaddingRight : mPaddingLeft;
18886    }
18887
18888    /**
18889     * Returns the right padding of this view. If there are inset and enabled
18890     * scrollbars, this value may include the space required to display the
18891     * scrollbars as well.
18892     *
18893     * @return the right padding in pixels
18894     */
18895    public int getPaddingRight() {
18896        if (!isPaddingResolved()) {
18897            resolvePadding();
18898        }
18899        return mPaddingRight;
18900    }
18901
18902    /**
18903     * Returns the end padding of this view depending on its resolved layout direction.
18904     * If there are inset and enabled scrollbars, this value may include the space
18905     * required to display the scrollbars as well.
18906     *
18907     * @return the end padding in pixels
18908     */
18909    public int getPaddingEnd() {
18910        if (!isPaddingResolved()) {
18911            resolvePadding();
18912        }
18913        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18914                mPaddingLeft : mPaddingRight;
18915    }
18916
18917    /**
18918     * Return if the padding has been set through relative values
18919     * {@link #setPaddingRelative(int, int, int, int)} or through
18920     * @attr ref android.R.styleable#View_paddingStart or
18921     * @attr ref android.R.styleable#View_paddingEnd
18922     *
18923     * @return true if the padding is relative or false if it is not.
18924     */
18925    public boolean isPaddingRelative() {
18926        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18927    }
18928
18929    Insets computeOpticalInsets() {
18930        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18931    }
18932
18933    /**
18934     * @hide
18935     */
18936    public void resetPaddingToInitialValues() {
18937        if (isRtlCompatibilityMode()) {
18938            mPaddingLeft = mUserPaddingLeftInitial;
18939            mPaddingRight = mUserPaddingRightInitial;
18940            return;
18941        }
18942        if (isLayoutRtl()) {
18943            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18944            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18945        } else {
18946            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18947            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18948        }
18949    }
18950
18951    /**
18952     * @hide
18953     */
18954    public Insets getOpticalInsets() {
18955        if (mLayoutInsets == null) {
18956            mLayoutInsets = computeOpticalInsets();
18957        }
18958        return mLayoutInsets;
18959    }
18960
18961    /**
18962     * Set this view's optical insets.
18963     *
18964     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
18965     * property. Views that compute their own optical insets should call it as part of measurement.
18966     * This method does not request layout. If you are setting optical insets outside of
18967     * measure/layout itself you will want to call requestLayout() yourself.
18968     * </p>
18969     * @hide
18970     */
18971    public void setOpticalInsets(Insets insets) {
18972        mLayoutInsets = insets;
18973    }
18974
18975    /**
18976     * Changes the selection state of this view. A view can be selected or not.
18977     * Note that selection is not the same as focus. Views are typically
18978     * selected in the context of an AdapterView like ListView or GridView;
18979     * the selected view is the view that is highlighted.
18980     *
18981     * @param selected true if the view must be selected, false otherwise
18982     */
18983    public void setSelected(boolean selected) {
18984        //noinspection DoubleNegation
18985        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
18986            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
18987            if (!selected) resetPressedState();
18988            invalidate(true);
18989            refreshDrawableState();
18990            dispatchSetSelected(selected);
18991            if (selected) {
18992                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
18993            } else {
18994                notifyViewAccessibilityStateChangedIfNeeded(
18995                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
18996            }
18997        }
18998    }
18999
19000    /**
19001     * Dispatch setSelected to all of this View's children.
19002     *
19003     * @see #setSelected(boolean)
19004     *
19005     * @param selected The new selected state
19006     */
19007    protected void dispatchSetSelected(boolean selected) {
19008    }
19009
19010    /**
19011     * Indicates the selection state of this view.
19012     *
19013     * @return true if the view is selected, false otherwise
19014     */
19015    @ViewDebug.ExportedProperty
19016    public boolean isSelected() {
19017        return (mPrivateFlags & PFLAG_SELECTED) != 0;
19018    }
19019
19020    /**
19021     * Changes the activated state of this view. A view can be activated or not.
19022     * Note that activation is not the same as selection.  Selection is
19023     * a transient property, representing the view (hierarchy) the user is
19024     * currently interacting with.  Activation is a longer-term state that the
19025     * user can move views in and out of.  For example, in a list view with
19026     * single or multiple selection enabled, the views in the current selection
19027     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
19028     * here.)  The activated state is propagated down to children of the view it
19029     * is set on.
19030     *
19031     * @param activated true if the view must be activated, false otherwise
19032     */
19033    public void setActivated(boolean activated) {
19034        //noinspection DoubleNegation
19035        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
19036            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
19037            invalidate(true);
19038            refreshDrawableState();
19039            dispatchSetActivated(activated);
19040        }
19041    }
19042
19043    /**
19044     * Dispatch setActivated to all of this View's children.
19045     *
19046     * @see #setActivated(boolean)
19047     *
19048     * @param activated The new activated state
19049     */
19050    protected void dispatchSetActivated(boolean activated) {
19051    }
19052
19053    /**
19054     * Indicates the activation state of this view.
19055     *
19056     * @return true if the view is activated, false otherwise
19057     */
19058    @ViewDebug.ExportedProperty
19059    public boolean isActivated() {
19060        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
19061    }
19062
19063    /**
19064     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
19065     * observer can be used to get notifications when global events, like
19066     * layout, happen.
19067     *
19068     * The returned ViewTreeObserver observer is not guaranteed to remain
19069     * valid for the lifetime of this View. If the caller of this method keeps
19070     * a long-lived reference to ViewTreeObserver, it should always check for
19071     * the return value of {@link ViewTreeObserver#isAlive()}.
19072     *
19073     * @return The ViewTreeObserver for this view's hierarchy.
19074     */
19075    public ViewTreeObserver getViewTreeObserver() {
19076        if (mAttachInfo != null) {
19077            return mAttachInfo.mTreeObserver;
19078        }
19079        if (mFloatingTreeObserver == null) {
19080            mFloatingTreeObserver = new ViewTreeObserver();
19081        }
19082        return mFloatingTreeObserver;
19083    }
19084
19085    /**
19086     * <p>Finds the topmost view in the current view hierarchy.</p>
19087     *
19088     * @return the topmost view containing this view
19089     */
19090    public View getRootView() {
19091        if (mAttachInfo != null) {
19092            final View v = mAttachInfo.mRootView;
19093            if (v != null) {
19094                return v;
19095            }
19096        }
19097
19098        View parent = this;
19099
19100        while (parent.mParent != null && parent.mParent instanceof View) {
19101            parent = (View) parent.mParent;
19102        }
19103
19104        return parent;
19105    }
19106
19107    /**
19108     * Transforms a motion event from view-local coordinates to on-screen
19109     * coordinates.
19110     *
19111     * @param ev the view-local motion event
19112     * @return false if the transformation could not be applied
19113     * @hide
19114     */
19115    public boolean toGlobalMotionEvent(MotionEvent ev) {
19116        final AttachInfo info = mAttachInfo;
19117        if (info == null) {
19118            return false;
19119        }
19120
19121        final Matrix m = info.mTmpMatrix;
19122        m.set(Matrix.IDENTITY_MATRIX);
19123        transformMatrixToGlobal(m);
19124        ev.transform(m);
19125        return true;
19126    }
19127
19128    /**
19129     * Transforms a motion event from on-screen coordinates to view-local
19130     * coordinates.
19131     *
19132     * @param ev the on-screen motion event
19133     * @return false if the transformation could not be applied
19134     * @hide
19135     */
19136    public boolean toLocalMotionEvent(MotionEvent ev) {
19137        final AttachInfo info = mAttachInfo;
19138        if (info == null) {
19139            return false;
19140        }
19141
19142        final Matrix m = info.mTmpMatrix;
19143        m.set(Matrix.IDENTITY_MATRIX);
19144        transformMatrixToLocal(m);
19145        ev.transform(m);
19146        return true;
19147    }
19148
19149    /**
19150     * Modifies the input matrix such that it maps view-local coordinates to
19151     * on-screen coordinates.
19152     *
19153     * @param m input matrix to modify
19154     * @hide
19155     */
19156    public void transformMatrixToGlobal(Matrix m) {
19157        final ViewParent parent = mParent;
19158        if (parent instanceof View) {
19159            final View vp = (View) parent;
19160            vp.transformMatrixToGlobal(m);
19161            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
19162        } else if (parent instanceof ViewRootImpl) {
19163            final ViewRootImpl vr = (ViewRootImpl) parent;
19164            vr.transformMatrixToGlobal(m);
19165            m.preTranslate(0, -vr.mCurScrollY);
19166        }
19167
19168        m.preTranslate(mLeft, mTop);
19169
19170        if (!hasIdentityMatrix()) {
19171            m.preConcat(getMatrix());
19172        }
19173    }
19174
19175    /**
19176     * Modifies the input matrix such that it maps on-screen coordinates to
19177     * view-local coordinates.
19178     *
19179     * @param m input matrix to modify
19180     * @hide
19181     */
19182    public void transformMatrixToLocal(Matrix m) {
19183        final ViewParent parent = mParent;
19184        if (parent instanceof View) {
19185            final View vp = (View) parent;
19186            vp.transformMatrixToLocal(m);
19187            m.postTranslate(vp.mScrollX, vp.mScrollY);
19188        } else if (parent instanceof ViewRootImpl) {
19189            final ViewRootImpl vr = (ViewRootImpl) parent;
19190            vr.transformMatrixToLocal(m);
19191            m.postTranslate(0, vr.mCurScrollY);
19192        }
19193
19194        m.postTranslate(-mLeft, -mTop);
19195
19196        if (!hasIdentityMatrix()) {
19197            m.postConcat(getInverseMatrix());
19198        }
19199    }
19200
19201    /**
19202     * @hide
19203     */
19204    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
19205            @ViewDebug.IntToString(from = 0, to = "x"),
19206            @ViewDebug.IntToString(from = 1, to = "y")
19207    })
19208    public int[] getLocationOnScreen() {
19209        int[] location = new int[2];
19210        getLocationOnScreen(location);
19211        return location;
19212    }
19213
19214    /**
19215     * <p>Computes the coordinates of this view on the screen. The argument
19216     * must be an array of two integers. After the method returns, the array
19217     * contains the x and y location in that order.</p>
19218     *
19219     * @param outLocation an array of two integers in which to hold the coordinates
19220     */
19221    public void getLocationOnScreen(@Size(2) int[] outLocation) {
19222        getLocationInWindow(outLocation);
19223
19224        final AttachInfo info = mAttachInfo;
19225        if (info != null) {
19226            outLocation[0] += info.mWindowLeft;
19227            outLocation[1] += info.mWindowTop;
19228        }
19229    }
19230
19231    /**
19232     * <p>Computes the coordinates of this view in its window. The argument
19233     * must be an array of two integers. After the method returns, the array
19234     * contains the x and y location in that order.</p>
19235     *
19236     * @param outLocation an array of two integers in which to hold the coordinates
19237     */
19238    public void getLocationInWindow(@Size(2) int[] outLocation) {
19239        if (outLocation == null || outLocation.length < 2) {
19240            throw new IllegalArgumentException("outLocation must be an array of two integers");
19241        }
19242
19243        outLocation[0] = 0;
19244        outLocation[1] = 0;
19245
19246        transformFromViewToWindowSpace(outLocation);
19247    }
19248
19249    /** @hide */
19250    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
19251        if (inOutLocation == null || inOutLocation.length < 2) {
19252            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
19253        }
19254
19255        if (mAttachInfo == null) {
19256            // When the view is not attached to a window, this method does not make sense
19257            inOutLocation[0] = inOutLocation[1] = 0;
19258            return;
19259        }
19260
19261        float position[] = mAttachInfo.mTmpTransformLocation;
19262        position[0] = inOutLocation[0];
19263        position[1] = inOutLocation[1];
19264
19265        if (!hasIdentityMatrix()) {
19266            getMatrix().mapPoints(position);
19267        }
19268
19269        position[0] += mLeft;
19270        position[1] += mTop;
19271
19272        ViewParent viewParent = mParent;
19273        while (viewParent instanceof View) {
19274            final View view = (View) viewParent;
19275
19276            position[0] -= view.mScrollX;
19277            position[1] -= view.mScrollY;
19278
19279            if (!view.hasIdentityMatrix()) {
19280                view.getMatrix().mapPoints(position);
19281            }
19282
19283            position[0] += view.mLeft;
19284            position[1] += view.mTop;
19285
19286            viewParent = view.mParent;
19287         }
19288
19289        if (viewParent instanceof ViewRootImpl) {
19290            // *cough*
19291            final ViewRootImpl vr = (ViewRootImpl) viewParent;
19292            position[1] -= vr.mCurScrollY;
19293        }
19294
19295        inOutLocation[0] = Math.round(position[0]);
19296        inOutLocation[1] = Math.round(position[1]);
19297    }
19298
19299    /**
19300     * {@hide}
19301     * @param id the id of the view to be found
19302     * @return the view of the specified id, null if cannot be found
19303     */
19304    protected View findViewTraversal(@IdRes int id) {
19305        if (id == mID) {
19306            return this;
19307        }
19308        return null;
19309    }
19310
19311    /**
19312     * {@hide}
19313     * @param tag the tag of the view to be found
19314     * @return the view of specified tag, null if cannot be found
19315     */
19316    protected View findViewWithTagTraversal(Object tag) {
19317        if (tag != null && tag.equals(mTag)) {
19318            return this;
19319        }
19320        return null;
19321    }
19322
19323    /**
19324     * {@hide}
19325     * @param predicate The predicate to evaluate.
19326     * @param childToSkip If not null, ignores this child during the recursive traversal.
19327     * @return The first view that matches the predicate or null.
19328     */
19329    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
19330        if (predicate.apply(this)) {
19331            return this;
19332        }
19333        return null;
19334    }
19335
19336    /**
19337     * Look for a child view with the given id.  If this view has the given
19338     * id, return this view.
19339     *
19340     * @param id The id to search for.
19341     * @return The view that has the given id in the hierarchy or null
19342     */
19343    @Nullable
19344    public final View findViewById(@IdRes int id) {
19345        if (id < 0) {
19346            return null;
19347        }
19348        return findViewTraversal(id);
19349    }
19350
19351    /**
19352     * Finds a view by its unuque and stable accessibility id.
19353     *
19354     * @param accessibilityId The searched accessibility id.
19355     * @return The found view.
19356     */
19357    final View findViewByAccessibilityId(int accessibilityId) {
19358        if (accessibilityId < 0) {
19359            return null;
19360        }
19361        View view = findViewByAccessibilityIdTraversal(accessibilityId);
19362        if (view != null) {
19363            return view.includeForAccessibility() ? view : null;
19364        }
19365        return null;
19366    }
19367
19368    /**
19369     * Performs the traversal to find a view by its unuque and stable accessibility id.
19370     *
19371     * <strong>Note:</strong>This method does not stop at the root namespace
19372     * boundary since the user can touch the screen at an arbitrary location
19373     * potentially crossing the root namespace bounday which will send an
19374     * accessibility event to accessibility services and they should be able
19375     * to obtain the event source. Also accessibility ids are guaranteed to be
19376     * unique in the window.
19377     *
19378     * @param accessibilityId The accessibility id.
19379     * @return The found view.
19380     *
19381     * @hide
19382     */
19383    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
19384        if (getAccessibilityViewId() == accessibilityId) {
19385            return this;
19386        }
19387        return null;
19388    }
19389
19390    /**
19391     * Look for a child view with the given tag.  If this view has the given
19392     * tag, return this view.
19393     *
19394     * @param tag The tag to search for, using "tag.equals(getTag())".
19395     * @return The View that has the given tag in the hierarchy or null
19396     */
19397    public final View findViewWithTag(Object tag) {
19398        if (tag == null) {
19399            return null;
19400        }
19401        return findViewWithTagTraversal(tag);
19402    }
19403
19404    /**
19405     * {@hide}
19406     * Look for a child view that matches the specified predicate.
19407     * If this view matches the predicate, return this view.
19408     *
19409     * @param predicate The predicate to evaluate.
19410     * @return The first view that matches the predicate or null.
19411     */
19412    public final View findViewByPredicate(Predicate<View> predicate) {
19413        return findViewByPredicateTraversal(predicate, null);
19414    }
19415
19416    /**
19417     * {@hide}
19418     * Look for a child view that matches the specified predicate,
19419     * starting with the specified view and its descendents and then
19420     * recusively searching the ancestors and siblings of that view
19421     * until this view is reached.
19422     *
19423     * This method is useful in cases where the predicate does not match
19424     * a single unique view (perhaps multiple views use the same id)
19425     * and we are trying to find the view that is "closest" in scope to the
19426     * starting view.
19427     *
19428     * @param start The view to start from.
19429     * @param predicate The predicate to evaluate.
19430     * @return The first view that matches the predicate or null.
19431     */
19432    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
19433        View childToSkip = null;
19434        for (;;) {
19435            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
19436            if (view != null || start == this) {
19437                return view;
19438            }
19439
19440            ViewParent parent = start.getParent();
19441            if (parent == null || !(parent instanceof View)) {
19442                return null;
19443            }
19444
19445            childToSkip = start;
19446            start = (View) parent;
19447        }
19448    }
19449
19450    /**
19451     * Sets the identifier for this view. The identifier does not have to be
19452     * unique in this view's hierarchy. The identifier should be a positive
19453     * number.
19454     *
19455     * @see #NO_ID
19456     * @see #getId()
19457     * @see #findViewById(int)
19458     *
19459     * @param id a number used to identify the view
19460     *
19461     * @attr ref android.R.styleable#View_id
19462     */
19463    public void setId(@IdRes int id) {
19464        mID = id;
19465        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
19466            mID = generateViewId();
19467        }
19468    }
19469
19470    /**
19471     * {@hide}
19472     *
19473     * @param isRoot true if the view belongs to the root namespace, false
19474     *        otherwise
19475     */
19476    public void setIsRootNamespace(boolean isRoot) {
19477        if (isRoot) {
19478            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
19479        } else {
19480            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
19481        }
19482    }
19483
19484    /**
19485     * {@hide}
19486     *
19487     * @return true if the view belongs to the root namespace, false otherwise
19488     */
19489    public boolean isRootNamespace() {
19490        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
19491    }
19492
19493    /**
19494     * Returns this view's identifier.
19495     *
19496     * @return a positive integer used to identify the view or {@link #NO_ID}
19497     *         if the view has no ID
19498     *
19499     * @see #setId(int)
19500     * @see #findViewById(int)
19501     * @attr ref android.R.styleable#View_id
19502     */
19503    @IdRes
19504    @ViewDebug.CapturedViewProperty
19505    public int getId() {
19506        return mID;
19507    }
19508
19509    /**
19510     * Returns this view's tag.
19511     *
19512     * @return the Object stored in this view as a tag, or {@code null} if not
19513     *         set
19514     *
19515     * @see #setTag(Object)
19516     * @see #getTag(int)
19517     */
19518    @ViewDebug.ExportedProperty
19519    public Object getTag() {
19520        return mTag;
19521    }
19522
19523    /**
19524     * Sets the tag associated with this view. A tag can be used to mark
19525     * a view in its hierarchy and does not have to be unique within the
19526     * hierarchy. Tags can also be used to store data within a view without
19527     * resorting to another data structure.
19528     *
19529     * @param tag an Object to tag the view with
19530     *
19531     * @see #getTag()
19532     * @see #setTag(int, Object)
19533     */
19534    public void setTag(final Object tag) {
19535        mTag = tag;
19536    }
19537
19538    /**
19539     * Returns the tag associated with this view and the specified key.
19540     *
19541     * @param key The key identifying the tag
19542     *
19543     * @return the Object stored in this view as a tag, or {@code null} if not
19544     *         set
19545     *
19546     * @see #setTag(int, Object)
19547     * @see #getTag()
19548     */
19549    public Object getTag(int key) {
19550        if (mKeyedTags != null) return mKeyedTags.get(key);
19551        return null;
19552    }
19553
19554    /**
19555     * Sets a tag associated with this view and a key. A tag can be used
19556     * to mark a view in its hierarchy and does not have to be unique within
19557     * the hierarchy. Tags can also be used to store data within a view
19558     * without resorting to another data structure.
19559     *
19560     * The specified key should be an id declared in the resources of the
19561     * application to ensure it is unique (see the <a
19562     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
19563     * Keys identified as belonging to
19564     * the Android framework or not associated with any package will cause
19565     * an {@link IllegalArgumentException} to be thrown.
19566     *
19567     * @param key The key identifying the tag
19568     * @param tag An Object to tag the view with
19569     *
19570     * @throws IllegalArgumentException If they specified key is not valid
19571     *
19572     * @see #setTag(Object)
19573     * @see #getTag(int)
19574     */
19575    public void setTag(int key, final Object tag) {
19576        // If the package id is 0x00 or 0x01, it's either an undefined package
19577        // or a framework id
19578        if ((key >>> 24) < 2) {
19579            throw new IllegalArgumentException("The key must be an application-specific "
19580                    + "resource id.");
19581        }
19582
19583        setKeyedTag(key, tag);
19584    }
19585
19586    /**
19587     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
19588     * framework id.
19589     *
19590     * @hide
19591     */
19592    public void setTagInternal(int key, Object tag) {
19593        if ((key >>> 24) != 0x1) {
19594            throw new IllegalArgumentException("The key must be a framework-specific "
19595                    + "resource id.");
19596        }
19597
19598        setKeyedTag(key, tag);
19599    }
19600
19601    private void setKeyedTag(int key, Object tag) {
19602        if (mKeyedTags == null) {
19603            mKeyedTags = new SparseArray<Object>(2);
19604        }
19605
19606        mKeyedTags.put(key, tag);
19607    }
19608
19609    /**
19610     * Prints information about this view in the log output, with the tag
19611     * {@link #VIEW_LOG_TAG}.
19612     *
19613     * @hide
19614     */
19615    public void debug() {
19616        debug(0);
19617    }
19618
19619    /**
19620     * Prints information about this view in the log output, with the tag
19621     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
19622     * indentation defined by the <code>depth</code>.
19623     *
19624     * @param depth the indentation level
19625     *
19626     * @hide
19627     */
19628    protected void debug(int depth) {
19629        String output = debugIndent(depth - 1);
19630
19631        output += "+ " + this;
19632        int id = getId();
19633        if (id != -1) {
19634            output += " (id=" + id + ")";
19635        }
19636        Object tag = getTag();
19637        if (tag != null) {
19638            output += " (tag=" + tag + ")";
19639        }
19640        Log.d(VIEW_LOG_TAG, output);
19641
19642        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
19643            output = debugIndent(depth) + " FOCUSED";
19644            Log.d(VIEW_LOG_TAG, output);
19645        }
19646
19647        output = debugIndent(depth);
19648        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
19649                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
19650                + "} ";
19651        Log.d(VIEW_LOG_TAG, output);
19652
19653        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
19654                || mPaddingBottom != 0) {
19655            output = debugIndent(depth);
19656            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
19657                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
19658            Log.d(VIEW_LOG_TAG, output);
19659        }
19660
19661        output = debugIndent(depth);
19662        output += "mMeasureWidth=" + mMeasuredWidth +
19663                " mMeasureHeight=" + mMeasuredHeight;
19664        Log.d(VIEW_LOG_TAG, output);
19665
19666        output = debugIndent(depth);
19667        if (mLayoutParams == null) {
19668            output += "BAD! no layout params";
19669        } else {
19670            output = mLayoutParams.debug(output);
19671        }
19672        Log.d(VIEW_LOG_TAG, output);
19673
19674        output = debugIndent(depth);
19675        output += "flags={";
19676        output += View.printFlags(mViewFlags);
19677        output += "}";
19678        Log.d(VIEW_LOG_TAG, output);
19679
19680        output = debugIndent(depth);
19681        output += "privateFlags={";
19682        output += View.printPrivateFlags(mPrivateFlags);
19683        output += "}";
19684        Log.d(VIEW_LOG_TAG, output);
19685    }
19686
19687    /**
19688     * Creates a string of whitespaces used for indentation.
19689     *
19690     * @param depth the indentation level
19691     * @return a String containing (depth * 2 + 3) * 2 white spaces
19692     *
19693     * @hide
19694     */
19695    protected static String debugIndent(int depth) {
19696        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
19697        for (int i = 0; i < (depth * 2) + 3; i++) {
19698            spaces.append(' ').append(' ');
19699        }
19700        return spaces.toString();
19701    }
19702
19703    /**
19704     * <p>Return the offset of the widget's text baseline from the widget's top
19705     * boundary. If this widget does not support baseline alignment, this
19706     * method returns -1. </p>
19707     *
19708     * @return the offset of the baseline within the widget's bounds or -1
19709     *         if baseline alignment is not supported
19710     */
19711    @ViewDebug.ExportedProperty(category = "layout")
19712    public int getBaseline() {
19713        return -1;
19714    }
19715
19716    /**
19717     * Returns whether the view hierarchy is currently undergoing a layout pass. This
19718     * information is useful to avoid situations such as calling {@link #requestLayout()} during
19719     * a layout pass.
19720     *
19721     * @return whether the view hierarchy is currently undergoing a layout pass
19722     */
19723    public boolean isInLayout() {
19724        ViewRootImpl viewRoot = getViewRootImpl();
19725        return (viewRoot != null && viewRoot.isInLayout());
19726    }
19727
19728    /**
19729     * Call this when something has changed which has invalidated the
19730     * layout of this view. This will schedule a layout pass of the view
19731     * tree. This should not be called while the view hierarchy is currently in a layout
19732     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
19733     * end of the current layout pass (and then layout will run again) or after the current
19734     * frame is drawn and the next layout occurs.
19735     *
19736     * <p>Subclasses which override this method should call the superclass method to
19737     * handle possible request-during-layout errors correctly.</p>
19738     */
19739    @CallSuper
19740    public void requestLayout() {
19741        if (mMeasureCache != null) mMeasureCache.clear();
19742
19743        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
19744            // Only trigger request-during-layout logic if this is the view requesting it,
19745            // not the views in its parent hierarchy
19746            ViewRootImpl viewRoot = getViewRootImpl();
19747            if (viewRoot != null && viewRoot.isInLayout()) {
19748                if (!viewRoot.requestLayoutDuringLayout(this)) {
19749                    return;
19750                }
19751            }
19752            mAttachInfo.mViewRequestingLayout = this;
19753        }
19754
19755        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19756        mPrivateFlags |= PFLAG_INVALIDATED;
19757
19758        if (mParent != null && !mParent.isLayoutRequested()) {
19759            mParent.requestLayout();
19760        }
19761        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
19762            mAttachInfo.mViewRequestingLayout = null;
19763        }
19764    }
19765
19766    /**
19767     * Forces this view to be laid out during the next layout pass.
19768     * This method does not call requestLayout() or forceLayout()
19769     * on the parent.
19770     */
19771    public void forceLayout() {
19772        if (mMeasureCache != null) mMeasureCache.clear();
19773
19774        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19775        mPrivateFlags |= PFLAG_INVALIDATED;
19776    }
19777
19778    /**
19779     * <p>
19780     * This is called to find out how big a view should be. The parent
19781     * supplies constraint information in the width and height parameters.
19782     * </p>
19783     *
19784     * <p>
19785     * The actual measurement work of a view is performed in
19786     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
19787     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
19788     * </p>
19789     *
19790     *
19791     * @param widthMeasureSpec Horizontal space requirements as imposed by the
19792     *        parent
19793     * @param heightMeasureSpec Vertical space requirements as imposed by the
19794     *        parent
19795     *
19796     * @see #onMeasure(int, int)
19797     */
19798    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
19799        boolean optical = isLayoutModeOptical(this);
19800        if (optical != isLayoutModeOptical(mParent)) {
19801            Insets insets = getOpticalInsets();
19802            int oWidth  = insets.left + insets.right;
19803            int oHeight = insets.top  + insets.bottom;
19804            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
19805            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
19806        }
19807
19808        // Suppress sign extension for the low bytes
19809        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
19810        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
19811
19812        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19813
19814        // Optimize layout by avoiding an extra EXACTLY pass when the view is
19815        // already measured as the correct size. In API 23 and below, this
19816        // extra pass is required to make LinearLayout re-distribute weight.
19817        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
19818                || heightMeasureSpec != mOldHeightMeasureSpec;
19819        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
19820                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
19821        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
19822                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
19823        final boolean needsLayout = specChanged
19824                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
19825
19826        if (forceLayout || needsLayout) {
19827            // first clears the measured dimension flag
19828            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
19829
19830            resolveRtlPropertiesIfNeeded();
19831
19832            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
19833            if (cacheIndex < 0 || sIgnoreMeasureCache) {
19834                // measure ourselves, this should set the measured dimension flag back
19835                onMeasure(widthMeasureSpec, heightMeasureSpec);
19836                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19837            } else {
19838                long value = mMeasureCache.valueAt(cacheIndex);
19839                // Casting a long to int drops the high 32 bits, no mask needed
19840                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
19841                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19842            }
19843
19844            // flag not set, setMeasuredDimension() was not invoked, we raise
19845            // an exception to warn the developer
19846            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
19847                throw new IllegalStateException("View with id " + getId() + ": "
19848                        + getClass().getName() + "#onMeasure() did not set the"
19849                        + " measured dimension by calling"
19850                        + " setMeasuredDimension()");
19851            }
19852
19853            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
19854        }
19855
19856        mOldWidthMeasureSpec = widthMeasureSpec;
19857        mOldHeightMeasureSpec = heightMeasureSpec;
19858
19859        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
19860                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
19861    }
19862
19863    /**
19864     * <p>
19865     * Measure the view and its content to determine the measured width and the
19866     * measured height. This method is invoked by {@link #measure(int, int)} and
19867     * should be overridden by subclasses to provide accurate and efficient
19868     * measurement of their contents.
19869     * </p>
19870     *
19871     * <p>
19872     * <strong>CONTRACT:</strong> When overriding this method, you
19873     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
19874     * measured width and height of this view. Failure to do so will trigger an
19875     * <code>IllegalStateException</code>, thrown by
19876     * {@link #measure(int, int)}. Calling the superclass'
19877     * {@link #onMeasure(int, int)} is a valid use.
19878     * </p>
19879     *
19880     * <p>
19881     * The base class implementation of measure defaults to the background size,
19882     * unless a larger size is allowed by the MeasureSpec. Subclasses should
19883     * override {@link #onMeasure(int, int)} to provide better measurements of
19884     * their content.
19885     * </p>
19886     *
19887     * <p>
19888     * If this method is overridden, it is the subclass's responsibility to make
19889     * sure the measured height and width are at least the view's minimum height
19890     * and width ({@link #getSuggestedMinimumHeight()} and
19891     * {@link #getSuggestedMinimumWidth()}).
19892     * </p>
19893     *
19894     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
19895     *                         The requirements are encoded with
19896     *                         {@link android.view.View.MeasureSpec}.
19897     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19898     *                         The requirements are encoded with
19899     *                         {@link android.view.View.MeasureSpec}.
19900     *
19901     * @see #getMeasuredWidth()
19902     * @see #getMeasuredHeight()
19903     * @see #setMeasuredDimension(int, int)
19904     * @see #getSuggestedMinimumHeight()
19905     * @see #getSuggestedMinimumWidth()
19906     * @see android.view.View.MeasureSpec#getMode(int)
19907     * @see android.view.View.MeasureSpec#getSize(int)
19908     */
19909    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19910        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19911                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19912    }
19913
19914    /**
19915     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19916     * measured width and measured height. Failing to do so will trigger an
19917     * exception at measurement time.</p>
19918     *
19919     * @param measuredWidth The measured width of this view.  May be a complex
19920     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19921     * {@link #MEASURED_STATE_TOO_SMALL}.
19922     * @param measuredHeight The measured height of this view.  May be a complex
19923     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19924     * {@link #MEASURED_STATE_TOO_SMALL}.
19925     */
19926    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19927        boolean optical = isLayoutModeOptical(this);
19928        if (optical != isLayoutModeOptical(mParent)) {
19929            Insets insets = getOpticalInsets();
19930            int opticalWidth  = insets.left + insets.right;
19931            int opticalHeight = insets.top  + insets.bottom;
19932
19933            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
19934            measuredHeight += optical ? opticalHeight : -opticalHeight;
19935        }
19936        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19937    }
19938
19939    /**
19940     * Sets the measured dimension without extra processing for things like optical bounds.
19941     * Useful for reapplying consistent values that have already been cooked with adjustments
19942     * for optical bounds, etc. such as those from the measurement cache.
19943     *
19944     * @param measuredWidth The measured width of this view.  May be a complex
19945     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19946     * {@link #MEASURED_STATE_TOO_SMALL}.
19947     * @param measuredHeight The measured height of this view.  May be a complex
19948     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19949     * {@link #MEASURED_STATE_TOO_SMALL}.
19950     */
19951    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19952        mMeasuredWidth = measuredWidth;
19953        mMeasuredHeight = measuredHeight;
19954
19955        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19956    }
19957
19958    /**
19959     * Merge two states as returned by {@link #getMeasuredState()}.
19960     * @param curState The current state as returned from a view or the result
19961     * of combining multiple views.
19962     * @param newState The new view state to combine.
19963     * @return Returns a new integer reflecting the combination of the two
19964     * states.
19965     */
19966    public static int combineMeasuredStates(int curState, int newState) {
19967        return curState | newState;
19968    }
19969
19970    /**
19971     * Version of {@link #resolveSizeAndState(int, int, int)}
19972     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
19973     */
19974    public static int resolveSize(int size, int measureSpec) {
19975        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
19976    }
19977
19978    /**
19979     * Utility to reconcile a desired size and state, with constraints imposed
19980     * by a MeasureSpec. Will take the desired size, unless a different size
19981     * is imposed by the constraints. The returned value is a compound integer,
19982     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
19983     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
19984     * resulting size is smaller than the size the view wants to be.
19985     *
19986     * @param size How big the view wants to be.
19987     * @param measureSpec Constraints imposed by the parent.
19988     * @param childMeasuredState Size information bit mask for the view's
19989     *                           children.
19990     * @return Size information bit mask as defined by
19991     *         {@link #MEASURED_SIZE_MASK} and
19992     *         {@link #MEASURED_STATE_TOO_SMALL}.
19993     */
19994    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
19995        final int specMode = MeasureSpec.getMode(measureSpec);
19996        final int specSize = MeasureSpec.getSize(measureSpec);
19997        final int result;
19998        switch (specMode) {
19999            case MeasureSpec.AT_MOST:
20000                if (specSize < size) {
20001                    result = specSize | MEASURED_STATE_TOO_SMALL;
20002                } else {
20003                    result = size;
20004                }
20005                break;
20006            case MeasureSpec.EXACTLY:
20007                result = specSize;
20008                break;
20009            case MeasureSpec.UNSPECIFIED:
20010            default:
20011                result = size;
20012        }
20013        return result | (childMeasuredState & MEASURED_STATE_MASK);
20014    }
20015
20016    /**
20017     * Utility to return a default size. Uses the supplied size if the
20018     * MeasureSpec imposed no constraints. Will get larger if allowed
20019     * by the MeasureSpec.
20020     *
20021     * @param size Default size for this view
20022     * @param measureSpec Constraints imposed by the parent
20023     * @return The size this view should be.
20024     */
20025    public static int getDefaultSize(int size, int measureSpec) {
20026        int result = size;
20027        int specMode = MeasureSpec.getMode(measureSpec);
20028        int specSize = MeasureSpec.getSize(measureSpec);
20029
20030        switch (specMode) {
20031        case MeasureSpec.UNSPECIFIED:
20032            result = size;
20033            break;
20034        case MeasureSpec.AT_MOST:
20035        case MeasureSpec.EXACTLY:
20036            result = specSize;
20037            break;
20038        }
20039        return result;
20040    }
20041
20042    /**
20043     * Returns the suggested minimum height that the view should use. This
20044     * returns the maximum of the view's minimum height
20045     * and the background's minimum height
20046     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
20047     * <p>
20048     * When being used in {@link #onMeasure(int, int)}, the caller should still
20049     * ensure the returned height is within the requirements of the parent.
20050     *
20051     * @return The suggested minimum height of the view.
20052     */
20053    protected int getSuggestedMinimumHeight() {
20054        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
20055
20056    }
20057
20058    /**
20059     * Returns the suggested minimum width that the view should use. This
20060     * returns the maximum of the view's minimum width
20061     * and the background's minimum width
20062     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
20063     * <p>
20064     * When being used in {@link #onMeasure(int, int)}, the caller should still
20065     * ensure the returned width is within the requirements of the parent.
20066     *
20067     * @return The suggested minimum width of the view.
20068     */
20069    protected int getSuggestedMinimumWidth() {
20070        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
20071    }
20072
20073    /**
20074     * Returns the minimum height of the view.
20075     *
20076     * @return the minimum height the view will try to be.
20077     *
20078     * @see #setMinimumHeight(int)
20079     *
20080     * @attr ref android.R.styleable#View_minHeight
20081     */
20082    public int getMinimumHeight() {
20083        return mMinHeight;
20084    }
20085
20086    /**
20087     * Sets the minimum height of the view. It is not guaranteed the view will
20088     * be able to achieve this minimum height (for example, if its parent layout
20089     * constrains it with less available height).
20090     *
20091     * @param minHeight The minimum height the view will try to be.
20092     *
20093     * @see #getMinimumHeight()
20094     *
20095     * @attr ref android.R.styleable#View_minHeight
20096     */
20097    @RemotableViewMethod
20098    public void setMinimumHeight(int minHeight) {
20099        mMinHeight = minHeight;
20100        requestLayout();
20101    }
20102
20103    /**
20104     * Returns the minimum width of the view.
20105     *
20106     * @return the minimum width the view will try to be.
20107     *
20108     * @see #setMinimumWidth(int)
20109     *
20110     * @attr ref android.R.styleable#View_minWidth
20111     */
20112    public int getMinimumWidth() {
20113        return mMinWidth;
20114    }
20115
20116    /**
20117     * Sets the minimum width of the view. It is not guaranteed the view will
20118     * be able to achieve this minimum width (for example, if its parent layout
20119     * constrains it with less available width).
20120     *
20121     * @param minWidth The minimum width the view will try to be.
20122     *
20123     * @see #getMinimumWidth()
20124     *
20125     * @attr ref android.R.styleable#View_minWidth
20126     */
20127    public void setMinimumWidth(int minWidth) {
20128        mMinWidth = minWidth;
20129        requestLayout();
20130
20131    }
20132
20133    /**
20134     * Get the animation currently associated with this view.
20135     *
20136     * @return The animation that is currently playing or
20137     *         scheduled to play for this view.
20138     */
20139    public Animation getAnimation() {
20140        return mCurrentAnimation;
20141    }
20142
20143    /**
20144     * Start the specified animation now.
20145     *
20146     * @param animation the animation to start now
20147     */
20148    public void startAnimation(Animation animation) {
20149        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
20150        setAnimation(animation);
20151        invalidateParentCaches();
20152        invalidate(true);
20153    }
20154
20155    /**
20156     * Cancels any animations for this view.
20157     */
20158    public void clearAnimation() {
20159        if (mCurrentAnimation != null) {
20160            mCurrentAnimation.detach();
20161        }
20162        mCurrentAnimation = null;
20163        invalidateParentIfNeeded();
20164    }
20165
20166    /**
20167     * Sets the next animation to play for this view.
20168     * If you want the animation to play immediately, use
20169     * {@link #startAnimation(android.view.animation.Animation)} instead.
20170     * This method provides allows fine-grained
20171     * control over the start time and invalidation, but you
20172     * must make sure that 1) the animation has a start time set, and
20173     * 2) the view's parent (which controls animations on its children)
20174     * will be invalidated when the animation is supposed to
20175     * start.
20176     *
20177     * @param animation The next animation, or null.
20178     */
20179    public void setAnimation(Animation animation) {
20180        mCurrentAnimation = animation;
20181
20182        if (animation != null) {
20183            // If the screen is off assume the animation start time is now instead of
20184            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
20185            // would cause the animation to start when the screen turns back on
20186            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
20187                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
20188                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
20189            }
20190            animation.reset();
20191        }
20192    }
20193
20194    /**
20195     * Invoked by a parent ViewGroup to notify the start of the animation
20196     * currently associated with this view. If you override this method,
20197     * always call super.onAnimationStart();
20198     *
20199     * @see #setAnimation(android.view.animation.Animation)
20200     * @see #getAnimation()
20201     */
20202    @CallSuper
20203    protected void onAnimationStart() {
20204        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
20205    }
20206
20207    /**
20208     * Invoked by a parent ViewGroup to notify the end of the animation
20209     * currently associated with this view. If you override this method,
20210     * always call super.onAnimationEnd();
20211     *
20212     * @see #setAnimation(android.view.animation.Animation)
20213     * @see #getAnimation()
20214     */
20215    @CallSuper
20216    protected void onAnimationEnd() {
20217        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
20218    }
20219
20220    /**
20221     * Invoked if there is a Transform that involves alpha. Subclass that can
20222     * draw themselves with the specified alpha should return true, and then
20223     * respect that alpha when their onDraw() is called. If this returns false
20224     * then the view may be redirected to draw into an offscreen buffer to
20225     * fulfill the request, which will look fine, but may be slower than if the
20226     * subclass handles it internally. The default implementation returns false.
20227     *
20228     * @param alpha The alpha (0..255) to apply to the view's drawing
20229     * @return true if the view can draw with the specified alpha.
20230     */
20231    protected boolean onSetAlpha(int alpha) {
20232        return false;
20233    }
20234
20235    /**
20236     * This is used by the RootView to perform an optimization when
20237     * the view hierarchy contains one or several SurfaceView.
20238     * SurfaceView is always considered transparent, but its children are not,
20239     * therefore all View objects remove themselves from the global transparent
20240     * region (passed as a parameter to this function).
20241     *
20242     * @param region The transparent region for this ViewAncestor (window).
20243     *
20244     * @return Returns true if the effective visibility of the view at this
20245     * point is opaque, regardless of the transparent region; returns false
20246     * if it is possible for underlying windows to be seen behind the view.
20247     *
20248     * {@hide}
20249     */
20250    public boolean gatherTransparentRegion(Region region) {
20251        final AttachInfo attachInfo = mAttachInfo;
20252        if (region != null && attachInfo != null) {
20253            final int pflags = mPrivateFlags;
20254            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
20255                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
20256                // remove it from the transparent region.
20257                final int[] location = attachInfo.mTransparentLocation;
20258                getLocationInWindow(location);
20259                // When a view has Z value, then it will be better to leave some area below the view
20260                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
20261                // the bottom part needs more offset than the left, top and right parts due to the
20262                // spot light effects.
20263                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
20264                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
20265                        location[0] + mRight - mLeft + shadowOffset,
20266                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
20267            } else {
20268                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
20269                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
20270                    // the background drawable's non-transparent parts from this transparent region.
20271                    applyDrawableToTransparentRegion(mBackground, region);
20272                }
20273                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20274                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
20275                    // Similarly, we remove the foreground drawable's non-transparent parts.
20276                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
20277                }
20278            }
20279        }
20280        return true;
20281    }
20282
20283    /**
20284     * Play a sound effect for this view.
20285     *
20286     * <p>The framework will play sound effects for some built in actions, such as
20287     * clicking, but you may wish to play these effects in your widget,
20288     * for instance, for internal navigation.
20289     *
20290     * <p>The sound effect will only be played if sound effects are enabled by the user, and
20291     * {@link #isSoundEffectsEnabled()} is true.
20292     *
20293     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
20294     */
20295    public void playSoundEffect(int soundConstant) {
20296        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
20297            return;
20298        }
20299        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
20300    }
20301
20302    /**
20303     * BZZZTT!!1!
20304     *
20305     * <p>Provide haptic feedback to the user for this view.
20306     *
20307     * <p>The framework will provide haptic feedback for some built in actions,
20308     * such as long presses, but you may wish to provide feedback for your
20309     * own widget.
20310     *
20311     * <p>The feedback will only be performed if
20312     * {@link #isHapticFeedbackEnabled()} is true.
20313     *
20314     * @param feedbackConstant One of the constants defined in
20315     * {@link HapticFeedbackConstants}
20316     */
20317    public boolean performHapticFeedback(int feedbackConstant) {
20318        return performHapticFeedback(feedbackConstant, 0);
20319    }
20320
20321    /**
20322     * BZZZTT!!1!
20323     *
20324     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
20325     *
20326     * @param feedbackConstant One of the constants defined in
20327     * {@link HapticFeedbackConstants}
20328     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
20329     */
20330    public boolean performHapticFeedback(int feedbackConstant, int flags) {
20331        if (mAttachInfo == null) {
20332            return false;
20333        }
20334        //noinspection SimplifiableIfStatement
20335        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
20336                && !isHapticFeedbackEnabled()) {
20337            return false;
20338        }
20339        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
20340                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
20341    }
20342
20343    /**
20344     * Request that the visibility of the status bar or other screen/window
20345     * decorations be changed.
20346     *
20347     * <p>This method is used to put the over device UI into temporary modes
20348     * where the user's attention is focused more on the application content,
20349     * by dimming or hiding surrounding system affordances.  This is typically
20350     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
20351     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
20352     * to be placed behind the action bar (and with these flags other system
20353     * affordances) so that smooth transitions between hiding and showing them
20354     * can be done.
20355     *
20356     * <p>Two representative examples of the use of system UI visibility is
20357     * implementing a content browsing application (like a magazine reader)
20358     * and a video playing application.
20359     *
20360     * <p>The first code shows a typical implementation of a View in a content
20361     * browsing application.  In this implementation, the application goes
20362     * into a content-oriented mode by hiding the status bar and action bar,
20363     * and putting the navigation elements into lights out mode.  The user can
20364     * then interact with content while in this mode.  Such an application should
20365     * provide an easy way for the user to toggle out of the mode (such as to
20366     * check information in the status bar or access notifications).  In the
20367     * implementation here, this is done simply by tapping on the content.
20368     *
20369     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
20370     *      content}
20371     *
20372     * <p>This second code sample shows a typical implementation of a View
20373     * in a video playing application.  In this situation, while the video is
20374     * playing the application would like to go into a complete full-screen mode,
20375     * to use as much of the display as possible for the video.  When in this state
20376     * the user can not interact with the application; the system intercepts
20377     * touching on the screen to pop the UI out of full screen mode.  See
20378     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
20379     *
20380     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
20381     *      content}
20382     *
20383     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20384     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20385     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20386     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20387     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20388     */
20389    public void setSystemUiVisibility(int visibility) {
20390        if (visibility != mSystemUiVisibility) {
20391            mSystemUiVisibility = visibility;
20392            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20393                mParent.recomputeViewAttributes(this);
20394            }
20395        }
20396    }
20397
20398    /**
20399     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
20400     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20401     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20402     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20403     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20404     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20405     */
20406    public int getSystemUiVisibility() {
20407        return mSystemUiVisibility;
20408    }
20409
20410    /**
20411     * Returns the current system UI visibility that is currently set for
20412     * the entire window.  This is the combination of the
20413     * {@link #setSystemUiVisibility(int)} values supplied by all of the
20414     * views in the window.
20415     */
20416    public int getWindowSystemUiVisibility() {
20417        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
20418    }
20419
20420    /**
20421     * Override to find out when the window's requested system UI visibility
20422     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
20423     * This is different from the callbacks received through
20424     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
20425     * in that this is only telling you about the local request of the window,
20426     * not the actual values applied by the system.
20427     */
20428    public void onWindowSystemUiVisibilityChanged(int visible) {
20429    }
20430
20431    /**
20432     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
20433     * the view hierarchy.
20434     */
20435    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
20436        onWindowSystemUiVisibilityChanged(visible);
20437    }
20438
20439    /**
20440     * Set a listener to receive callbacks when the visibility of the system bar changes.
20441     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
20442     */
20443    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
20444        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
20445        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20446            mParent.recomputeViewAttributes(this);
20447        }
20448    }
20449
20450    /**
20451     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
20452     * the view hierarchy.
20453     */
20454    public void dispatchSystemUiVisibilityChanged(int visibility) {
20455        ListenerInfo li = mListenerInfo;
20456        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
20457            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
20458                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
20459        }
20460    }
20461
20462    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
20463        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
20464        if (val != mSystemUiVisibility) {
20465            setSystemUiVisibility(val);
20466            return true;
20467        }
20468        return false;
20469    }
20470
20471    /** @hide */
20472    public void setDisabledSystemUiVisibility(int flags) {
20473        if (mAttachInfo != null) {
20474            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
20475                mAttachInfo.mDisabledSystemUiVisibility = flags;
20476                if (mParent != null) {
20477                    mParent.recomputeViewAttributes(this);
20478                }
20479            }
20480        }
20481    }
20482
20483    /**
20484     * Creates an image that the system displays during the drag and drop
20485     * operation. This is called a &quot;drag shadow&quot;. The default implementation
20486     * for a DragShadowBuilder based on a View returns an image that has exactly the same
20487     * appearance as the given View. The default also positions the center of the drag shadow
20488     * directly under the touch point. If no View is provided (the constructor with no parameters
20489     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
20490     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
20491     * default is an invisible drag shadow.
20492     * <p>
20493     * You are not required to use the View you provide to the constructor as the basis of the
20494     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
20495     * anything you want as the drag shadow.
20496     * </p>
20497     * <p>
20498     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
20499     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
20500     *  size and position of the drag shadow. It uses this data to construct a
20501     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
20502     *  so that your application can draw the shadow image in the Canvas.
20503     * </p>
20504     *
20505     * <div class="special reference">
20506     * <h3>Developer Guides</h3>
20507     * <p>For a guide to implementing drag and drop features, read the
20508     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20509     * </div>
20510     */
20511    public static class DragShadowBuilder {
20512        private final WeakReference<View> mView;
20513
20514        /**
20515         * Constructs a shadow image builder based on a View. By default, the resulting drag
20516         * shadow will have the same appearance and dimensions as the View, with the touch point
20517         * over the center of the View.
20518         * @param view A View. Any View in scope can be used.
20519         */
20520        public DragShadowBuilder(View view) {
20521            mView = new WeakReference<View>(view);
20522        }
20523
20524        /**
20525         * Construct a shadow builder object with no associated View.  This
20526         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
20527         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
20528         * to supply the drag shadow's dimensions and appearance without
20529         * reference to any View object. If they are not overridden, then the result is an
20530         * invisible drag shadow.
20531         */
20532        public DragShadowBuilder() {
20533            mView = new WeakReference<View>(null);
20534        }
20535
20536        /**
20537         * Returns the View object that had been passed to the
20538         * {@link #View.DragShadowBuilder(View)}
20539         * constructor.  If that View parameter was {@code null} or if the
20540         * {@link #View.DragShadowBuilder()}
20541         * constructor was used to instantiate the builder object, this method will return
20542         * null.
20543         *
20544         * @return The View object associate with this builder object.
20545         */
20546        @SuppressWarnings({"JavadocReference"})
20547        final public View getView() {
20548            return mView.get();
20549        }
20550
20551        /**
20552         * Provides the metrics for the shadow image. These include the dimensions of
20553         * the shadow image, and the point within that shadow that should
20554         * be centered under the touch location while dragging.
20555         * <p>
20556         * The default implementation sets the dimensions of the shadow to be the
20557         * same as the dimensions of the View itself and centers the shadow under
20558         * the touch point.
20559         * </p>
20560         *
20561         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
20562         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
20563         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
20564         * image.
20565         *
20566         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
20567         * shadow image that should be underneath the touch point during the drag and drop
20568         * operation. Your application must set {@link android.graphics.Point#x} to the
20569         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
20570         */
20571        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
20572            final View view = mView.get();
20573            if (view != null) {
20574                outShadowSize.set(view.getWidth(), view.getHeight());
20575                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
20576            } else {
20577                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
20578            }
20579        }
20580
20581        /**
20582         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
20583         * based on the dimensions it received from the
20584         * {@link #onProvideShadowMetrics(Point, Point)} callback.
20585         *
20586         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
20587         */
20588        public void onDrawShadow(Canvas canvas) {
20589            final View view = mView.get();
20590            if (view != null) {
20591                view.draw(canvas);
20592            } else {
20593                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
20594            }
20595        }
20596    }
20597
20598    /**
20599     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
20600     * startDragAndDrop()} for newer platform versions.
20601     */
20602    @Deprecated
20603    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
20604                                   Object myLocalState, int flags) {
20605        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
20606    }
20607
20608    /**
20609     * Starts a drag and drop operation. When your application calls this method, it passes a
20610     * {@link android.view.View.DragShadowBuilder} object to the system. The
20611     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
20612     * to get metrics for the drag shadow, and then calls the object's
20613     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
20614     * <p>
20615     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
20616     *  drag events to all the View objects in your application that are currently visible. It does
20617     *  this either by calling the View object's drag listener (an implementation of
20618     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
20619     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
20620     *  Both are passed a {@link android.view.DragEvent} object that has a
20621     *  {@link android.view.DragEvent#getAction()} value of
20622     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
20623     * </p>
20624     * <p>
20625     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
20626     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
20627     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
20628     * to the View the user selected for dragging.
20629     * </p>
20630     * @param data A {@link android.content.ClipData} object pointing to the data to be
20631     * transferred by the drag and drop operation.
20632     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20633     * drag shadow.
20634     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
20635     * drop operation. This Object is put into every DragEvent object sent by the system during the
20636     * current drag.
20637     * <p>
20638     * myLocalState is a lightweight mechanism for the sending information from the dragged View
20639     * to the target Views. For example, it can contain flags that differentiate between a
20640     * a copy operation and a move operation.
20641     * </p>
20642     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
20643     * flags, or any combination of the following:
20644     *     <ul>
20645     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
20646     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
20647     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
20648     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
20649     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
20650     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
20651     *     </ul>
20652     * @return {@code true} if the method completes successfully, or
20653     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
20654     * do a drag, and so no drag operation is in progress.
20655     */
20656    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
20657            Object myLocalState, int flags) {
20658        if (ViewDebug.DEBUG_DRAG) {
20659            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
20660        }
20661        if (mAttachInfo == null) {
20662            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
20663            return false;
20664        }
20665
20666        data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
20667
20668        boolean okay = false;
20669
20670        Point shadowSize = new Point();
20671        Point shadowTouchPoint = new Point();
20672        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
20673
20674        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
20675                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
20676            throw new IllegalStateException("Drag shadow dimensions must not be negative");
20677        }
20678
20679        if (ViewDebug.DEBUG_DRAG) {
20680            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
20681                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
20682        }
20683        if (mAttachInfo.mDragSurface != null) {
20684            mAttachInfo.mDragSurface.release();
20685        }
20686        mAttachInfo.mDragSurface = new Surface();
20687        try {
20688            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
20689                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
20690            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
20691                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
20692            if (mAttachInfo.mDragToken != null) {
20693                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20694                try {
20695                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20696                    shadowBuilder.onDrawShadow(canvas);
20697                } finally {
20698                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20699                }
20700
20701                final ViewRootImpl root = getViewRootImpl();
20702
20703                // Cache the local state object for delivery with DragEvents
20704                root.setLocalDragState(myLocalState);
20705
20706                // repurpose 'shadowSize' for the last touch point
20707                root.getLastTouchPoint(shadowSize);
20708
20709                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
20710                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
20711                        shadowTouchPoint.x, shadowTouchPoint.y, data);
20712                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
20713            }
20714        } catch (Exception e) {
20715            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
20716            mAttachInfo.mDragSurface.destroy();
20717            mAttachInfo.mDragSurface = null;
20718        }
20719
20720        return okay;
20721    }
20722
20723    /**
20724     * Cancels an ongoing drag and drop operation.
20725     * <p>
20726     * A {@link android.view.DragEvent} object with
20727     * {@link android.view.DragEvent#getAction()} value of
20728     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
20729     * {@link android.view.DragEvent#getResult()} value of {@code false}
20730     * will be sent to every
20731     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
20732     * even if they are not currently visible.
20733     * </p>
20734     * <p>
20735     * This method can be called on any View in the same window as the View on which
20736     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
20737     * was called.
20738     * </p>
20739     */
20740    public final void cancelDragAndDrop() {
20741        if (ViewDebug.DEBUG_DRAG) {
20742            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
20743        }
20744        if (mAttachInfo == null) {
20745            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
20746            return;
20747        }
20748        if (mAttachInfo.mDragToken != null) {
20749            try {
20750                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
20751            } catch (Exception e) {
20752                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
20753            }
20754            mAttachInfo.mDragToken = null;
20755        } else {
20756            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
20757        }
20758    }
20759
20760    /**
20761     * Updates the drag shadow for the ongoing drag and drop operation.
20762     *
20763     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20764     * new drag shadow.
20765     */
20766    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
20767        if (ViewDebug.DEBUG_DRAG) {
20768            Log.d(VIEW_LOG_TAG, "updateDragShadow");
20769        }
20770        if (mAttachInfo == null) {
20771            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
20772            return;
20773        }
20774        if (mAttachInfo.mDragToken != null) {
20775            try {
20776                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20777                try {
20778                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20779                    shadowBuilder.onDrawShadow(canvas);
20780                } finally {
20781                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20782                }
20783            } catch (Exception e) {
20784                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
20785            }
20786        } else {
20787            Log.e(VIEW_LOG_TAG, "No active drag");
20788        }
20789    }
20790
20791    /**
20792     * Starts a move from {startX, startY}, the amount of the movement will be the offset
20793     * between {startX, startY} and the new cursor positon.
20794     * @param startX horizontal coordinate where the move started.
20795     * @param startY vertical coordinate where the move started.
20796     * @return whether moving was started successfully.
20797     * @hide
20798     */
20799    public final boolean startMovingTask(float startX, float startY) {
20800        if (ViewDebug.DEBUG_POSITIONING) {
20801            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
20802        }
20803        try {
20804            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
20805        } catch (RemoteException e) {
20806            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
20807        }
20808        return false;
20809    }
20810
20811    /**
20812     * Handles drag events sent by the system following a call to
20813     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
20814     * startDragAndDrop()}.
20815     *<p>
20816     * When the system calls this method, it passes a
20817     * {@link android.view.DragEvent} object. A call to
20818     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
20819     * in DragEvent. The method uses these to determine what is happening in the drag and drop
20820     * operation.
20821     * @param event The {@link android.view.DragEvent} sent by the system.
20822     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
20823     * in DragEvent, indicating the type of drag event represented by this object.
20824     * @return {@code true} if the method was successful, otherwise {@code false}.
20825     * <p>
20826     *  The method should return {@code true} in response to an action type of
20827     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
20828     *  operation.
20829     * </p>
20830     * <p>
20831     *  The method should also return {@code true} in response to an action type of
20832     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
20833     *  {@code false} if it didn't.
20834     * </p>
20835     */
20836    public boolean onDragEvent(DragEvent event) {
20837        return false;
20838    }
20839
20840    /**
20841     * Detects if this View is enabled and has a drag event listener.
20842     * If both are true, then it calls the drag event listener with the
20843     * {@link android.view.DragEvent} it received. If the drag event listener returns
20844     * {@code true}, then dispatchDragEvent() returns {@code true}.
20845     * <p>
20846     * For all other cases, the method calls the
20847     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
20848     * method and returns its result.
20849     * </p>
20850     * <p>
20851     * This ensures that a drag event is always consumed, even if the View does not have a drag
20852     * event listener. However, if the View has a listener and the listener returns true, then
20853     * onDragEvent() is not called.
20854     * </p>
20855     */
20856    public boolean dispatchDragEvent(DragEvent event) {
20857        ListenerInfo li = mListenerInfo;
20858        //noinspection SimplifiableIfStatement
20859        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
20860                && li.mOnDragListener.onDrag(this, event)) {
20861            return true;
20862        }
20863        return onDragEvent(event);
20864    }
20865
20866    boolean canAcceptDrag() {
20867        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
20868    }
20869
20870    /**
20871     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
20872     * it is ever exposed at all.
20873     * @hide
20874     */
20875    public void onCloseSystemDialogs(String reason) {
20876    }
20877
20878    /**
20879     * Given a Drawable whose bounds have been set to draw into this view,
20880     * update a Region being computed for
20881     * {@link #gatherTransparentRegion(android.graphics.Region)} so
20882     * that any non-transparent parts of the Drawable are removed from the
20883     * given transparent region.
20884     *
20885     * @param dr The Drawable whose transparency is to be applied to the region.
20886     * @param region A Region holding the current transparency information,
20887     * where any parts of the region that are set are considered to be
20888     * transparent.  On return, this region will be modified to have the
20889     * transparency information reduced by the corresponding parts of the
20890     * Drawable that are not transparent.
20891     * {@hide}
20892     */
20893    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
20894        if (DBG) {
20895            Log.i("View", "Getting transparent region for: " + this);
20896        }
20897        final Region r = dr.getTransparentRegion();
20898        final Rect db = dr.getBounds();
20899        final AttachInfo attachInfo = mAttachInfo;
20900        if (r != null && attachInfo != null) {
20901            final int w = getRight()-getLeft();
20902            final int h = getBottom()-getTop();
20903            if (db.left > 0) {
20904                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
20905                r.op(0, 0, db.left, h, Region.Op.UNION);
20906            }
20907            if (db.right < w) {
20908                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
20909                r.op(db.right, 0, w, h, Region.Op.UNION);
20910            }
20911            if (db.top > 0) {
20912                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
20913                r.op(0, 0, w, db.top, Region.Op.UNION);
20914            }
20915            if (db.bottom < h) {
20916                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
20917                r.op(0, db.bottom, w, h, Region.Op.UNION);
20918            }
20919            final int[] location = attachInfo.mTransparentLocation;
20920            getLocationInWindow(location);
20921            r.translate(location[0], location[1]);
20922            region.op(r, Region.Op.INTERSECT);
20923        } else {
20924            region.op(db, Region.Op.DIFFERENCE);
20925        }
20926    }
20927
20928    private void checkForLongClick(int delayOffset, float x, float y) {
20929        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
20930            mHasPerformedLongPress = false;
20931
20932            if (mPendingCheckForLongPress == null) {
20933                mPendingCheckForLongPress = new CheckForLongPress();
20934            }
20935            mPendingCheckForLongPress.setAnchor(x, y);
20936            mPendingCheckForLongPress.rememberWindowAttachCount();
20937            postDelayed(mPendingCheckForLongPress,
20938                    ViewConfiguration.getLongPressTimeout() - delayOffset);
20939        }
20940    }
20941
20942    /**
20943     * Inflate a view from an XML resource.  This convenience method wraps the {@link
20944     * LayoutInflater} class, which provides a full range of options for view inflation.
20945     *
20946     * @param context The Context object for your activity or application.
20947     * @param resource The resource ID to inflate
20948     * @param root A view group that will be the parent.  Used to properly inflate the
20949     * layout_* parameters.
20950     * @see LayoutInflater
20951     */
20952    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
20953        LayoutInflater factory = LayoutInflater.from(context);
20954        return factory.inflate(resource, root);
20955    }
20956
20957    /**
20958     * Scroll the view with standard behavior for scrolling beyond the normal
20959     * content boundaries. Views that call this method should override
20960     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
20961     * results of an over-scroll operation.
20962     *
20963     * Views can use this method to handle any touch or fling-based scrolling.
20964     *
20965     * @param deltaX Change in X in pixels
20966     * @param deltaY Change in Y in pixels
20967     * @param scrollX Current X scroll value in pixels before applying deltaX
20968     * @param scrollY Current Y scroll value in pixels before applying deltaY
20969     * @param scrollRangeX Maximum content scroll range along the X axis
20970     * @param scrollRangeY Maximum content scroll range along the Y axis
20971     * @param maxOverScrollX Number of pixels to overscroll by in either direction
20972     *          along the X axis.
20973     * @param maxOverScrollY Number of pixels to overscroll by in either direction
20974     *          along the Y axis.
20975     * @param isTouchEvent true if this scroll operation is the result of a touch event.
20976     * @return true if scrolling was clamped to an over-scroll boundary along either
20977     *          axis, false otherwise.
20978     */
20979    @SuppressWarnings({"UnusedParameters"})
20980    protected boolean overScrollBy(int deltaX, int deltaY,
20981            int scrollX, int scrollY,
20982            int scrollRangeX, int scrollRangeY,
20983            int maxOverScrollX, int maxOverScrollY,
20984            boolean isTouchEvent) {
20985        final int overScrollMode = mOverScrollMode;
20986        final boolean canScrollHorizontal =
20987                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
20988        final boolean canScrollVertical =
20989                computeVerticalScrollRange() > computeVerticalScrollExtent();
20990        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
20991                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
20992        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
20993                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
20994
20995        int newScrollX = scrollX + deltaX;
20996        if (!overScrollHorizontal) {
20997            maxOverScrollX = 0;
20998        }
20999
21000        int newScrollY = scrollY + deltaY;
21001        if (!overScrollVertical) {
21002            maxOverScrollY = 0;
21003        }
21004
21005        // Clamp values if at the limits and record
21006        final int left = -maxOverScrollX;
21007        final int right = maxOverScrollX + scrollRangeX;
21008        final int top = -maxOverScrollY;
21009        final int bottom = maxOverScrollY + scrollRangeY;
21010
21011        boolean clampedX = false;
21012        if (newScrollX > right) {
21013            newScrollX = right;
21014            clampedX = true;
21015        } else if (newScrollX < left) {
21016            newScrollX = left;
21017            clampedX = true;
21018        }
21019
21020        boolean clampedY = false;
21021        if (newScrollY > bottom) {
21022            newScrollY = bottom;
21023            clampedY = true;
21024        } else if (newScrollY < top) {
21025            newScrollY = top;
21026            clampedY = true;
21027        }
21028
21029        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
21030
21031        return clampedX || clampedY;
21032    }
21033
21034    /**
21035     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
21036     * respond to the results of an over-scroll operation.
21037     *
21038     * @param scrollX New X scroll value in pixels
21039     * @param scrollY New Y scroll value in pixels
21040     * @param clampedX True if scrollX was clamped to an over-scroll boundary
21041     * @param clampedY True if scrollY was clamped to an over-scroll boundary
21042     */
21043    protected void onOverScrolled(int scrollX, int scrollY,
21044            boolean clampedX, boolean clampedY) {
21045        // Intentionally empty.
21046    }
21047
21048    /**
21049     * Returns the over-scroll mode for this view. The result will be
21050     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21051     * (allow over-scrolling only if the view content is larger than the container),
21052     * or {@link #OVER_SCROLL_NEVER}.
21053     *
21054     * @return This view's over-scroll mode.
21055     */
21056    public int getOverScrollMode() {
21057        return mOverScrollMode;
21058    }
21059
21060    /**
21061     * Set the over-scroll mode for this view. Valid over-scroll modes are
21062     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21063     * (allow over-scrolling only if the view content is larger than the container),
21064     * or {@link #OVER_SCROLL_NEVER}.
21065     *
21066     * Setting the over-scroll mode of a view will have an effect only if the
21067     * view is capable of scrolling.
21068     *
21069     * @param overScrollMode The new over-scroll mode for this view.
21070     */
21071    public void setOverScrollMode(int overScrollMode) {
21072        if (overScrollMode != OVER_SCROLL_ALWAYS &&
21073                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
21074                overScrollMode != OVER_SCROLL_NEVER) {
21075            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
21076        }
21077        mOverScrollMode = overScrollMode;
21078    }
21079
21080    /**
21081     * Enable or disable nested scrolling for this view.
21082     *
21083     * <p>If this property is set to true the view will be permitted to initiate nested
21084     * scrolling operations with a compatible parent view in the current hierarchy. If this
21085     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
21086     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
21087     * the nested scroll.</p>
21088     *
21089     * @param enabled true to enable nested scrolling, false to disable
21090     *
21091     * @see #isNestedScrollingEnabled()
21092     */
21093    public void setNestedScrollingEnabled(boolean enabled) {
21094        if (enabled) {
21095            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
21096        } else {
21097            stopNestedScroll();
21098            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
21099        }
21100    }
21101
21102    /**
21103     * Returns true if nested scrolling is enabled for this view.
21104     *
21105     * <p>If nested scrolling is enabled and this View class implementation supports it,
21106     * this view will act as a nested scrolling child view when applicable, forwarding data
21107     * about the scroll operation in progress to a compatible and cooperating nested scrolling
21108     * parent.</p>
21109     *
21110     * @return true if nested scrolling is enabled
21111     *
21112     * @see #setNestedScrollingEnabled(boolean)
21113     */
21114    public boolean isNestedScrollingEnabled() {
21115        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
21116                PFLAG3_NESTED_SCROLLING_ENABLED;
21117    }
21118
21119    /**
21120     * Begin a nestable scroll operation along the given axes.
21121     *
21122     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
21123     *
21124     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
21125     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
21126     * In the case of touch scrolling the nested scroll will be terminated automatically in
21127     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
21128     * In the event of programmatic scrolling the caller must explicitly call
21129     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
21130     *
21131     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
21132     * If it returns false the caller may ignore the rest of this contract until the next scroll.
21133     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
21134     *
21135     * <p>At each incremental step of the scroll the caller should invoke
21136     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
21137     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
21138     * parent at least partially consumed the scroll and the caller should adjust the amount it
21139     * scrolls by.</p>
21140     *
21141     * <p>After applying the remainder of the scroll delta the caller should invoke
21142     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
21143     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
21144     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
21145     * </p>
21146     *
21147     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
21148     *             {@link #SCROLL_AXIS_VERTICAL}.
21149     * @return true if a cooperative parent was found and nested scrolling has been enabled for
21150     *         the current gesture.
21151     *
21152     * @see #stopNestedScroll()
21153     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21154     * @see #dispatchNestedScroll(int, int, int, int, int[])
21155     */
21156    public boolean startNestedScroll(int axes) {
21157        if (hasNestedScrollingParent()) {
21158            // Already in progress
21159            return true;
21160        }
21161        if (isNestedScrollingEnabled()) {
21162            ViewParent p = getParent();
21163            View child = this;
21164            while (p != null) {
21165                try {
21166                    if (p.onStartNestedScroll(child, this, axes)) {
21167                        mNestedScrollingParent = p;
21168                        p.onNestedScrollAccepted(child, this, axes);
21169                        return true;
21170                    }
21171                } catch (AbstractMethodError e) {
21172                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
21173                            "method onStartNestedScroll", e);
21174                    // Allow the search upward to continue
21175                }
21176                if (p instanceof View) {
21177                    child = (View) p;
21178                }
21179                p = p.getParent();
21180            }
21181        }
21182        return false;
21183    }
21184
21185    /**
21186     * Stop a nested scroll in progress.
21187     *
21188     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
21189     *
21190     * @see #startNestedScroll(int)
21191     */
21192    public void stopNestedScroll() {
21193        if (mNestedScrollingParent != null) {
21194            mNestedScrollingParent.onStopNestedScroll(this);
21195            mNestedScrollingParent = null;
21196        }
21197    }
21198
21199    /**
21200     * Returns true if this view has a nested scrolling parent.
21201     *
21202     * <p>The presence of a nested scrolling parent indicates that this view has initiated
21203     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
21204     *
21205     * @return whether this view has a nested scrolling parent
21206     */
21207    public boolean hasNestedScrollingParent() {
21208        return mNestedScrollingParent != null;
21209    }
21210
21211    /**
21212     * Dispatch one step of a nested scroll in progress.
21213     *
21214     * <p>Implementations of views that support nested scrolling should call this to report
21215     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
21216     * is not currently in progress or nested scrolling is not
21217     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
21218     *
21219     * <p>Compatible View implementations should also call
21220     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
21221     * consuming a component of the scroll event themselves.</p>
21222     *
21223     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
21224     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
21225     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
21226     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
21227     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21228     *                       in local view coordinates of this view from before this operation
21229     *                       to after it completes. View implementations may use this to adjust
21230     *                       expected input coordinate tracking.
21231     * @return true if the event was dispatched, false if it could not be dispatched.
21232     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21233     */
21234    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
21235            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
21236        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21237            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
21238                int startX = 0;
21239                int startY = 0;
21240                if (offsetInWindow != null) {
21241                    getLocationInWindow(offsetInWindow);
21242                    startX = offsetInWindow[0];
21243                    startY = offsetInWindow[1];
21244                }
21245
21246                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
21247                        dxUnconsumed, dyUnconsumed);
21248
21249                if (offsetInWindow != null) {
21250                    getLocationInWindow(offsetInWindow);
21251                    offsetInWindow[0] -= startX;
21252                    offsetInWindow[1] -= startY;
21253                }
21254                return true;
21255            } else if (offsetInWindow != null) {
21256                // No motion, no dispatch. Keep offsetInWindow up to date.
21257                offsetInWindow[0] = 0;
21258                offsetInWindow[1] = 0;
21259            }
21260        }
21261        return false;
21262    }
21263
21264    /**
21265     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
21266     *
21267     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
21268     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
21269     * scrolling operation to consume some or all of the scroll operation before the child view
21270     * consumes it.</p>
21271     *
21272     * @param dx Horizontal scroll distance in pixels
21273     * @param dy Vertical scroll distance in pixels
21274     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
21275     *                 and consumed[1] the consumed dy.
21276     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21277     *                       in local view coordinates of this view from before this operation
21278     *                       to after it completes. View implementations may use this to adjust
21279     *                       expected input coordinate tracking.
21280     * @return true if the parent consumed some or all of the scroll delta
21281     * @see #dispatchNestedScroll(int, int, int, int, int[])
21282     */
21283    public boolean dispatchNestedPreScroll(int dx, int dy,
21284            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
21285        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21286            if (dx != 0 || dy != 0) {
21287                int startX = 0;
21288                int startY = 0;
21289                if (offsetInWindow != null) {
21290                    getLocationInWindow(offsetInWindow);
21291                    startX = offsetInWindow[0];
21292                    startY = offsetInWindow[1];
21293                }
21294
21295                if (consumed == null) {
21296                    if (mTempNestedScrollConsumed == null) {
21297                        mTempNestedScrollConsumed = new int[2];
21298                    }
21299                    consumed = mTempNestedScrollConsumed;
21300                }
21301                consumed[0] = 0;
21302                consumed[1] = 0;
21303                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
21304
21305                if (offsetInWindow != null) {
21306                    getLocationInWindow(offsetInWindow);
21307                    offsetInWindow[0] -= startX;
21308                    offsetInWindow[1] -= startY;
21309                }
21310                return consumed[0] != 0 || consumed[1] != 0;
21311            } else if (offsetInWindow != null) {
21312                offsetInWindow[0] = 0;
21313                offsetInWindow[1] = 0;
21314            }
21315        }
21316        return false;
21317    }
21318
21319    /**
21320     * Dispatch a fling to a nested scrolling parent.
21321     *
21322     * <p>This method should be used to indicate that a nested scrolling child has detected
21323     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
21324     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
21325     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
21326     * along a scrollable axis.</p>
21327     *
21328     * <p>If a nested scrolling child view would normally fling but it is at the edge of
21329     * its own content, it can use this method to delegate the fling to its nested scrolling
21330     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
21331     *
21332     * @param velocityX Horizontal fling velocity in pixels per second
21333     * @param velocityY Vertical fling velocity in pixels per second
21334     * @param consumed true if the child consumed the fling, false otherwise
21335     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
21336     */
21337    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
21338        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21339            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
21340        }
21341        return false;
21342    }
21343
21344    /**
21345     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
21346     *
21347     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
21348     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
21349     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
21350     * before the child view consumes it. If this method returns <code>true</code>, a nested
21351     * parent view consumed the fling and this view should not scroll as a result.</p>
21352     *
21353     * <p>For a better user experience, only one view in a nested scrolling chain should consume
21354     * the fling at a time. If a parent view consumed the fling this method will return false.
21355     * Custom view implementations should account for this in two ways:</p>
21356     *
21357     * <ul>
21358     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
21359     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
21360     *     position regardless.</li>
21361     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
21362     *     even to settle back to a valid idle position.</li>
21363     * </ul>
21364     *
21365     * <p>Views should also not offer fling velocities to nested parent views along an axis
21366     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
21367     * should not offer a horizontal fling velocity to its parents since scrolling along that
21368     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
21369     *
21370     * @param velocityX Horizontal fling velocity in pixels per second
21371     * @param velocityY Vertical fling velocity in pixels per second
21372     * @return true if a nested scrolling parent consumed the fling
21373     */
21374    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
21375        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21376            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
21377        }
21378        return false;
21379    }
21380
21381    /**
21382     * Gets a scale factor that determines the distance the view should scroll
21383     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
21384     * @return The vertical scroll scale factor.
21385     * @hide
21386     */
21387    protected float getVerticalScrollFactor() {
21388        if (mVerticalScrollFactor == 0) {
21389            TypedValue outValue = new TypedValue();
21390            if (!mContext.getTheme().resolveAttribute(
21391                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
21392                throw new IllegalStateException(
21393                        "Expected theme to define listPreferredItemHeight.");
21394            }
21395            mVerticalScrollFactor = outValue.getDimension(
21396                    mContext.getResources().getDisplayMetrics());
21397        }
21398        return mVerticalScrollFactor;
21399    }
21400
21401    /**
21402     * Gets a scale factor that determines the distance the view should scroll
21403     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
21404     * @return The horizontal scroll scale factor.
21405     * @hide
21406     */
21407    protected float getHorizontalScrollFactor() {
21408        // TODO: Should use something else.
21409        return getVerticalScrollFactor();
21410    }
21411
21412    /**
21413     * Return the value specifying the text direction or policy that was set with
21414     * {@link #setTextDirection(int)}.
21415     *
21416     * @return the defined text direction. It can be one of:
21417     *
21418     * {@link #TEXT_DIRECTION_INHERIT},
21419     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21420     * {@link #TEXT_DIRECTION_ANY_RTL},
21421     * {@link #TEXT_DIRECTION_LTR},
21422     * {@link #TEXT_DIRECTION_RTL},
21423     * {@link #TEXT_DIRECTION_LOCALE},
21424     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21425     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21426     *
21427     * @attr ref android.R.styleable#View_textDirection
21428     *
21429     * @hide
21430     */
21431    @ViewDebug.ExportedProperty(category = "text", mapping = {
21432            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21433            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21434            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21435            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21436            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21437            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21438            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21439            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21440    })
21441    public int getRawTextDirection() {
21442        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
21443    }
21444
21445    /**
21446     * Set the text direction.
21447     *
21448     * @param textDirection the direction to set. Should be one of:
21449     *
21450     * {@link #TEXT_DIRECTION_INHERIT},
21451     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21452     * {@link #TEXT_DIRECTION_ANY_RTL},
21453     * {@link #TEXT_DIRECTION_LTR},
21454     * {@link #TEXT_DIRECTION_RTL},
21455     * {@link #TEXT_DIRECTION_LOCALE}
21456     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21457     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
21458     *
21459     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
21460     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
21461     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
21462     *
21463     * @attr ref android.R.styleable#View_textDirection
21464     */
21465    public void setTextDirection(int textDirection) {
21466        if (getRawTextDirection() != textDirection) {
21467            // Reset the current text direction and the resolved one
21468            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
21469            resetResolvedTextDirection();
21470            // Set the new text direction
21471            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
21472            // Do resolution
21473            resolveTextDirection();
21474            // Notify change
21475            onRtlPropertiesChanged(getLayoutDirection());
21476            // Refresh
21477            requestLayout();
21478            invalidate(true);
21479        }
21480    }
21481
21482    /**
21483     * Return the resolved text direction.
21484     *
21485     * @return the resolved text direction. Returns one of:
21486     *
21487     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21488     * {@link #TEXT_DIRECTION_ANY_RTL},
21489     * {@link #TEXT_DIRECTION_LTR},
21490     * {@link #TEXT_DIRECTION_RTL},
21491     * {@link #TEXT_DIRECTION_LOCALE},
21492     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21493     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21494     *
21495     * @attr ref android.R.styleable#View_textDirection
21496     */
21497    @ViewDebug.ExportedProperty(category = "text", mapping = {
21498            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21499            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21500            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21501            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21502            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21503            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21504            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21505            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21506    })
21507    public int getTextDirection() {
21508        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
21509    }
21510
21511    /**
21512     * Resolve the text direction.
21513     *
21514     * @return true if resolution has been done, false otherwise.
21515     *
21516     * @hide
21517     */
21518    public boolean resolveTextDirection() {
21519        // Reset any previous text direction resolution
21520        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21521
21522        if (hasRtlSupport()) {
21523            // Set resolved text direction flag depending on text direction flag
21524            final int textDirection = getRawTextDirection();
21525            switch(textDirection) {
21526                case TEXT_DIRECTION_INHERIT:
21527                    if (!canResolveTextDirection()) {
21528                        // We cannot do the resolution if there is no parent, so use the default one
21529                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21530                        // Resolution will need to happen again later
21531                        return false;
21532                    }
21533
21534                    // Parent has not yet resolved, so we still return the default
21535                    try {
21536                        if (!mParent.isTextDirectionResolved()) {
21537                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21538                            // Resolution will need to happen again later
21539                            return false;
21540                        }
21541                    } catch (AbstractMethodError e) {
21542                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21543                                " does not fully implement ViewParent", e);
21544                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
21545                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21546                        return true;
21547                    }
21548
21549                    // Set current resolved direction to the same value as the parent's one
21550                    int parentResolvedDirection;
21551                    try {
21552                        parentResolvedDirection = mParent.getTextDirection();
21553                    } catch (AbstractMethodError e) {
21554                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21555                                " does not fully implement ViewParent", e);
21556                        parentResolvedDirection = TEXT_DIRECTION_LTR;
21557                    }
21558                    switch (parentResolvedDirection) {
21559                        case TEXT_DIRECTION_FIRST_STRONG:
21560                        case TEXT_DIRECTION_ANY_RTL:
21561                        case TEXT_DIRECTION_LTR:
21562                        case TEXT_DIRECTION_RTL:
21563                        case TEXT_DIRECTION_LOCALE:
21564                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
21565                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
21566                            mPrivateFlags2 |=
21567                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21568                            break;
21569                        default:
21570                            // Default resolved direction is "first strong" heuristic
21571                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21572                    }
21573                    break;
21574                case TEXT_DIRECTION_FIRST_STRONG:
21575                case TEXT_DIRECTION_ANY_RTL:
21576                case TEXT_DIRECTION_LTR:
21577                case TEXT_DIRECTION_RTL:
21578                case TEXT_DIRECTION_LOCALE:
21579                case TEXT_DIRECTION_FIRST_STRONG_LTR:
21580                case TEXT_DIRECTION_FIRST_STRONG_RTL:
21581                    // Resolved direction is the same as text direction
21582                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21583                    break;
21584                default:
21585                    // Default resolved direction is "first strong" heuristic
21586                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21587            }
21588        } else {
21589            // Default resolved direction is "first strong" heuristic
21590            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21591        }
21592
21593        // Set to resolved
21594        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
21595        return true;
21596    }
21597
21598    /**
21599     * Check if text direction resolution can be done.
21600     *
21601     * @return true if text direction resolution can be done otherwise return false.
21602     */
21603    public boolean canResolveTextDirection() {
21604        switch (getRawTextDirection()) {
21605            case TEXT_DIRECTION_INHERIT:
21606                if (mParent != null) {
21607                    try {
21608                        return mParent.canResolveTextDirection();
21609                    } catch (AbstractMethodError e) {
21610                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21611                                " does not fully implement ViewParent", e);
21612                    }
21613                }
21614                return false;
21615
21616            default:
21617                return true;
21618        }
21619    }
21620
21621    /**
21622     * Reset resolved text direction. Text direction will be resolved during a call to
21623     * {@link #onMeasure(int, int)}.
21624     *
21625     * @hide
21626     */
21627    public void resetResolvedTextDirection() {
21628        // Reset any previous text direction resolution
21629        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21630        // Set to default value
21631        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21632    }
21633
21634    /**
21635     * @return true if text direction is inherited.
21636     *
21637     * @hide
21638     */
21639    public boolean isTextDirectionInherited() {
21640        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
21641    }
21642
21643    /**
21644     * @return true if text direction is resolved.
21645     */
21646    public boolean isTextDirectionResolved() {
21647        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
21648    }
21649
21650    /**
21651     * Return the value specifying the text alignment or policy that was set with
21652     * {@link #setTextAlignment(int)}.
21653     *
21654     * @return the defined text alignment. It can be one of:
21655     *
21656     * {@link #TEXT_ALIGNMENT_INHERIT},
21657     * {@link #TEXT_ALIGNMENT_GRAVITY},
21658     * {@link #TEXT_ALIGNMENT_CENTER},
21659     * {@link #TEXT_ALIGNMENT_TEXT_START},
21660     * {@link #TEXT_ALIGNMENT_TEXT_END},
21661     * {@link #TEXT_ALIGNMENT_VIEW_START},
21662     * {@link #TEXT_ALIGNMENT_VIEW_END}
21663     *
21664     * @attr ref android.R.styleable#View_textAlignment
21665     *
21666     * @hide
21667     */
21668    @ViewDebug.ExportedProperty(category = "text", mapping = {
21669            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21670            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21671            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21672            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21673            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21674            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21675            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21676    })
21677    @TextAlignment
21678    public int getRawTextAlignment() {
21679        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
21680    }
21681
21682    /**
21683     * Set the text alignment.
21684     *
21685     * @param textAlignment The text alignment to set. Should be one of
21686     *
21687     * {@link #TEXT_ALIGNMENT_INHERIT},
21688     * {@link #TEXT_ALIGNMENT_GRAVITY},
21689     * {@link #TEXT_ALIGNMENT_CENTER},
21690     * {@link #TEXT_ALIGNMENT_TEXT_START},
21691     * {@link #TEXT_ALIGNMENT_TEXT_END},
21692     * {@link #TEXT_ALIGNMENT_VIEW_START},
21693     * {@link #TEXT_ALIGNMENT_VIEW_END}
21694     *
21695     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
21696     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
21697     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
21698     *
21699     * @attr ref android.R.styleable#View_textAlignment
21700     */
21701    public void setTextAlignment(@TextAlignment int textAlignment) {
21702        if (textAlignment != getRawTextAlignment()) {
21703            // Reset the current and resolved text alignment
21704            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
21705            resetResolvedTextAlignment();
21706            // Set the new text alignment
21707            mPrivateFlags2 |=
21708                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
21709            // Do resolution
21710            resolveTextAlignment();
21711            // Notify change
21712            onRtlPropertiesChanged(getLayoutDirection());
21713            // Refresh
21714            requestLayout();
21715            invalidate(true);
21716        }
21717    }
21718
21719    /**
21720     * Return the resolved text alignment.
21721     *
21722     * @return the resolved text alignment. Returns one of:
21723     *
21724     * {@link #TEXT_ALIGNMENT_GRAVITY},
21725     * {@link #TEXT_ALIGNMENT_CENTER},
21726     * {@link #TEXT_ALIGNMENT_TEXT_START},
21727     * {@link #TEXT_ALIGNMENT_TEXT_END},
21728     * {@link #TEXT_ALIGNMENT_VIEW_START},
21729     * {@link #TEXT_ALIGNMENT_VIEW_END}
21730     *
21731     * @attr ref android.R.styleable#View_textAlignment
21732     */
21733    @ViewDebug.ExportedProperty(category = "text", mapping = {
21734            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21735            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21736            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21737            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21738            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21739            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21740            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21741    })
21742    @TextAlignment
21743    public int getTextAlignment() {
21744        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
21745                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
21746    }
21747
21748    /**
21749     * Resolve the text alignment.
21750     *
21751     * @return true if resolution has been done, false otherwise.
21752     *
21753     * @hide
21754     */
21755    public boolean resolveTextAlignment() {
21756        // Reset any previous text alignment resolution
21757        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21758
21759        if (hasRtlSupport()) {
21760            // Set resolved text alignment flag depending on text alignment flag
21761            final int textAlignment = getRawTextAlignment();
21762            switch (textAlignment) {
21763                case TEXT_ALIGNMENT_INHERIT:
21764                    // Check if we can resolve the text alignment
21765                    if (!canResolveTextAlignment()) {
21766                        // We cannot do the resolution if there is no parent so use the default
21767                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21768                        // Resolution will need to happen again later
21769                        return false;
21770                    }
21771
21772                    // Parent has not yet resolved, so we still return the default
21773                    try {
21774                        if (!mParent.isTextAlignmentResolved()) {
21775                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21776                            // Resolution will need to happen again later
21777                            return false;
21778                        }
21779                    } catch (AbstractMethodError e) {
21780                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21781                                " does not fully implement ViewParent", e);
21782                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
21783                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21784                        return true;
21785                    }
21786
21787                    int parentResolvedTextAlignment;
21788                    try {
21789                        parentResolvedTextAlignment = mParent.getTextAlignment();
21790                    } catch (AbstractMethodError e) {
21791                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21792                                " does not fully implement ViewParent", e);
21793                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
21794                    }
21795                    switch (parentResolvedTextAlignment) {
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 the parent resolved
21803                            // text alignment
21804                            mPrivateFlags2 |=
21805                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21806                            break;
21807                        default:
21808                            // Use default resolved text alignment
21809                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21810                    }
21811                    break;
21812                case TEXT_ALIGNMENT_GRAVITY:
21813                case TEXT_ALIGNMENT_TEXT_START:
21814                case TEXT_ALIGNMENT_TEXT_END:
21815                case TEXT_ALIGNMENT_CENTER:
21816                case TEXT_ALIGNMENT_VIEW_START:
21817                case TEXT_ALIGNMENT_VIEW_END:
21818                    // Resolved text alignment is the same as text alignment
21819                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21820                    break;
21821                default:
21822                    // Use default resolved text alignment
21823                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21824            }
21825        } else {
21826            // Use default resolved text alignment
21827            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21828        }
21829
21830        // Set the resolved
21831        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21832        return true;
21833    }
21834
21835    /**
21836     * Check if text alignment resolution can be done.
21837     *
21838     * @return true if text alignment resolution can be done otherwise return false.
21839     */
21840    public boolean canResolveTextAlignment() {
21841        switch (getRawTextAlignment()) {
21842            case TEXT_DIRECTION_INHERIT:
21843                if (mParent != null) {
21844                    try {
21845                        return mParent.canResolveTextAlignment();
21846                    } catch (AbstractMethodError e) {
21847                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21848                                " does not fully implement ViewParent", e);
21849                    }
21850                }
21851                return false;
21852
21853            default:
21854                return true;
21855        }
21856    }
21857
21858    /**
21859     * Reset resolved text alignment. Text alignment will be resolved during a call to
21860     * {@link #onMeasure(int, int)}.
21861     *
21862     * @hide
21863     */
21864    public void resetResolvedTextAlignment() {
21865        // Reset any previous text alignment resolution
21866        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21867        // Set to default
21868        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21869    }
21870
21871    /**
21872     * @return true if text alignment is inherited.
21873     *
21874     * @hide
21875     */
21876    public boolean isTextAlignmentInherited() {
21877        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
21878    }
21879
21880    /**
21881     * @return true if text alignment is resolved.
21882     */
21883    public boolean isTextAlignmentResolved() {
21884        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21885    }
21886
21887    /**
21888     * Generate a value suitable for use in {@link #setId(int)}.
21889     * This value will not collide with ID values generated at build time by aapt for R.id.
21890     *
21891     * @return a generated ID value
21892     */
21893    public static int generateViewId() {
21894        for (;;) {
21895            final int result = sNextGeneratedId.get();
21896            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
21897            int newValue = result + 1;
21898            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
21899            if (sNextGeneratedId.compareAndSet(result, newValue)) {
21900                return result;
21901            }
21902        }
21903    }
21904
21905    /**
21906     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
21907     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
21908     *                           a normal View or a ViewGroup with
21909     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
21910     * @hide
21911     */
21912    public void captureTransitioningViews(List<View> transitioningViews) {
21913        if (getVisibility() == View.VISIBLE) {
21914            transitioningViews.add(this);
21915        }
21916    }
21917
21918    /**
21919     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
21920     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
21921     * @hide
21922     */
21923    public void findNamedViews(Map<String, View> namedElements) {
21924        if (getVisibility() == VISIBLE || mGhostView != null) {
21925            String transitionName = getTransitionName();
21926            if (transitionName != null) {
21927                namedElements.put(transitionName, this);
21928            }
21929        }
21930    }
21931
21932    /**
21933     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
21934     * The default implementation does not care the location or event types, but some subclasses
21935     * may use it (such as WebViews).
21936     * @param event The MotionEvent from a mouse
21937     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
21938     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
21939     * @see PointerIcon
21940     */
21941    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
21942        final float x = event.getX(pointerIndex);
21943        final float y = event.getY(pointerIndex);
21944        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
21945            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
21946        }
21947        return mPointerIcon;
21948    }
21949
21950    /**
21951     * Set the pointer icon for the current view.
21952     * Passing {@code null} will restore the pointer icon to its default value.
21953     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
21954     */
21955    public void setPointerIcon(PointerIcon pointerIcon) {
21956        mPointerIcon = pointerIcon;
21957        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
21958            return;
21959        }
21960        try {
21961            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
21962        } catch (RemoteException e) {
21963        }
21964    }
21965
21966    /**
21967     * Gets the pointer icon for the current view.
21968     */
21969    public PointerIcon getPointerIcon() {
21970        return mPointerIcon;
21971    }
21972
21973    //
21974    // Properties
21975    //
21976    /**
21977     * A Property wrapper around the <code>alpha</code> functionality handled by the
21978     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
21979     */
21980    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
21981        @Override
21982        public void setValue(View object, float value) {
21983            object.setAlpha(value);
21984        }
21985
21986        @Override
21987        public Float get(View object) {
21988            return object.getAlpha();
21989        }
21990    };
21991
21992    /**
21993     * A Property wrapper around the <code>translationX</code> functionality handled by the
21994     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
21995     */
21996    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
21997        @Override
21998        public void setValue(View object, float value) {
21999            object.setTranslationX(value);
22000        }
22001
22002                @Override
22003        public Float get(View object) {
22004            return object.getTranslationX();
22005        }
22006    };
22007
22008    /**
22009     * A Property wrapper around the <code>translationY</code> functionality handled by the
22010     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
22011     */
22012    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
22013        @Override
22014        public void setValue(View object, float value) {
22015            object.setTranslationY(value);
22016        }
22017
22018        @Override
22019        public Float get(View object) {
22020            return object.getTranslationY();
22021        }
22022    };
22023
22024    /**
22025     * A Property wrapper around the <code>translationZ</code> functionality handled by the
22026     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
22027     */
22028    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
22029        @Override
22030        public void setValue(View object, float value) {
22031            object.setTranslationZ(value);
22032        }
22033
22034        @Override
22035        public Float get(View object) {
22036            return object.getTranslationZ();
22037        }
22038    };
22039
22040    /**
22041     * A Property wrapper around the <code>x</code> functionality handled by the
22042     * {@link View#setX(float)} and {@link View#getX()} methods.
22043     */
22044    public static final Property<View, Float> X = new FloatProperty<View>("x") {
22045        @Override
22046        public void setValue(View object, float value) {
22047            object.setX(value);
22048        }
22049
22050        @Override
22051        public Float get(View object) {
22052            return object.getX();
22053        }
22054    };
22055
22056    /**
22057     * A Property wrapper around the <code>y</code> functionality handled by the
22058     * {@link View#setY(float)} and {@link View#getY()} methods.
22059     */
22060    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
22061        @Override
22062        public void setValue(View object, float value) {
22063            object.setY(value);
22064        }
22065
22066        @Override
22067        public Float get(View object) {
22068            return object.getY();
22069        }
22070    };
22071
22072    /**
22073     * A Property wrapper around the <code>z</code> functionality handled by the
22074     * {@link View#setZ(float)} and {@link View#getZ()} methods.
22075     */
22076    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
22077        @Override
22078        public void setValue(View object, float value) {
22079            object.setZ(value);
22080        }
22081
22082        @Override
22083        public Float get(View object) {
22084            return object.getZ();
22085        }
22086    };
22087
22088    /**
22089     * A Property wrapper around the <code>rotation</code> functionality handled by the
22090     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
22091     */
22092    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
22093        @Override
22094        public void setValue(View object, float value) {
22095            object.setRotation(value);
22096        }
22097
22098        @Override
22099        public Float get(View object) {
22100            return object.getRotation();
22101        }
22102    };
22103
22104    /**
22105     * A Property wrapper around the <code>rotationX</code> functionality handled by the
22106     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
22107     */
22108    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
22109        @Override
22110        public void setValue(View object, float value) {
22111            object.setRotationX(value);
22112        }
22113
22114        @Override
22115        public Float get(View object) {
22116            return object.getRotationX();
22117        }
22118    };
22119
22120    /**
22121     * A Property wrapper around the <code>rotationY</code> functionality handled by the
22122     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
22123     */
22124    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
22125        @Override
22126        public void setValue(View object, float value) {
22127            object.setRotationY(value);
22128        }
22129
22130        @Override
22131        public Float get(View object) {
22132            return object.getRotationY();
22133        }
22134    };
22135
22136    /**
22137     * A Property wrapper around the <code>scaleX</code> functionality handled by the
22138     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
22139     */
22140    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
22141        @Override
22142        public void setValue(View object, float value) {
22143            object.setScaleX(value);
22144        }
22145
22146        @Override
22147        public Float get(View object) {
22148            return object.getScaleX();
22149        }
22150    };
22151
22152    /**
22153     * A Property wrapper around the <code>scaleY</code> functionality handled by the
22154     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
22155     */
22156    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
22157        @Override
22158        public void setValue(View object, float value) {
22159            object.setScaleY(value);
22160        }
22161
22162        @Override
22163        public Float get(View object) {
22164            return object.getScaleY();
22165        }
22166    };
22167
22168    /**
22169     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
22170     * Each MeasureSpec represents a requirement for either the width or the height.
22171     * A MeasureSpec is comprised of a size and a mode. There are three possible
22172     * modes:
22173     * <dl>
22174     * <dt>UNSPECIFIED</dt>
22175     * <dd>
22176     * The parent has not imposed any constraint on the child. It can be whatever size
22177     * it wants.
22178     * </dd>
22179     *
22180     * <dt>EXACTLY</dt>
22181     * <dd>
22182     * The parent has determined an exact size for the child. The child is going to be
22183     * given those bounds regardless of how big it wants to be.
22184     * </dd>
22185     *
22186     * <dt>AT_MOST</dt>
22187     * <dd>
22188     * The child can be as large as it wants up to the specified size.
22189     * </dd>
22190     * </dl>
22191     *
22192     * MeasureSpecs are implemented as ints to reduce object allocation. This class
22193     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
22194     */
22195    public static class MeasureSpec {
22196        private static final int MODE_SHIFT = 30;
22197        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
22198
22199        /** @hide */
22200        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
22201        @Retention(RetentionPolicy.SOURCE)
22202        public @interface MeasureSpecMode {}
22203
22204        /**
22205         * Measure specification mode: The parent has not imposed any constraint
22206         * on the child. It can be whatever size it wants.
22207         */
22208        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
22209
22210        /**
22211         * Measure specification mode: The parent has determined an exact size
22212         * for the child. The child is going to be given those bounds regardless
22213         * of how big it wants to be.
22214         */
22215        public static final int EXACTLY     = 1 << MODE_SHIFT;
22216
22217        /**
22218         * Measure specification mode: The child can be as large as it wants up
22219         * to the specified size.
22220         */
22221        public static final int AT_MOST     = 2 << MODE_SHIFT;
22222
22223        /**
22224         * Creates a measure specification based on the supplied size and mode.
22225         *
22226         * The mode must always be one of the following:
22227         * <ul>
22228         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
22229         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
22230         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
22231         * </ul>
22232         *
22233         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
22234         * implementation was such that the order of arguments did not matter
22235         * and overflow in either value could impact the resulting MeasureSpec.
22236         * {@link android.widget.RelativeLayout} was affected by this bug.
22237         * Apps targeting API levels greater than 17 will get the fixed, more strict
22238         * behavior.</p>
22239         *
22240         * @param size the size of the measure specification
22241         * @param mode the mode of the measure specification
22242         * @return the measure specification based on size and mode
22243         */
22244        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
22245                                          @MeasureSpecMode int mode) {
22246            if (sUseBrokenMakeMeasureSpec) {
22247                return size + mode;
22248            } else {
22249                return (size & ~MODE_MASK) | (mode & MODE_MASK);
22250            }
22251        }
22252
22253        /**
22254         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
22255         * will automatically get a size of 0. Older apps expect this.
22256         *
22257         * @hide internal use only for compatibility with system widgets and older apps
22258         */
22259        public static int makeSafeMeasureSpec(int size, int mode) {
22260            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
22261                return 0;
22262            }
22263            return makeMeasureSpec(size, mode);
22264        }
22265
22266        /**
22267         * Extracts the mode from the supplied measure specification.
22268         *
22269         * @param measureSpec the measure specification to extract the mode from
22270         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
22271         *         {@link android.view.View.MeasureSpec#AT_MOST} or
22272         *         {@link android.view.View.MeasureSpec#EXACTLY}
22273         */
22274        @MeasureSpecMode
22275        public static int getMode(int measureSpec) {
22276            //noinspection ResourceType
22277            return (measureSpec & MODE_MASK);
22278        }
22279
22280        /**
22281         * Extracts the size from the supplied measure specification.
22282         *
22283         * @param measureSpec the measure specification to extract the size from
22284         * @return the size in pixels defined in the supplied measure specification
22285         */
22286        public static int getSize(int measureSpec) {
22287            return (measureSpec & ~MODE_MASK);
22288        }
22289
22290        static int adjust(int measureSpec, int delta) {
22291            final int mode = getMode(measureSpec);
22292            int size = getSize(measureSpec);
22293            if (mode == UNSPECIFIED) {
22294                // No need to adjust size for UNSPECIFIED mode.
22295                return makeMeasureSpec(size, UNSPECIFIED);
22296            }
22297            size += delta;
22298            if (size < 0) {
22299                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
22300                        ") spec: " + toString(measureSpec) + " delta: " + delta);
22301                size = 0;
22302            }
22303            return makeMeasureSpec(size, mode);
22304        }
22305
22306        /**
22307         * Returns a String representation of the specified measure
22308         * specification.
22309         *
22310         * @param measureSpec the measure specification to convert to a String
22311         * @return a String with the following format: "MeasureSpec: MODE SIZE"
22312         */
22313        public static String toString(int measureSpec) {
22314            int mode = getMode(measureSpec);
22315            int size = getSize(measureSpec);
22316
22317            StringBuilder sb = new StringBuilder("MeasureSpec: ");
22318
22319            if (mode == UNSPECIFIED)
22320                sb.append("UNSPECIFIED ");
22321            else if (mode == EXACTLY)
22322                sb.append("EXACTLY ");
22323            else if (mode == AT_MOST)
22324                sb.append("AT_MOST ");
22325            else
22326                sb.append(mode).append(" ");
22327
22328            sb.append(size);
22329            return sb.toString();
22330        }
22331    }
22332
22333    private final class CheckForLongPress implements Runnable {
22334        private int mOriginalWindowAttachCount;
22335        private float mX;
22336        private float mY;
22337
22338        @Override
22339        public void run() {
22340            if (isPressed() && (mParent != null)
22341                    && mOriginalWindowAttachCount == mWindowAttachCount) {
22342                if (performLongClick(mX, mY)) {
22343                    mHasPerformedLongPress = true;
22344                }
22345            }
22346        }
22347
22348        public void setAnchor(float x, float y) {
22349            mX = x;
22350            mY = y;
22351        }
22352
22353        public void rememberWindowAttachCount() {
22354            mOriginalWindowAttachCount = mWindowAttachCount;
22355        }
22356    }
22357
22358    private final class CheckForTap implements Runnable {
22359        public float x;
22360        public float y;
22361
22362        @Override
22363        public void run() {
22364            mPrivateFlags &= ~PFLAG_PREPRESSED;
22365            setPressed(true, x, y);
22366            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
22367        }
22368    }
22369
22370    private final class PerformClick implements Runnable {
22371        @Override
22372        public void run() {
22373            performClick();
22374        }
22375    }
22376
22377    /**
22378     * This method returns a ViewPropertyAnimator object, which can be used to animate
22379     * specific properties on this View.
22380     *
22381     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
22382     */
22383    public ViewPropertyAnimator animate() {
22384        if (mAnimator == null) {
22385            mAnimator = new ViewPropertyAnimator(this);
22386        }
22387        return mAnimator;
22388    }
22389
22390    /**
22391     * Sets the name of the View to be used to identify Views in Transitions.
22392     * Names should be unique in the View hierarchy.
22393     *
22394     * @param transitionName The name of the View to uniquely identify it for Transitions.
22395     */
22396    public final void setTransitionName(String transitionName) {
22397        mTransitionName = transitionName;
22398    }
22399
22400    /**
22401     * Returns the name of the View to be used to identify Views in Transitions.
22402     * Names should be unique in the View hierarchy.
22403     *
22404     * <p>This returns null if the View has not been given a name.</p>
22405     *
22406     * @return The name used of the View to be used to identify Views in Transitions or null
22407     * if no name has been given.
22408     */
22409    @ViewDebug.ExportedProperty
22410    public String getTransitionName() {
22411        return mTransitionName;
22412    }
22413
22414    /**
22415     * @hide
22416     */
22417    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
22418        // Do nothing.
22419    }
22420
22421    /**
22422     * Interface definition for a callback to be invoked when a hardware key event is
22423     * dispatched to this view. The callback will be invoked before the key event is
22424     * given to the view. This is only useful for hardware keyboards; a software input
22425     * method has no obligation to trigger this listener.
22426     */
22427    public interface OnKeyListener {
22428        /**
22429         * Called when a hardware key is dispatched to a view. This allows listeners to
22430         * get a chance to respond before the target view.
22431         * <p>Key presses in software keyboards will generally NOT trigger this method,
22432         * although some may elect to do so in some situations. Do not assume a
22433         * software input method has to be key-based; even if it is, it may use key presses
22434         * in a different way than you expect, so there is no way to reliably catch soft
22435         * input key presses.
22436         *
22437         * @param v The view the key has been dispatched to.
22438         * @param keyCode The code for the physical key that was pressed
22439         * @param event The KeyEvent object containing full information about
22440         *        the event.
22441         * @return True if the listener has consumed the event, false otherwise.
22442         */
22443        boolean onKey(View v, int keyCode, KeyEvent event);
22444    }
22445
22446    /**
22447     * Interface definition for a callback to be invoked when a touch event is
22448     * dispatched to this view. The callback will be invoked before the touch
22449     * event is given to the view.
22450     */
22451    public interface OnTouchListener {
22452        /**
22453         * Called when a touch event is dispatched to a view. This allows listeners to
22454         * get a chance to respond before the target view.
22455         *
22456         * @param v The view the touch event has been dispatched to.
22457         * @param event The MotionEvent object containing full information about
22458         *        the event.
22459         * @return True if the listener has consumed the event, false otherwise.
22460         */
22461        boolean onTouch(View v, MotionEvent event);
22462    }
22463
22464    /**
22465     * Interface definition for a callback to be invoked when a hover event is
22466     * dispatched to this view. The callback will be invoked before the hover
22467     * event is given to the view.
22468     */
22469    public interface OnHoverListener {
22470        /**
22471         * Called when a hover event is dispatched to a view. This allows listeners to
22472         * get a chance to respond before the target view.
22473         *
22474         * @param v The view the hover event has been dispatched to.
22475         * @param event The MotionEvent object containing full information about
22476         *        the event.
22477         * @return True if the listener has consumed the event, false otherwise.
22478         */
22479        boolean onHover(View v, MotionEvent event);
22480    }
22481
22482    /**
22483     * Interface definition for a callback to be invoked when a generic motion event is
22484     * dispatched to this view. The callback will be invoked before the generic motion
22485     * event is given to the view.
22486     */
22487    public interface OnGenericMotionListener {
22488        /**
22489         * Called when a generic motion event is dispatched to a view. This allows listeners to
22490         * get a chance to respond before the target view.
22491         *
22492         * @param v The view the generic motion event has been dispatched to.
22493         * @param event The MotionEvent object containing full information about
22494         *        the event.
22495         * @return True if the listener has consumed the event, false otherwise.
22496         */
22497        boolean onGenericMotion(View v, MotionEvent event);
22498    }
22499
22500    /**
22501     * Interface definition for a callback to be invoked when a view has been clicked and held.
22502     */
22503    public interface OnLongClickListener {
22504        /**
22505         * Called when a view has been clicked and held.
22506         *
22507         * @param v The view that was clicked and held.
22508         *
22509         * @return true if the callback consumed the long click, false otherwise.
22510         */
22511        boolean onLongClick(View v);
22512    }
22513
22514    /**
22515     * Interface definition for a callback to be invoked when a drag is being dispatched
22516     * to this view.  The callback will be invoked before the hosting view's own
22517     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
22518     * onDrag(event) behavior, it should return 'false' from this callback.
22519     *
22520     * <div class="special reference">
22521     * <h3>Developer Guides</h3>
22522     * <p>For a guide to implementing drag and drop features, read the
22523     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22524     * </div>
22525     */
22526    public interface OnDragListener {
22527        /**
22528         * Called when a drag event is dispatched to a view. This allows listeners
22529         * to get a chance to override base View behavior.
22530         *
22531         * @param v The View that received the drag event.
22532         * @param event The {@link android.view.DragEvent} object for the drag event.
22533         * @return {@code true} if the drag event was handled successfully, or {@code false}
22534         * if the drag event was not handled. Note that {@code false} will trigger the View
22535         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
22536         */
22537        boolean onDrag(View v, DragEvent event);
22538    }
22539
22540    /**
22541     * Interface definition for a callback to be invoked when the focus state of
22542     * a view changed.
22543     */
22544    public interface OnFocusChangeListener {
22545        /**
22546         * Called when the focus state of a view has changed.
22547         *
22548         * @param v The view whose state has changed.
22549         * @param hasFocus The new focus state of v.
22550         */
22551        void onFocusChange(View v, boolean hasFocus);
22552    }
22553
22554    /**
22555     * Interface definition for a callback to be invoked when a view is clicked.
22556     */
22557    public interface OnClickListener {
22558        /**
22559         * Called when a view has been clicked.
22560         *
22561         * @param v The view that was clicked.
22562         */
22563        void onClick(View v);
22564    }
22565
22566    /**
22567     * Interface definition for a callback to be invoked when a view is context clicked.
22568     */
22569    public interface OnContextClickListener {
22570        /**
22571         * Called when a view is context clicked.
22572         *
22573         * @param v The view that has been context clicked.
22574         * @return true if the callback consumed the context click, false otherwise.
22575         */
22576        boolean onContextClick(View v);
22577    }
22578
22579    /**
22580     * Interface definition for a callback to be invoked when the context menu
22581     * for this view is being built.
22582     */
22583    public interface OnCreateContextMenuListener {
22584        /**
22585         * Called when the context menu for this view is being built. It is not
22586         * safe to hold onto the menu after this method returns.
22587         *
22588         * @param menu The context menu that is being built
22589         * @param v The view for which the context menu is being built
22590         * @param menuInfo Extra information about the item for which the
22591         *            context menu should be shown. This information will vary
22592         *            depending on the class of v.
22593         */
22594        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
22595    }
22596
22597    /**
22598     * Interface definition for a callback to be invoked when the status bar changes
22599     * visibility.  This reports <strong>global</strong> changes to the system UI
22600     * state, not what the application is requesting.
22601     *
22602     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
22603     */
22604    public interface OnSystemUiVisibilityChangeListener {
22605        /**
22606         * Called when the status bar changes visibility because of a call to
22607         * {@link View#setSystemUiVisibility(int)}.
22608         *
22609         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22610         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
22611         * This tells you the <strong>global</strong> state of these UI visibility
22612         * flags, not what your app is currently applying.
22613         */
22614        public void onSystemUiVisibilityChange(int visibility);
22615    }
22616
22617    /**
22618     * Interface definition for a callback to be invoked when this view is attached
22619     * or detached from its window.
22620     */
22621    public interface OnAttachStateChangeListener {
22622        /**
22623         * Called when the view is attached to a window.
22624         * @param v The view that was attached
22625         */
22626        public void onViewAttachedToWindow(View v);
22627        /**
22628         * Called when the view is detached from a window.
22629         * @param v The view that was detached
22630         */
22631        public void onViewDetachedFromWindow(View v);
22632    }
22633
22634    /**
22635     * Listener for applying window insets on a view in a custom way.
22636     *
22637     * <p>Apps may choose to implement this interface if they want to apply custom policy
22638     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
22639     * is set, its
22640     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
22641     * method will be called instead of the View's own
22642     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
22643     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
22644     * the View's normal behavior as part of its own.</p>
22645     */
22646    public interface OnApplyWindowInsetsListener {
22647        /**
22648         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
22649         * on a View, this listener method will be called instead of the view's own
22650         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
22651         *
22652         * @param v The view applying window insets
22653         * @param insets The insets to apply
22654         * @return The insets supplied, minus any insets that were consumed
22655         */
22656        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
22657    }
22658
22659    private final class UnsetPressedState implements Runnable {
22660        @Override
22661        public void run() {
22662            setPressed(false);
22663        }
22664    }
22665
22666    /**
22667     * Base class for derived classes that want to save and restore their own
22668     * state in {@link android.view.View#onSaveInstanceState()}.
22669     */
22670    public static class BaseSavedState extends AbsSavedState {
22671        String mStartActivityRequestWhoSaved;
22672
22673        /**
22674         * Constructor used when reading from a parcel. Reads the state of the superclass.
22675         *
22676         * @param source parcel to read from
22677         */
22678        public BaseSavedState(Parcel source) {
22679            this(source, null);
22680        }
22681
22682        /**
22683         * Constructor used when reading from a parcel using a given class loader.
22684         * Reads the state of the superclass.
22685         *
22686         * @param source parcel to read from
22687         * @param loader ClassLoader to use for reading
22688         */
22689        public BaseSavedState(Parcel source, ClassLoader loader) {
22690            super(source, loader);
22691            mStartActivityRequestWhoSaved = source.readString();
22692        }
22693
22694        /**
22695         * Constructor called by derived classes when creating their SavedState objects
22696         *
22697         * @param superState The state of the superclass of this view
22698         */
22699        public BaseSavedState(Parcelable superState) {
22700            super(superState);
22701        }
22702
22703        @Override
22704        public void writeToParcel(Parcel out, int flags) {
22705            super.writeToParcel(out, flags);
22706            out.writeString(mStartActivityRequestWhoSaved);
22707        }
22708
22709        public static final Parcelable.Creator<BaseSavedState> CREATOR
22710                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
22711            @Override
22712            public BaseSavedState createFromParcel(Parcel in) {
22713                return new BaseSavedState(in);
22714            }
22715
22716            @Override
22717            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
22718                return new BaseSavedState(in, loader);
22719            }
22720
22721            @Override
22722            public BaseSavedState[] newArray(int size) {
22723                return new BaseSavedState[size];
22724            }
22725        };
22726    }
22727
22728    /**
22729     * A set of information given to a view when it is attached to its parent
22730     * window.
22731     */
22732    final static class AttachInfo {
22733        interface Callbacks {
22734            void playSoundEffect(int effectId);
22735            boolean performHapticFeedback(int effectId, boolean always);
22736        }
22737
22738        /**
22739         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
22740         * to a Handler. This class contains the target (View) to invalidate and
22741         * the coordinates of the dirty rectangle.
22742         *
22743         * For performance purposes, this class also implements a pool of up to
22744         * POOL_LIMIT objects that get reused. This reduces memory allocations
22745         * whenever possible.
22746         */
22747        static class InvalidateInfo {
22748            private static final int POOL_LIMIT = 10;
22749
22750            private static final SynchronizedPool<InvalidateInfo> sPool =
22751                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
22752
22753            View target;
22754
22755            int left;
22756            int top;
22757            int right;
22758            int bottom;
22759
22760            public static InvalidateInfo obtain() {
22761                InvalidateInfo instance = sPool.acquire();
22762                return (instance != null) ? instance : new InvalidateInfo();
22763            }
22764
22765            public void recycle() {
22766                target = null;
22767                sPool.release(this);
22768            }
22769        }
22770
22771        final IWindowSession mSession;
22772
22773        final IWindow mWindow;
22774
22775        final IBinder mWindowToken;
22776
22777        final Display mDisplay;
22778
22779        final Callbacks mRootCallbacks;
22780
22781        IWindowId mIWindowId;
22782        WindowId mWindowId;
22783
22784        /**
22785         * The top view of the hierarchy.
22786         */
22787        View mRootView;
22788
22789        IBinder mPanelParentWindowToken;
22790
22791        boolean mHardwareAccelerated;
22792        boolean mHardwareAccelerationRequested;
22793        ThreadedRenderer mThreadedRenderer;
22794        List<RenderNode> mPendingAnimatingRenderNodes;
22795
22796        /**
22797         * The state of the display to which the window is attached, as reported
22798         * by {@link Display#getState()}.  Note that the display state constants
22799         * declared by {@link Display} do not exactly line up with the screen state
22800         * constants declared by {@link View} (there are more display states than
22801         * screen states).
22802         */
22803        int mDisplayState = Display.STATE_UNKNOWN;
22804
22805        /**
22806         * Scale factor used by the compatibility mode
22807         */
22808        float mApplicationScale;
22809
22810        /**
22811         * Indicates whether the application is in compatibility mode
22812         */
22813        boolean mScalingRequired;
22814
22815        /**
22816         * Left position of this view's window
22817         */
22818        int mWindowLeft;
22819
22820        /**
22821         * Top position of this view's window
22822         */
22823        int mWindowTop;
22824
22825        /**
22826         * Indicates whether views need to use 32-bit drawing caches
22827         */
22828        boolean mUse32BitDrawingCache;
22829
22830        /**
22831         * For windows that are full-screen but using insets to layout inside
22832         * of the screen areas, these are the current insets to appear inside
22833         * the overscan area of the display.
22834         */
22835        final Rect mOverscanInsets = new Rect();
22836
22837        /**
22838         * For windows that are full-screen but using insets to layout inside
22839         * of the screen decorations, these are the current insets for the
22840         * content of the window.
22841         */
22842        final Rect mContentInsets = new Rect();
22843
22844        /**
22845         * For windows that are full-screen but using insets to layout inside
22846         * of the screen decorations, these are the current insets for the
22847         * actual visible parts of the window.
22848         */
22849        final Rect mVisibleInsets = new Rect();
22850
22851        /**
22852         * For windows that are full-screen but using insets to layout inside
22853         * of the screen decorations, these are the current insets for the
22854         * stable system windows.
22855         */
22856        final Rect mStableInsets = new Rect();
22857
22858        /**
22859         * For windows that include areas that are not covered by real surface these are the outsets
22860         * for real surface.
22861         */
22862        final Rect mOutsets = new Rect();
22863
22864        /**
22865         * In multi-window we force show the navigation bar. Because we don't want that the surface
22866         * size changes in this mode, we instead have a flag whether the navigation bar size should
22867         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
22868         */
22869        boolean mAlwaysConsumeNavBar;
22870
22871        /**
22872         * The internal insets given by this window.  This value is
22873         * supplied by the client (through
22874         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
22875         * be given to the window manager when changed to be used in laying
22876         * out windows behind it.
22877         */
22878        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
22879                = new ViewTreeObserver.InternalInsetsInfo();
22880
22881        /**
22882         * Set to true when mGivenInternalInsets is non-empty.
22883         */
22884        boolean mHasNonEmptyGivenInternalInsets;
22885
22886        /**
22887         * All views in the window's hierarchy that serve as scroll containers,
22888         * used to determine if the window can be resized or must be panned
22889         * to adjust for a soft input area.
22890         */
22891        final ArrayList<View> mScrollContainers = new ArrayList<View>();
22892
22893        final KeyEvent.DispatcherState mKeyDispatchState
22894                = new KeyEvent.DispatcherState();
22895
22896        /**
22897         * Indicates whether the view's window currently has the focus.
22898         */
22899        boolean mHasWindowFocus;
22900
22901        /**
22902         * The current visibility of the window.
22903         */
22904        int mWindowVisibility;
22905
22906        /**
22907         * Indicates the time at which drawing started to occur.
22908         */
22909        long mDrawingTime;
22910
22911        /**
22912         * Indicates whether or not ignoring the DIRTY_MASK flags.
22913         */
22914        boolean mIgnoreDirtyState;
22915
22916        /**
22917         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
22918         * to avoid clearing that flag prematurely.
22919         */
22920        boolean mSetIgnoreDirtyState = false;
22921
22922        /**
22923         * Indicates whether the view's window is currently in touch mode.
22924         */
22925        boolean mInTouchMode;
22926
22927        /**
22928         * Indicates whether the view has requested unbuffered input dispatching for the current
22929         * event stream.
22930         */
22931        boolean mUnbufferedDispatchRequested;
22932
22933        /**
22934         * Indicates that ViewAncestor should trigger a global layout change
22935         * the next time it performs a traversal
22936         */
22937        boolean mRecomputeGlobalAttributes;
22938
22939        /**
22940         * Always report new attributes at next traversal.
22941         */
22942        boolean mForceReportNewAttributes;
22943
22944        /**
22945         * Set during a traveral if any views want to keep the screen on.
22946         */
22947        boolean mKeepScreenOn;
22948
22949        /**
22950         * Set during a traveral if the light center needs to be updated.
22951         */
22952        boolean mNeedsUpdateLightCenter;
22953
22954        /**
22955         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
22956         */
22957        int mSystemUiVisibility;
22958
22959        /**
22960         * Hack to force certain system UI visibility flags to be cleared.
22961         */
22962        int mDisabledSystemUiVisibility;
22963
22964        /**
22965         * Last global system UI visibility reported by the window manager.
22966         */
22967        int mGlobalSystemUiVisibility = -1;
22968
22969        /**
22970         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
22971         * attached.
22972         */
22973        boolean mHasSystemUiListeners;
22974
22975        /**
22976         * Set if the window has requested to extend into the overscan region
22977         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
22978         */
22979        boolean mOverscanRequested;
22980
22981        /**
22982         * Set if the visibility of any views has changed.
22983         */
22984        boolean mViewVisibilityChanged;
22985
22986        /**
22987         * Set to true if a view has been scrolled.
22988         */
22989        boolean mViewScrollChanged;
22990
22991        /**
22992         * Set to true if high contrast mode enabled
22993         */
22994        boolean mHighContrastText;
22995
22996        /**
22997         * Set to true if a pointer event is currently being handled.
22998         */
22999        boolean mHandlingPointerEvent;
23000
23001        /**
23002         * Global to the view hierarchy used as a temporary for dealing with
23003         * x/y points in the transparent region computations.
23004         */
23005        final int[] mTransparentLocation = new int[2];
23006
23007        /**
23008         * Global to the view hierarchy used as a temporary for dealing with
23009         * x/y points in the ViewGroup.invalidateChild implementation.
23010         */
23011        final int[] mInvalidateChildLocation = new int[2];
23012
23013        /**
23014         * Global to the view hierarchy used as a temporary for dealing with
23015         * computing absolute on-screen location.
23016         */
23017        final int[] mTmpLocation = new int[2];
23018
23019        /**
23020         * Global to the view hierarchy used as a temporary for dealing with
23021         * x/y location when view is transformed.
23022         */
23023        final float[] mTmpTransformLocation = new float[2];
23024
23025        /**
23026         * The view tree observer used to dispatch global events like
23027         * layout, pre-draw, touch mode change, etc.
23028         */
23029        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
23030
23031        /**
23032         * A Canvas used by the view hierarchy to perform bitmap caching.
23033         */
23034        Canvas mCanvas;
23035
23036        /**
23037         * The view root impl.
23038         */
23039        final ViewRootImpl mViewRootImpl;
23040
23041        /**
23042         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
23043         * handler can be used to pump events in the UI events queue.
23044         */
23045        final Handler mHandler;
23046
23047        /**
23048         * Temporary for use in computing invalidate rectangles while
23049         * calling up the hierarchy.
23050         */
23051        final Rect mTmpInvalRect = new Rect();
23052
23053        /**
23054         * Temporary for use in computing hit areas with transformed views
23055         */
23056        final RectF mTmpTransformRect = new RectF();
23057
23058        /**
23059         * Temporary for use in computing hit areas with transformed views
23060         */
23061        final RectF mTmpTransformRect1 = new RectF();
23062
23063        /**
23064         * Temporary list of rectanges.
23065         */
23066        final List<RectF> mTmpRectList = new ArrayList<>();
23067
23068        /**
23069         * Temporary for use in transforming invalidation rect
23070         */
23071        final Matrix mTmpMatrix = new Matrix();
23072
23073        /**
23074         * Temporary for use in transforming invalidation rect
23075         */
23076        final Transformation mTmpTransformation = new Transformation();
23077
23078        /**
23079         * Temporary for use in querying outlines from OutlineProviders
23080         */
23081        final Outline mTmpOutline = new Outline();
23082
23083        /**
23084         * Temporary list for use in collecting focusable descendents of a view.
23085         */
23086        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
23087
23088        /**
23089         * The id of the window for accessibility purposes.
23090         */
23091        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
23092
23093        /**
23094         * Flags related to accessibility processing.
23095         *
23096         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
23097         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
23098         */
23099        int mAccessibilityFetchFlags;
23100
23101        /**
23102         * The drawable for highlighting accessibility focus.
23103         */
23104        Drawable mAccessibilityFocusDrawable;
23105
23106        /**
23107         * Show where the margins, bounds and layout bounds are for each view.
23108         */
23109        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
23110
23111        /**
23112         * Point used to compute visible regions.
23113         */
23114        final Point mPoint = new Point();
23115
23116        /**
23117         * Used to track which View originated a requestLayout() call, used when
23118         * requestLayout() is called during layout.
23119         */
23120        View mViewRequestingLayout;
23121
23122        /**
23123         * Used to track views that need (at least) a partial relayout at their current size
23124         * during the next traversal.
23125         */
23126        List<View> mPartialLayoutViews = new ArrayList<>();
23127
23128        /**
23129         * Swapped with mPartialLayoutViews during layout to avoid concurrent
23130         * modification. Lazily assigned during ViewRootImpl layout.
23131         */
23132        List<View> mEmptyPartialLayoutViews;
23133
23134        /**
23135         * Used to track the identity of the current drag operation.
23136         */
23137        IBinder mDragToken;
23138
23139        /**
23140         * The drag shadow surface for the current drag operation.
23141         */
23142        public Surface mDragSurface;
23143
23144        /**
23145         * Creates a new set of attachment information with the specified
23146         * events handler and thread.
23147         *
23148         * @param handler the events handler the view must use
23149         */
23150        AttachInfo(IWindowSession session, IWindow window, Display display,
23151                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
23152            mSession = session;
23153            mWindow = window;
23154            mWindowToken = window.asBinder();
23155            mDisplay = display;
23156            mViewRootImpl = viewRootImpl;
23157            mHandler = handler;
23158            mRootCallbacks = effectPlayer;
23159        }
23160    }
23161
23162    /**
23163     * <p>ScrollabilityCache holds various fields used by a View when scrolling
23164     * is supported. This avoids keeping too many unused fields in most
23165     * instances of View.</p>
23166     */
23167    private static class ScrollabilityCache implements Runnable {
23168
23169        /**
23170         * Scrollbars are not visible
23171         */
23172        public static final int OFF = 0;
23173
23174        /**
23175         * Scrollbars are visible
23176         */
23177        public static final int ON = 1;
23178
23179        /**
23180         * Scrollbars are fading away
23181         */
23182        public static final int FADING = 2;
23183
23184        public boolean fadeScrollBars;
23185
23186        public int fadingEdgeLength;
23187        public int scrollBarDefaultDelayBeforeFade;
23188        public int scrollBarFadeDuration;
23189
23190        public int scrollBarSize;
23191        public ScrollBarDrawable scrollBar;
23192        public float[] interpolatorValues;
23193        public View host;
23194
23195        public final Paint paint;
23196        public final Matrix matrix;
23197        public Shader shader;
23198
23199        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
23200
23201        private static final float[] OPAQUE = { 255 };
23202        private static final float[] TRANSPARENT = { 0.0f };
23203
23204        /**
23205         * When fading should start. This time moves into the future every time
23206         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
23207         */
23208        public long fadeStartTime;
23209
23210
23211        /**
23212         * The current state of the scrollbars: ON, OFF, or FADING
23213         */
23214        public int state = OFF;
23215
23216        private int mLastColor;
23217
23218        public final Rect mScrollBarBounds = new Rect();
23219
23220        public static final int NOT_DRAGGING = 0;
23221        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
23222        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
23223        public int mScrollBarDraggingState = NOT_DRAGGING;
23224
23225        public float mScrollBarDraggingPos = 0;
23226
23227        public ScrollabilityCache(ViewConfiguration configuration, View host) {
23228            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
23229            scrollBarSize = configuration.getScaledScrollBarSize();
23230            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
23231            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
23232
23233            paint = new Paint();
23234            matrix = new Matrix();
23235            // use use a height of 1, and then wack the matrix each time we
23236            // actually use it.
23237            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23238            paint.setShader(shader);
23239            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23240
23241            this.host = host;
23242        }
23243
23244        public void setFadeColor(int color) {
23245            if (color != mLastColor) {
23246                mLastColor = color;
23247
23248                if (color != 0) {
23249                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
23250                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
23251                    paint.setShader(shader);
23252                    // Restore the default transfer mode (src_over)
23253                    paint.setXfermode(null);
23254                } else {
23255                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23256                    paint.setShader(shader);
23257                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23258                }
23259            }
23260        }
23261
23262        public void run() {
23263            long now = AnimationUtils.currentAnimationTimeMillis();
23264            if (now >= fadeStartTime) {
23265
23266                // the animation fades the scrollbars out by changing
23267                // the opacity (alpha) from fully opaque to fully
23268                // transparent
23269                int nextFrame = (int) now;
23270                int framesCount = 0;
23271
23272                Interpolator interpolator = scrollBarInterpolator;
23273
23274                // Start opaque
23275                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
23276
23277                // End transparent
23278                nextFrame += scrollBarFadeDuration;
23279                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
23280
23281                state = FADING;
23282
23283                // Kick off the fade animation
23284                host.invalidate(true);
23285            }
23286        }
23287    }
23288
23289    /**
23290     * Resuable callback for sending
23291     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
23292     */
23293    private class SendViewScrolledAccessibilityEvent implements Runnable {
23294        public volatile boolean mIsPending;
23295
23296        public void run() {
23297            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
23298            mIsPending = false;
23299        }
23300    }
23301
23302    /**
23303     * <p>
23304     * This class represents a delegate that can be registered in a {@link View}
23305     * to enhance accessibility support via composition rather via inheritance.
23306     * It is specifically targeted to widget developers that extend basic View
23307     * classes i.e. classes in package android.view, that would like their
23308     * applications to be backwards compatible.
23309     * </p>
23310     * <div class="special reference">
23311     * <h3>Developer Guides</h3>
23312     * <p>For more information about making applications accessible, read the
23313     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
23314     * developer guide.</p>
23315     * </div>
23316     * <p>
23317     * A scenario in which a developer would like to use an accessibility delegate
23318     * is overriding a method introduced in a later API version than the minimal API
23319     * version supported by the application. For example, the method
23320     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
23321     * in API version 4 when the accessibility APIs were first introduced. If a
23322     * developer would like his application to run on API version 4 devices (assuming
23323     * all other APIs used by the application are version 4 or lower) and take advantage
23324     * of this method, instead of overriding the method which would break the application's
23325     * backwards compatibility, he can override the corresponding method in this
23326     * delegate and register the delegate in the target View if the API version of
23327     * the system is high enough, i.e. the API version is the same as or higher than the API
23328     * version that introduced
23329     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
23330     * </p>
23331     * <p>
23332     * Here is an example implementation:
23333     * </p>
23334     * <code><pre><p>
23335     * if (Build.VERSION.SDK_INT >= 14) {
23336     *     // If the API version is equal of higher than the version in
23337     *     // which onInitializeAccessibilityNodeInfo was introduced we
23338     *     // register a delegate with a customized implementation.
23339     *     View view = findViewById(R.id.view_id);
23340     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
23341     *         public void onInitializeAccessibilityNodeInfo(View host,
23342     *                 AccessibilityNodeInfo info) {
23343     *             // Let the default implementation populate the info.
23344     *             super.onInitializeAccessibilityNodeInfo(host, info);
23345     *             // Set some other information.
23346     *             info.setEnabled(host.isEnabled());
23347     *         }
23348     *     });
23349     * }
23350     * </code></pre></p>
23351     * <p>
23352     * This delegate contains methods that correspond to the accessibility methods
23353     * in View. If a delegate has been specified the implementation in View hands
23354     * off handling to the corresponding method in this delegate. The default
23355     * implementation the delegate methods behaves exactly as the corresponding
23356     * method in View for the case of no accessibility delegate been set. Hence,
23357     * to customize the behavior of a View method, clients can override only the
23358     * corresponding delegate method without altering the behavior of the rest
23359     * accessibility related methods of the host view.
23360     * </p>
23361     * <p>
23362     * <strong>Note:</strong> On platform versions prior to
23363     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
23364     * views in the {@code android.widget.*} package are called <i>before</i>
23365     * host methods. This prevents certain properties such as class name from
23366     * being modified by overriding
23367     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
23368     * as any changes will be overwritten by the host class.
23369     * <p>
23370     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
23371     * methods are called <i>after</i> host methods, which all properties to be
23372     * modified without being overwritten by the host class.
23373     */
23374    public static class AccessibilityDelegate {
23375
23376        /**
23377         * Sends an accessibility event of the given type. If accessibility is not
23378         * enabled this method has no effect.
23379         * <p>
23380         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
23381         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
23382         * been set.
23383         * </p>
23384         *
23385         * @param host The View hosting the delegate.
23386         * @param eventType The type of the event to send.
23387         *
23388         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
23389         */
23390        public void sendAccessibilityEvent(View host, int eventType) {
23391            host.sendAccessibilityEventInternal(eventType);
23392        }
23393
23394        /**
23395         * Performs the specified accessibility action on the view. For
23396         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
23397         * <p>
23398         * The default implementation behaves as
23399         * {@link View#performAccessibilityAction(int, Bundle)
23400         *  View#performAccessibilityAction(int, Bundle)} for the case of
23401         *  no accessibility delegate been set.
23402         * </p>
23403         *
23404         * @param action The action to perform.
23405         * @return Whether the action was performed.
23406         *
23407         * @see View#performAccessibilityAction(int, Bundle)
23408         *      View#performAccessibilityAction(int, Bundle)
23409         */
23410        public boolean performAccessibilityAction(View host, int action, Bundle args) {
23411            return host.performAccessibilityActionInternal(action, args);
23412        }
23413
23414        /**
23415         * Sends an accessibility event. This method behaves exactly as
23416         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
23417         * empty {@link AccessibilityEvent} and does not perform a check whether
23418         * accessibility is enabled.
23419         * <p>
23420         * The default implementation behaves as
23421         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23422         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
23423         * the case of no accessibility delegate been set.
23424         * </p>
23425         *
23426         * @param host The View hosting the delegate.
23427         * @param event The event to send.
23428         *
23429         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23430         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23431         */
23432        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
23433            host.sendAccessibilityEventUncheckedInternal(event);
23434        }
23435
23436        /**
23437         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
23438         * to its children for adding their text content to the event.
23439         * <p>
23440         * The default implementation behaves as
23441         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23442         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
23443         * the case of no accessibility delegate been set.
23444         * </p>
23445         *
23446         * @param host The View hosting the delegate.
23447         * @param event The event.
23448         * @return True if the event population was completed.
23449         *
23450         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23451         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23452         */
23453        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23454            return host.dispatchPopulateAccessibilityEventInternal(event);
23455        }
23456
23457        /**
23458         * Gives a chance to the host View to populate the accessibility event with its
23459         * text content.
23460         * <p>
23461         * The default implementation behaves as
23462         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
23463         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
23464         * the case of no accessibility delegate been set.
23465         * </p>
23466         *
23467         * @param host The View hosting the delegate.
23468         * @param event The accessibility event which to populate.
23469         *
23470         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
23471         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
23472         */
23473        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23474            host.onPopulateAccessibilityEventInternal(event);
23475        }
23476
23477        /**
23478         * Initializes an {@link AccessibilityEvent} with information about the
23479         * the host View which is the event source.
23480         * <p>
23481         * The default implementation behaves as
23482         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
23483         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
23484         * the case of no accessibility delegate been set.
23485         * </p>
23486         *
23487         * @param host The View hosting the delegate.
23488         * @param event The event to initialize.
23489         *
23490         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
23491         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
23492         */
23493        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
23494            host.onInitializeAccessibilityEventInternal(event);
23495        }
23496
23497        /**
23498         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
23499         * <p>
23500         * The default implementation behaves as
23501         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23502         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
23503         * the case of no accessibility delegate been set.
23504         * </p>
23505         *
23506         * @param host The View hosting the delegate.
23507         * @param info The instance to initialize.
23508         *
23509         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23510         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23511         */
23512        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
23513            host.onInitializeAccessibilityNodeInfoInternal(info);
23514        }
23515
23516        /**
23517         * Called when a child of the host View has requested sending an
23518         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
23519         * to augment the event.
23520         * <p>
23521         * The default implementation behaves as
23522         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23523         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
23524         * the case of no accessibility delegate been set.
23525         * </p>
23526         *
23527         * @param host The View hosting the delegate.
23528         * @param child The child which requests sending the event.
23529         * @param event The event to be sent.
23530         * @return True if the event should be sent
23531         *
23532         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23533         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23534         */
23535        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
23536                AccessibilityEvent event) {
23537            return host.onRequestSendAccessibilityEventInternal(child, event);
23538        }
23539
23540        /**
23541         * Gets the provider for managing a virtual view hierarchy rooted at this View
23542         * and reported to {@link android.accessibilityservice.AccessibilityService}s
23543         * that explore the window content.
23544         * <p>
23545         * The default implementation behaves as
23546         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
23547         * the case of no accessibility delegate been set.
23548         * </p>
23549         *
23550         * @return The provider.
23551         *
23552         * @see AccessibilityNodeProvider
23553         */
23554        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
23555            return null;
23556        }
23557
23558        /**
23559         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
23560         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
23561         * This method is responsible for obtaining an accessibility node info from a
23562         * pool of reusable instances and calling
23563         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
23564         * view to initialize the former.
23565         * <p>
23566         * <strong>Note:</strong> The client is responsible for recycling the obtained
23567         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
23568         * creation.
23569         * </p>
23570         * <p>
23571         * The default implementation behaves as
23572         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
23573         * the case of no accessibility delegate been set.
23574         * </p>
23575         * @return A populated {@link AccessibilityNodeInfo}.
23576         *
23577         * @see AccessibilityNodeInfo
23578         *
23579         * @hide
23580         */
23581        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
23582            return host.createAccessibilityNodeInfoInternal();
23583        }
23584    }
23585
23586    private class MatchIdPredicate implements Predicate<View> {
23587        public int mId;
23588
23589        @Override
23590        public boolean apply(View view) {
23591            return (view.mID == mId);
23592        }
23593    }
23594
23595    private class MatchLabelForPredicate implements Predicate<View> {
23596        private int mLabeledId;
23597
23598        @Override
23599        public boolean apply(View view) {
23600            return (view.mLabelForId == mLabeledId);
23601        }
23602    }
23603
23604    private class SendViewStateChangedAccessibilityEvent implements Runnable {
23605        private int mChangeTypes = 0;
23606        private boolean mPosted;
23607        private boolean mPostedWithDelay;
23608        private long mLastEventTimeMillis;
23609
23610        @Override
23611        public void run() {
23612            mPosted = false;
23613            mPostedWithDelay = false;
23614            mLastEventTimeMillis = SystemClock.uptimeMillis();
23615            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
23616                final AccessibilityEvent event = AccessibilityEvent.obtain();
23617                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
23618                event.setContentChangeTypes(mChangeTypes);
23619                sendAccessibilityEventUnchecked(event);
23620            }
23621            mChangeTypes = 0;
23622        }
23623
23624        public void runOrPost(int changeType) {
23625            mChangeTypes |= changeType;
23626
23627            // If this is a live region or the child of a live region, collect
23628            // all events from this frame and send them on the next frame.
23629            if (inLiveRegion()) {
23630                // If we're already posted with a delay, remove that.
23631                if (mPostedWithDelay) {
23632                    removeCallbacks(this);
23633                    mPostedWithDelay = false;
23634                }
23635                // Only post if we're not already posted.
23636                if (!mPosted) {
23637                    post(this);
23638                    mPosted = true;
23639                }
23640                return;
23641            }
23642
23643            if (mPosted) {
23644                return;
23645            }
23646
23647            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
23648            final long minEventIntevalMillis =
23649                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
23650            if (timeSinceLastMillis >= minEventIntevalMillis) {
23651                removeCallbacks(this);
23652                run();
23653            } else {
23654                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
23655                mPostedWithDelay = true;
23656            }
23657        }
23658    }
23659
23660    private boolean inLiveRegion() {
23661        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23662            return true;
23663        }
23664
23665        ViewParent parent = getParent();
23666        while (parent instanceof View) {
23667            if (((View) parent).getAccessibilityLiveRegion()
23668                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23669                return true;
23670            }
23671            parent = parent.getParent();
23672        }
23673
23674        return false;
23675    }
23676
23677    /**
23678     * Dump all private flags in readable format, useful for documentation and
23679     * sanity checking.
23680     */
23681    private static void dumpFlags() {
23682        final HashMap<String, String> found = Maps.newHashMap();
23683        try {
23684            for (Field field : View.class.getDeclaredFields()) {
23685                final int modifiers = field.getModifiers();
23686                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
23687                    if (field.getType().equals(int.class)) {
23688                        final int value = field.getInt(null);
23689                        dumpFlag(found, field.getName(), value);
23690                    } else if (field.getType().equals(int[].class)) {
23691                        final int[] values = (int[]) field.get(null);
23692                        for (int i = 0; i < values.length; i++) {
23693                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
23694                        }
23695                    }
23696                }
23697            }
23698        } catch (IllegalAccessException e) {
23699            throw new RuntimeException(e);
23700        }
23701
23702        final ArrayList<String> keys = Lists.newArrayList();
23703        keys.addAll(found.keySet());
23704        Collections.sort(keys);
23705        for (String key : keys) {
23706            Log.d(VIEW_LOG_TAG, found.get(key));
23707        }
23708    }
23709
23710    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
23711        // Sort flags by prefix, then by bits, always keeping unique keys
23712        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
23713        final int prefix = name.indexOf('_');
23714        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
23715        final String output = bits + " " + name;
23716        found.put(key, output);
23717    }
23718
23719    /** {@hide} */
23720    public void encode(@NonNull ViewHierarchyEncoder stream) {
23721        stream.beginObject(this);
23722        encodeProperties(stream);
23723        stream.endObject();
23724    }
23725
23726    /** {@hide} */
23727    @CallSuper
23728    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
23729        Object resolveId = ViewDebug.resolveId(getContext(), mID);
23730        if (resolveId instanceof String) {
23731            stream.addProperty("id", (String) resolveId);
23732        } else {
23733            stream.addProperty("id", mID);
23734        }
23735
23736        stream.addProperty("misc:transformation.alpha",
23737                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
23738        stream.addProperty("misc:transitionName", getTransitionName());
23739
23740        // layout
23741        stream.addProperty("layout:left", mLeft);
23742        stream.addProperty("layout:right", mRight);
23743        stream.addProperty("layout:top", mTop);
23744        stream.addProperty("layout:bottom", mBottom);
23745        stream.addProperty("layout:width", getWidth());
23746        stream.addProperty("layout:height", getHeight());
23747        stream.addProperty("layout:layoutDirection", getLayoutDirection());
23748        stream.addProperty("layout:layoutRtl", isLayoutRtl());
23749        stream.addProperty("layout:hasTransientState", hasTransientState());
23750        stream.addProperty("layout:baseline", getBaseline());
23751
23752        // layout params
23753        ViewGroup.LayoutParams layoutParams = getLayoutParams();
23754        if (layoutParams != null) {
23755            stream.addPropertyKey("layoutParams");
23756            layoutParams.encode(stream);
23757        }
23758
23759        // scrolling
23760        stream.addProperty("scrolling:scrollX", mScrollX);
23761        stream.addProperty("scrolling:scrollY", mScrollY);
23762
23763        // padding
23764        stream.addProperty("padding:paddingLeft", mPaddingLeft);
23765        stream.addProperty("padding:paddingRight", mPaddingRight);
23766        stream.addProperty("padding:paddingTop", mPaddingTop);
23767        stream.addProperty("padding:paddingBottom", mPaddingBottom);
23768        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
23769        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
23770        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
23771        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
23772        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
23773
23774        // measurement
23775        stream.addProperty("measurement:minHeight", mMinHeight);
23776        stream.addProperty("measurement:minWidth", mMinWidth);
23777        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
23778        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
23779
23780        // drawing
23781        stream.addProperty("drawing:elevation", getElevation());
23782        stream.addProperty("drawing:translationX", getTranslationX());
23783        stream.addProperty("drawing:translationY", getTranslationY());
23784        stream.addProperty("drawing:translationZ", getTranslationZ());
23785        stream.addProperty("drawing:rotation", getRotation());
23786        stream.addProperty("drawing:rotationX", getRotationX());
23787        stream.addProperty("drawing:rotationY", getRotationY());
23788        stream.addProperty("drawing:scaleX", getScaleX());
23789        stream.addProperty("drawing:scaleY", getScaleY());
23790        stream.addProperty("drawing:pivotX", getPivotX());
23791        stream.addProperty("drawing:pivotY", getPivotY());
23792        stream.addProperty("drawing:opaque", isOpaque());
23793        stream.addProperty("drawing:alpha", getAlpha());
23794        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
23795        stream.addProperty("drawing:shadow", hasShadow());
23796        stream.addProperty("drawing:solidColor", getSolidColor());
23797        stream.addProperty("drawing:layerType", mLayerType);
23798        stream.addProperty("drawing:willNotDraw", willNotDraw());
23799        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
23800        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
23801        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
23802        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
23803
23804        // focus
23805        stream.addProperty("focus:hasFocus", hasFocus());
23806        stream.addProperty("focus:isFocused", isFocused());
23807        stream.addProperty("focus:isFocusable", isFocusable());
23808        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
23809
23810        stream.addProperty("misc:clickable", isClickable());
23811        stream.addProperty("misc:pressed", isPressed());
23812        stream.addProperty("misc:selected", isSelected());
23813        stream.addProperty("misc:touchMode", isInTouchMode());
23814        stream.addProperty("misc:hovered", isHovered());
23815        stream.addProperty("misc:activated", isActivated());
23816
23817        stream.addProperty("misc:visibility", getVisibility());
23818        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
23819        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
23820
23821        stream.addProperty("misc:enabled", isEnabled());
23822        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
23823        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
23824
23825        // theme attributes
23826        Resources.Theme theme = getContext().getTheme();
23827        if (theme != null) {
23828            stream.addPropertyKey("theme");
23829            theme.encode(stream);
23830        }
23831
23832        // view attribute information
23833        int n = mAttributes != null ? mAttributes.length : 0;
23834        stream.addProperty("meta:__attrCount__", n/2);
23835        for (int i = 0; i < n; i += 2) {
23836            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
23837        }
23838
23839        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
23840
23841        // text
23842        stream.addProperty("text:textDirection", getTextDirection());
23843        stream.addProperty("text:textAlignment", getTextAlignment());
23844
23845        // accessibility
23846        CharSequence contentDescription = getContentDescription();
23847        stream.addProperty("accessibility:contentDescription",
23848                contentDescription == null ? "" : contentDescription.toString());
23849        stream.addProperty("accessibility:labelFor", getLabelFor());
23850        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
23851    }
23852
23853    /**
23854     * Determine if this view is rendered on a round wearable device and is the main view
23855     * on the screen.
23856     */
23857    private boolean shouldDrawRoundScrollbar() {
23858        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
23859            return false;
23860        }
23861
23862        final View rootView = getRootView();
23863        final WindowInsets insets = getRootWindowInsets();
23864
23865        int height = getHeight();
23866        int width = getWidth();
23867        int displayHeight = rootView.getHeight();
23868        int displayWidth = rootView.getWidth();
23869
23870        if (height != displayHeight || width != displayWidth) {
23871            return false;
23872        }
23873
23874        getLocationOnScreen(mAttachInfo.mTmpLocation);
23875        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
23876                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
23877    }
23878}
23879