View.java revision 1b060c3ab5494a434f27d4603207ce52b3c6e4f3
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     * Prior to N, when drag enters into child of a view that has already received an
834     * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
835     * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
836     * false from its event handler for these events.
837     * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
838     * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
839     * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
840     */
841    static boolean sCascadedDragDrop;
842
843    /**
844     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
845     * calling setFlags.
846     */
847    private static final int NOT_FOCUSABLE = 0x00000000;
848
849    /**
850     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
851     * setFlags.
852     */
853    private static final int FOCUSABLE = 0x00000001;
854
855    /**
856     * Mask for use with setFlags indicating bits used for focus.
857     */
858    private static final int FOCUSABLE_MASK = 0x00000001;
859
860    /**
861     * This view will adjust its padding to fit sytem windows (e.g. status bar)
862     */
863    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
864
865    /** @hide */
866    @IntDef({VISIBLE, INVISIBLE, GONE})
867    @Retention(RetentionPolicy.SOURCE)
868    public @interface Visibility {}
869
870    /**
871     * This view is visible.
872     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
873     * android:visibility}.
874     */
875    public static final int VISIBLE = 0x00000000;
876
877    /**
878     * This view is invisible, but it still takes up space for layout purposes.
879     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
880     * android:visibility}.
881     */
882    public static final int INVISIBLE = 0x00000004;
883
884    /**
885     * This view is invisible, and it doesn't take any space for layout
886     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
887     * android:visibility}.
888     */
889    public static final int GONE = 0x00000008;
890
891    /**
892     * Mask for use with setFlags indicating bits used for visibility.
893     * {@hide}
894     */
895    static final int VISIBILITY_MASK = 0x0000000C;
896
897    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
898
899    /**
900     * This view is enabled. Interpretation varies by subclass.
901     * Use with ENABLED_MASK when calling setFlags.
902     * {@hide}
903     */
904    static final int ENABLED = 0x00000000;
905
906    /**
907     * This view is disabled. Interpretation varies by subclass.
908     * Use with ENABLED_MASK when calling setFlags.
909     * {@hide}
910     */
911    static final int DISABLED = 0x00000020;
912
913   /**
914    * Mask for use with setFlags indicating bits used for indicating whether
915    * this view is enabled
916    * {@hide}
917    */
918    static final int ENABLED_MASK = 0x00000020;
919
920    /**
921     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
922     * called and further optimizations will be performed. It is okay to have
923     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
924     * {@hide}
925     */
926    static final int WILL_NOT_DRAW = 0x00000080;
927
928    /**
929     * Mask for use with setFlags indicating bits used for indicating whether
930     * this view is will draw
931     * {@hide}
932     */
933    static final int DRAW_MASK = 0x00000080;
934
935    /**
936     * <p>This view doesn't show scrollbars.</p>
937     * {@hide}
938     */
939    static final int SCROLLBARS_NONE = 0x00000000;
940
941    /**
942     * <p>This view shows horizontal scrollbars.</p>
943     * {@hide}
944     */
945    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
946
947    /**
948     * <p>This view shows vertical scrollbars.</p>
949     * {@hide}
950     */
951    static final int SCROLLBARS_VERTICAL = 0x00000200;
952
953    /**
954     * <p>Mask for use with setFlags indicating bits used for indicating which
955     * scrollbars are enabled.</p>
956     * {@hide}
957     */
958    static final int SCROLLBARS_MASK = 0x00000300;
959
960    /**
961     * Indicates that the view should filter touches when its window is obscured.
962     * Refer to the class comments for more information about this security feature.
963     * {@hide}
964     */
965    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
966
967    /**
968     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
969     * that they are optional and should be skipped if the window has
970     * requested system UI flags that ignore those insets for layout.
971     */
972    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
973
974    /**
975     * <p>This view doesn't show fading edges.</p>
976     * {@hide}
977     */
978    static final int FADING_EDGE_NONE = 0x00000000;
979
980    /**
981     * <p>This view shows horizontal fading edges.</p>
982     * {@hide}
983     */
984    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
985
986    /**
987     * <p>This view shows vertical fading edges.</p>
988     * {@hide}
989     */
990    static final int FADING_EDGE_VERTICAL = 0x00002000;
991
992    /**
993     * <p>Mask for use with setFlags indicating bits used for indicating which
994     * fading edges are enabled.</p>
995     * {@hide}
996     */
997    static final int FADING_EDGE_MASK = 0x00003000;
998
999    /**
1000     * <p>Indicates this view can be clicked. When clickable, a View reacts
1001     * to clicks by notifying the OnClickListener.<p>
1002     * {@hide}
1003     */
1004    static final int CLICKABLE = 0x00004000;
1005
1006    /**
1007     * <p>Indicates this view is caching its drawing into a bitmap.</p>
1008     * {@hide}
1009     */
1010    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1011
1012    /**
1013     * <p>Indicates that no icicle should be saved for this view.<p>
1014     * {@hide}
1015     */
1016    static final int SAVE_DISABLED = 0x000010000;
1017
1018    /**
1019     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1020     * property.</p>
1021     * {@hide}
1022     */
1023    static final int SAVE_DISABLED_MASK = 0x000010000;
1024
1025    /**
1026     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1027     * {@hide}
1028     */
1029    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1030
1031    /**
1032     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1033     * {@hide}
1034     */
1035    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1036
1037    /** @hide */
1038    @Retention(RetentionPolicy.SOURCE)
1039    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1040    public @interface DrawingCacheQuality {}
1041
1042    /**
1043     * <p>Enables low quality mode for the drawing cache.</p>
1044     */
1045    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1046
1047    /**
1048     * <p>Enables high quality mode for the drawing cache.</p>
1049     */
1050    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1051
1052    /**
1053     * <p>Enables automatic quality mode for the drawing cache.</p>
1054     */
1055    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1056
1057    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1058            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1059    };
1060
1061    /**
1062     * <p>Mask for use with setFlags indicating bits used for the cache
1063     * quality property.</p>
1064     * {@hide}
1065     */
1066    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1067
1068    /**
1069     * <p>
1070     * Indicates this view can be long clicked. When long clickable, a View
1071     * reacts to long clicks by notifying the OnLongClickListener or showing a
1072     * context menu.
1073     * </p>
1074     * {@hide}
1075     */
1076    static final int LONG_CLICKABLE = 0x00200000;
1077
1078    /**
1079     * <p>Indicates that this view gets its drawable states from its direct parent
1080     * and ignores its original internal states.</p>
1081     *
1082     * @hide
1083     */
1084    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1085
1086    /**
1087     * <p>
1088     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1089     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1090     * OnContextClickListener.
1091     * </p>
1092     * {@hide}
1093     */
1094    static final int CONTEXT_CLICKABLE = 0x00800000;
1095
1096
1097    /** @hide */
1098    @IntDef({
1099        SCROLLBARS_INSIDE_OVERLAY,
1100        SCROLLBARS_INSIDE_INSET,
1101        SCROLLBARS_OUTSIDE_OVERLAY,
1102        SCROLLBARS_OUTSIDE_INSET
1103    })
1104    @Retention(RetentionPolicy.SOURCE)
1105    public @interface ScrollBarStyle {}
1106
1107    /**
1108     * The scrollbar style to display the scrollbars inside the content area,
1109     * without increasing the padding. The scrollbars will be overlaid with
1110     * translucency on the view's content.
1111     */
1112    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1113
1114    /**
1115     * The scrollbar style to display the scrollbars inside the padded area,
1116     * increasing the padding of the view. The scrollbars will not overlap the
1117     * content area of the view.
1118     */
1119    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1120
1121    /**
1122     * The scrollbar style to display the scrollbars at the edge of the view,
1123     * without increasing the padding. The scrollbars will be overlaid with
1124     * translucency.
1125     */
1126    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1127
1128    /**
1129     * The scrollbar style to display the scrollbars at the edge of the view,
1130     * increasing the padding of the view. The scrollbars will only overlap the
1131     * background, if any.
1132     */
1133    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1134
1135    /**
1136     * Mask to check if the scrollbar style is overlay or inset.
1137     * {@hide}
1138     */
1139    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1140
1141    /**
1142     * Mask to check if the scrollbar style is inside or outside.
1143     * {@hide}
1144     */
1145    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1146
1147    /**
1148     * Mask for scrollbar style.
1149     * {@hide}
1150     */
1151    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1152
1153    /**
1154     * View flag indicating that the screen should remain on while the
1155     * window containing this view is visible to the user.  This effectively
1156     * takes care of automatically setting the WindowManager's
1157     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1158     */
1159    public static final int KEEP_SCREEN_ON = 0x04000000;
1160
1161    /**
1162     * View flag indicating whether this view should have sound effects enabled
1163     * for events such as clicking and touching.
1164     */
1165    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1166
1167    /**
1168     * View flag indicating whether this view should have haptic feedback
1169     * enabled for events such as long presses.
1170     */
1171    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1172
1173    /**
1174     * <p>Indicates that the view hierarchy should stop saving state when
1175     * it reaches this view.  If state saving is initiated immediately at
1176     * the view, it will be allowed.
1177     * {@hide}
1178     */
1179    static final int PARENT_SAVE_DISABLED = 0x20000000;
1180
1181    /**
1182     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1183     * {@hide}
1184     */
1185    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1186
1187    /** @hide */
1188    @IntDef(flag = true,
1189            value = {
1190                FOCUSABLES_ALL,
1191                FOCUSABLES_TOUCH_MODE
1192            })
1193    @Retention(RetentionPolicy.SOURCE)
1194    public @interface FocusableMode {}
1195
1196    /**
1197     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1198     * should add all focusable Views regardless if they are focusable in touch mode.
1199     */
1200    public static final int FOCUSABLES_ALL = 0x00000000;
1201
1202    /**
1203     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1204     * should add only Views focusable in touch mode.
1205     */
1206    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1207
1208    /** @hide */
1209    @IntDef({
1210            FOCUS_BACKWARD,
1211            FOCUS_FORWARD,
1212            FOCUS_LEFT,
1213            FOCUS_UP,
1214            FOCUS_RIGHT,
1215            FOCUS_DOWN
1216    })
1217    @Retention(RetentionPolicy.SOURCE)
1218    public @interface FocusDirection {}
1219
1220    /** @hide */
1221    @IntDef({
1222            FOCUS_LEFT,
1223            FOCUS_UP,
1224            FOCUS_RIGHT,
1225            FOCUS_DOWN
1226    })
1227    @Retention(RetentionPolicy.SOURCE)
1228    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1229
1230    /**
1231     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1232     * item.
1233     */
1234    public static final int FOCUS_BACKWARD = 0x00000001;
1235
1236    /**
1237     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1238     * item.
1239     */
1240    public static final int FOCUS_FORWARD = 0x00000002;
1241
1242    /**
1243     * Use with {@link #focusSearch(int)}. Move focus to the left.
1244     */
1245    public static final int FOCUS_LEFT = 0x00000011;
1246
1247    /**
1248     * Use with {@link #focusSearch(int)}. Move focus up.
1249     */
1250    public static final int FOCUS_UP = 0x00000021;
1251
1252    /**
1253     * Use with {@link #focusSearch(int)}. Move focus to the right.
1254     */
1255    public static final int FOCUS_RIGHT = 0x00000042;
1256
1257    /**
1258     * Use with {@link #focusSearch(int)}. Move focus down.
1259     */
1260    public static final int FOCUS_DOWN = 0x00000082;
1261
1262    /**
1263     * Bits of {@link #getMeasuredWidthAndState()} and
1264     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1265     */
1266    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1267
1268    /**
1269     * Bits of {@link #getMeasuredWidthAndState()} and
1270     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1271     */
1272    public static final int MEASURED_STATE_MASK = 0xff000000;
1273
1274    /**
1275     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1276     * for functions that combine both width and height into a single int,
1277     * such as {@link #getMeasuredState()} and the childState argument of
1278     * {@link #resolveSizeAndState(int, int, int)}.
1279     */
1280    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1281
1282    /**
1283     * Bit of {@link #getMeasuredWidthAndState()} and
1284     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1285     * is smaller that the space the view would like to have.
1286     */
1287    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1288
1289    /**
1290     * Base View state sets
1291     */
1292    // Singles
1293    /**
1294     * Indicates the view has no states set. States are used with
1295     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1296     * view depending on its state.
1297     *
1298     * @see android.graphics.drawable.Drawable
1299     * @see #getDrawableState()
1300     */
1301    protected static final int[] EMPTY_STATE_SET;
1302    /**
1303     * Indicates the view is enabled. States are used with
1304     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1305     * view depending on its state.
1306     *
1307     * @see android.graphics.drawable.Drawable
1308     * @see #getDrawableState()
1309     */
1310    protected static final int[] ENABLED_STATE_SET;
1311    /**
1312     * Indicates the view is focused. States are used with
1313     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1314     * view depending on its state.
1315     *
1316     * @see android.graphics.drawable.Drawable
1317     * @see #getDrawableState()
1318     */
1319    protected static final int[] FOCUSED_STATE_SET;
1320    /**
1321     * Indicates the view is selected. States are used with
1322     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1323     * view depending on its state.
1324     *
1325     * @see android.graphics.drawable.Drawable
1326     * @see #getDrawableState()
1327     */
1328    protected static final int[] SELECTED_STATE_SET;
1329    /**
1330     * Indicates the view is pressed. States are used with
1331     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1332     * view depending on its state.
1333     *
1334     * @see android.graphics.drawable.Drawable
1335     * @see #getDrawableState()
1336     */
1337    protected static final int[] PRESSED_STATE_SET;
1338    /**
1339     * Indicates the view's window has focus. States are used with
1340     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1341     * view depending on its state.
1342     *
1343     * @see android.graphics.drawable.Drawable
1344     * @see #getDrawableState()
1345     */
1346    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1347    // Doubles
1348    /**
1349     * Indicates the view is enabled and has the focus.
1350     *
1351     * @see #ENABLED_STATE_SET
1352     * @see #FOCUSED_STATE_SET
1353     */
1354    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1355    /**
1356     * Indicates the view is enabled and selected.
1357     *
1358     * @see #ENABLED_STATE_SET
1359     * @see #SELECTED_STATE_SET
1360     */
1361    protected static final int[] ENABLED_SELECTED_STATE_SET;
1362    /**
1363     * Indicates the view is enabled and that its window has focus.
1364     *
1365     * @see #ENABLED_STATE_SET
1366     * @see #WINDOW_FOCUSED_STATE_SET
1367     */
1368    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1369    /**
1370     * Indicates the view is focused and selected.
1371     *
1372     * @see #FOCUSED_STATE_SET
1373     * @see #SELECTED_STATE_SET
1374     */
1375    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1376    /**
1377     * Indicates the view has the focus and that its window has the focus.
1378     *
1379     * @see #FOCUSED_STATE_SET
1380     * @see #WINDOW_FOCUSED_STATE_SET
1381     */
1382    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1383    /**
1384     * Indicates the view is selected and that its window has the focus.
1385     *
1386     * @see #SELECTED_STATE_SET
1387     * @see #WINDOW_FOCUSED_STATE_SET
1388     */
1389    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1390    // Triples
1391    /**
1392     * Indicates the view is enabled, focused and selected.
1393     *
1394     * @see #ENABLED_STATE_SET
1395     * @see #FOCUSED_STATE_SET
1396     * @see #SELECTED_STATE_SET
1397     */
1398    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1399    /**
1400     * Indicates the view is enabled, focused and its window has the focus.
1401     *
1402     * @see #ENABLED_STATE_SET
1403     * @see #FOCUSED_STATE_SET
1404     * @see #WINDOW_FOCUSED_STATE_SET
1405     */
1406    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1407    /**
1408     * Indicates the view is enabled, selected and its window has the focus.
1409     *
1410     * @see #ENABLED_STATE_SET
1411     * @see #SELECTED_STATE_SET
1412     * @see #WINDOW_FOCUSED_STATE_SET
1413     */
1414    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1415    /**
1416     * Indicates the view is focused, selected and its window has the focus.
1417     *
1418     * @see #FOCUSED_STATE_SET
1419     * @see #SELECTED_STATE_SET
1420     * @see #WINDOW_FOCUSED_STATE_SET
1421     */
1422    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1423    /**
1424     * Indicates the view is enabled, focused, selected and its window
1425     * has the focus.
1426     *
1427     * @see #ENABLED_STATE_SET
1428     * @see #FOCUSED_STATE_SET
1429     * @see #SELECTED_STATE_SET
1430     * @see #WINDOW_FOCUSED_STATE_SET
1431     */
1432    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1433    /**
1434     * Indicates the view is pressed and its window has the focus.
1435     *
1436     * @see #PRESSED_STATE_SET
1437     * @see #WINDOW_FOCUSED_STATE_SET
1438     */
1439    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1440    /**
1441     * Indicates the view is pressed and selected.
1442     *
1443     * @see #PRESSED_STATE_SET
1444     * @see #SELECTED_STATE_SET
1445     */
1446    protected static final int[] PRESSED_SELECTED_STATE_SET;
1447    /**
1448     * Indicates the view is pressed, selected and its window has the focus.
1449     *
1450     * @see #PRESSED_STATE_SET
1451     * @see #SELECTED_STATE_SET
1452     * @see #WINDOW_FOCUSED_STATE_SET
1453     */
1454    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1455    /**
1456     * Indicates the view is pressed and focused.
1457     *
1458     * @see #PRESSED_STATE_SET
1459     * @see #FOCUSED_STATE_SET
1460     */
1461    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1462    /**
1463     * Indicates the view is pressed, focused and its window has the focus.
1464     *
1465     * @see #PRESSED_STATE_SET
1466     * @see #FOCUSED_STATE_SET
1467     * @see #WINDOW_FOCUSED_STATE_SET
1468     */
1469    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1470    /**
1471     * Indicates the view is pressed, focused and selected.
1472     *
1473     * @see #PRESSED_STATE_SET
1474     * @see #SELECTED_STATE_SET
1475     * @see #FOCUSED_STATE_SET
1476     */
1477    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1478    /**
1479     * Indicates the view is pressed, focused, selected and its window has the focus.
1480     *
1481     * @see #PRESSED_STATE_SET
1482     * @see #FOCUSED_STATE_SET
1483     * @see #SELECTED_STATE_SET
1484     * @see #WINDOW_FOCUSED_STATE_SET
1485     */
1486    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1487    /**
1488     * Indicates the view is pressed and enabled.
1489     *
1490     * @see #PRESSED_STATE_SET
1491     * @see #ENABLED_STATE_SET
1492     */
1493    protected static final int[] PRESSED_ENABLED_STATE_SET;
1494    /**
1495     * Indicates the view is pressed, enabled and its window has the focus.
1496     *
1497     * @see #PRESSED_STATE_SET
1498     * @see #ENABLED_STATE_SET
1499     * @see #WINDOW_FOCUSED_STATE_SET
1500     */
1501    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1502    /**
1503     * Indicates the view is pressed, enabled and selected.
1504     *
1505     * @see #PRESSED_STATE_SET
1506     * @see #ENABLED_STATE_SET
1507     * @see #SELECTED_STATE_SET
1508     */
1509    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1510    /**
1511     * Indicates the view is pressed, enabled, selected and its window has the
1512     * focus.
1513     *
1514     * @see #PRESSED_STATE_SET
1515     * @see #ENABLED_STATE_SET
1516     * @see #SELECTED_STATE_SET
1517     * @see #WINDOW_FOCUSED_STATE_SET
1518     */
1519    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1520    /**
1521     * Indicates the view is pressed, enabled and focused.
1522     *
1523     * @see #PRESSED_STATE_SET
1524     * @see #ENABLED_STATE_SET
1525     * @see #FOCUSED_STATE_SET
1526     */
1527    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1528    /**
1529     * Indicates the view is pressed, enabled, focused and its window has the
1530     * focus.
1531     *
1532     * @see #PRESSED_STATE_SET
1533     * @see #ENABLED_STATE_SET
1534     * @see #FOCUSED_STATE_SET
1535     * @see #WINDOW_FOCUSED_STATE_SET
1536     */
1537    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1538    /**
1539     * Indicates the view is pressed, enabled, focused and selected.
1540     *
1541     * @see #PRESSED_STATE_SET
1542     * @see #ENABLED_STATE_SET
1543     * @see #SELECTED_STATE_SET
1544     * @see #FOCUSED_STATE_SET
1545     */
1546    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1547    /**
1548     * Indicates the view is pressed, enabled, focused, selected and its window
1549     * has the focus.
1550     *
1551     * @see #PRESSED_STATE_SET
1552     * @see #ENABLED_STATE_SET
1553     * @see #SELECTED_STATE_SET
1554     * @see #FOCUSED_STATE_SET
1555     * @see #WINDOW_FOCUSED_STATE_SET
1556     */
1557    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1558
1559    static {
1560        EMPTY_STATE_SET = StateSet.get(0);
1561
1562        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1563
1564        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1565        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1566                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1567
1568        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1569        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1570                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1571        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1572                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1573        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1574                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1575                        | StateSet.VIEW_STATE_FOCUSED);
1576
1577        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1578        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1579                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1580        ENABLED_SELECTED_STATE_SET = StateSet.get(
1581                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1582        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1583                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1584                        | StateSet.VIEW_STATE_ENABLED);
1585        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1586                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1587        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1588                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1589                        | StateSet.VIEW_STATE_ENABLED);
1590        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1591                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1592                        | StateSet.VIEW_STATE_ENABLED);
1593        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1594                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1595                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1596
1597        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1598        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1599                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1600        PRESSED_SELECTED_STATE_SET = StateSet.get(
1601                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1602        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1603                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1604                        | StateSet.VIEW_STATE_PRESSED);
1605        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1606                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1607        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1608                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1609                        | StateSet.VIEW_STATE_PRESSED);
1610        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1611                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1612                        | StateSet.VIEW_STATE_PRESSED);
1613        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1614                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1615                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1616        PRESSED_ENABLED_STATE_SET = StateSet.get(
1617                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1618        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1619                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1620                        | StateSet.VIEW_STATE_PRESSED);
1621        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1622                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1623                        | StateSet.VIEW_STATE_PRESSED);
1624        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1625                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1626                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1627        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1628                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1629                        | StateSet.VIEW_STATE_PRESSED);
1630        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1631                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1632                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1633        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1634                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1635                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1636        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1637                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1638                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1639                        | StateSet.VIEW_STATE_PRESSED);
1640    }
1641
1642    /**
1643     * Accessibility event types that are dispatched for text population.
1644     */
1645    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1646            AccessibilityEvent.TYPE_VIEW_CLICKED
1647            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1648            | AccessibilityEvent.TYPE_VIEW_SELECTED
1649            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1650            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1651            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1652            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1653            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1654            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1655            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1656            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1657
1658    /**
1659     * Temporary Rect currently for use in setBackground().  This will probably
1660     * be extended in the future to hold our own class with more than just
1661     * a Rect. :)
1662     */
1663    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1664
1665    /**
1666     * Map used to store views' tags.
1667     */
1668    private SparseArray<Object> mKeyedTags;
1669
1670    /**
1671     * The next available accessibility id.
1672     */
1673    private static int sNextAccessibilityViewId;
1674
1675    /**
1676     * The animation currently associated with this view.
1677     * @hide
1678     */
1679    protected Animation mCurrentAnimation = null;
1680
1681    /**
1682     * Width as measured during measure pass.
1683     * {@hide}
1684     */
1685    @ViewDebug.ExportedProperty(category = "measurement")
1686    int mMeasuredWidth;
1687
1688    /**
1689     * Height as measured during measure pass.
1690     * {@hide}
1691     */
1692    @ViewDebug.ExportedProperty(category = "measurement")
1693    int mMeasuredHeight;
1694
1695    /**
1696     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1697     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1698     * its display list. This flag, used only when hw accelerated, allows us to clear the
1699     * flag while retaining this information until it's needed (at getDisplayList() time and
1700     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1701     *
1702     * {@hide}
1703     */
1704    boolean mRecreateDisplayList = false;
1705
1706    /**
1707     * The view's identifier.
1708     * {@hide}
1709     *
1710     * @see #setId(int)
1711     * @see #getId()
1712     */
1713    @IdRes
1714    @ViewDebug.ExportedProperty(resolveId = true)
1715    int mID = NO_ID;
1716
1717    /**
1718     * The stable ID of this view for accessibility purposes.
1719     */
1720    int mAccessibilityViewId = NO_ID;
1721
1722    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1723
1724    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1725
1726    /**
1727     * The view's tag.
1728     * {@hide}
1729     *
1730     * @see #setTag(Object)
1731     * @see #getTag()
1732     */
1733    protected Object mTag = null;
1734
1735    // for mPrivateFlags:
1736    /** {@hide} */
1737    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1738    /** {@hide} */
1739    static final int PFLAG_FOCUSED                     = 0x00000002;
1740    /** {@hide} */
1741    static final int PFLAG_SELECTED                    = 0x00000004;
1742    /** {@hide} */
1743    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1744    /** {@hide} */
1745    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1746    /** {@hide} */
1747    static final int PFLAG_DRAWN                       = 0x00000020;
1748    /**
1749     * When this flag is set, this view is running an animation on behalf of its
1750     * children and should therefore not cancel invalidate requests, even if they
1751     * lie outside of this view's bounds.
1752     *
1753     * {@hide}
1754     */
1755    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1756    /** {@hide} */
1757    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1758    /** {@hide} */
1759    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1760    /** {@hide} */
1761    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1762    /** {@hide} */
1763    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1764    /** {@hide} */
1765    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1766    /** {@hide} */
1767    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1768
1769    private static final int PFLAG_PRESSED             = 0x00004000;
1770
1771    /** {@hide} */
1772    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1773    /**
1774     * Flag used to indicate that this view should be drawn once more (and only once
1775     * more) after its animation has completed.
1776     * {@hide}
1777     */
1778    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1779
1780    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1781
1782    /**
1783     * Indicates that the View returned true when onSetAlpha() was called and that
1784     * the alpha must be restored.
1785     * {@hide}
1786     */
1787    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1788
1789    /**
1790     * Set by {@link #setScrollContainer(boolean)}.
1791     */
1792    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1793
1794    /**
1795     * Set by {@link #setScrollContainer(boolean)}.
1796     */
1797    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1798
1799    /**
1800     * View flag indicating whether this view was invalidated (fully or partially.)
1801     *
1802     * @hide
1803     */
1804    static final int PFLAG_DIRTY                       = 0x00200000;
1805
1806    /**
1807     * View flag indicating whether this view was invalidated by an opaque
1808     * invalidate request.
1809     *
1810     * @hide
1811     */
1812    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1813
1814    /**
1815     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1816     *
1817     * @hide
1818     */
1819    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1820
1821    /**
1822     * Indicates whether the background is opaque.
1823     *
1824     * @hide
1825     */
1826    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1827
1828    /**
1829     * Indicates whether the scrollbars are opaque.
1830     *
1831     * @hide
1832     */
1833    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1834
1835    /**
1836     * Indicates whether the view is opaque.
1837     *
1838     * @hide
1839     */
1840    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1841
1842    /**
1843     * Indicates a prepressed state;
1844     * the short time between ACTION_DOWN and recognizing
1845     * a 'real' press. Prepressed is used to recognize quick taps
1846     * even when they are shorter than ViewConfiguration.getTapTimeout().
1847     *
1848     * @hide
1849     */
1850    private static final int PFLAG_PREPRESSED          = 0x02000000;
1851
1852    /**
1853     * Indicates whether the view is temporarily detached.
1854     *
1855     * @hide
1856     */
1857    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1858
1859    /**
1860     * Indicates that we should awaken scroll bars once attached
1861     *
1862     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1863     * during window attachment and it is no longer needed. Feel free to repurpose it.
1864     *
1865     * @hide
1866     */
1867    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1868
1869    /**
1870     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1871     * @hide
1872     */
1873    private static final int PFLAG_HOVERED             = 0x10000000;
1874
1875    /**
1876     * no longer needed, should be reused
1877     */
1878    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1879
1880    /** {@hide} */
1881    static final int PFLAG_ACTIVATED                   = 0x40000000;
1882
1883    /**
1884     * Indicates that this view was specifically invalidated, not just dirtied because some
1885     * child view was invalidated. The flag is used to determine when we need to recreate
1886     * a view's display list (as opposed to just returning a reference to its existing
1887     * display list).
1888     *
1889     * @hide
1890     */
1891    static final int PFLAG_INVALIDATED                 = 0x80000000;
1892
1893    /**
1894     * Masks for mPrivateFlags2, as generated by dumpFlags():
1895     *
1896     * |-------|-------|-------|-------|
1897     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1898     *                                1  PFLAG2_DRAG_HOVERED
1899     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1900     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1901     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1902     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1903     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1904     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1905     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1906     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1907     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1908     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1909     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1910     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1911     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1912     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1913     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1914     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1915     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1916     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1917     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1918     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1919     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1920     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1921     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1922     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1923     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1924     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1925     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1926     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1927     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1928     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1929     *    1                              PFLAG2_PADDING_RESOLVED
1930     *   1                               PFLAG2_DRAWABLE_RESOLVED
1931     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1932     * |-------|-------|-------|-------|
1933     */
1934
1935    /**
1936     * Indicates that this view has reported that it can accept the current drag's content.
1937     * Cleared when the drag operation concludes.
1938     * @hide
1939     */
1940    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1941
1942    /**
1943     * Indicates that this view is currently directly under the drag location in a
1944     * drag-and-drop operation involving content that it can accept.  Cleared when
1945     * the drag exits the view, or when the drag operation concludes.
1946     * @hide
1947     */
1948    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1949
1950    /** @hide */
1951    @IntDef({
1952        LAYOUT_DIRECTION_LTR,
1953        LAYOUT_DIRECTION_RTL,
1954        LAYOUT_DIRECTION_INHERIT,
1955        LAYOUT_DIRECTION_LOCALE
1956    })
1957    @Retention(RetentionPolicy.SOURCE)
1958    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1959    public @interface LayoutDir {}
1960
1961    /** @hide */
1962    @IntDef({
1963        LAYOUT_DIRECTION_LTR,
1964        LAYOUT_DIRECTION_RTL
1965    })
1966    @Retention(RetentionPolicy.SOURCE)
1967    public @interface ResolvedLayoutDir {}
1968
1969    /**
1970     * A flag to indicate that the layout direction of this view has not been defined yet.
1971     * @hide
1972     */
1973    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1974
1975    /**
1976     * Horizontal layout direction of this view is from Left to Right.
1977     * Use with {@link #setLayoutDirection}.
1978     */
1979    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1980
1981    /**
1982     * Horizontal layout direction of this view is from Right to Left.
1983     * Use with {@link #setLayoutDirection}.
1984     */
1985    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1986
1987    /**
1988     * Horizontal layout direction of this view is inherited from its parent.
1989     * Use with {@link #setLayoutDirection}.
1990     */
1991    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1992
1993    /**
1994     * Horizontal layout direction of this view is from deduced from the default language
1995     * script for the locale. Use with {@link #setLayoutDirection}.
1996     */
1997    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1998
1999    /**
2000     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2001     * @hide
2002     */
2003    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2004
2005    /**
2006     * Mask for use with private flags indicating bits used for horizontal layout direction.
2007     * @hide
2008     */
2009    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2010
2011    /**
2012     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2013     * right-to-left direction.
2014     * @hide
2015     */
2016    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2017
2018    /**
2019     * Indicates whether the view horizontal layout direction has been resolved.
2020     * @hide
2021     */
2022    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2023
2024    /**
2025     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2026     * @hide
2027     */
2028    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2029            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2030
2031    /*
2032     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2033     * flag value.
2034     * @hide
2035     */
2036    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2037            LAYOUT_DIRECTION_LTR,
2038            LAYOUT_DIRECTION_RTL,
2039            LAYOUT_DIRECTION_INHERIT,
2040            LAYOUT_DIRECTION_LOCALE
2041    };
2042
2043    /**
2044     * Default horizontal layout direction.
2045     */
2046    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2047
2048    /**
2049     * Default horizontal layout direction.
2050     * @hide
2051     */
2052    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2053
2054    /**
2055     * Text direction is inherited through {@link ViewGroup}
2056     */
2057    public static final int TEXT_DIRECTION_INHERIT = 0;
2058
2059    /**
2060     * Text direction is using "first strong algorithm". The first strong directional character
2061     * determines the paragraph direction. If there is no strong directional character, the
2062     * paragraph direction is the view's resolved layout direction.
2063     */
2064    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2065
2066    /**
2067     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2068     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2069     * If there are neither, the paragraph direction is the view's resolved layout direction.
2070     */
2071    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2072
2073    /**
2074     * Text direction is forced to LTR.
2075     */
2076    public static final int TEXT_DIRECTION_LTR = 3;
2077
2078    /**
2079     * Text direction is forced to RTL.
2080     */
2081    public static final int TEXT_DIRECTION_RTL = 4;
2082
2083    /**
2084     * Text direction is coming from the system Locale.
2085     */
2086    public static final int TEXT_DIRECTION_LOCALE = 5;
2087
2088    /**
2089     * Text direction is using "first strong algorithm". The first strong directional character
2090     * determines the paragraph direction. If there is no strong directional character, the
2091     * paragraph direction is LTR.
2092     */
2093    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2094
2095    /**
2096     * Text direction is using "first strong algorithm". The first strong directional character
2097     * determines the paragraph direction. If there is no strong directional character, the
2098     * paragraph direction is RTL.
2099     */
2100    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2101
2102    /**
2103     * Default text direction is inherited
2104     */
2105    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2106
2107    /**
2108     * Default resolved text direction
2109     * @hide
2110     */
2111    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2112
2113    /**
2114     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2115     * @hide
2116     */
2117    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2118
2119    /**
2120     * Mask for use with private flags indicating bits used for text direction.
2121     * @hide
2122     */
2123    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2124            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2125
2126    /**
2127     * Array of text direction flags for mapping attribute "textDirection" to correct
2128     * flag value.
2129     * @hide
2130     */
2131    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2132            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2133            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2134            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2135            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2136            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2137            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2138            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2139            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2140    };
2141
2142    /**
2143     * Indicates whether the view text direction has been resolved.
2144     * @hide
2145     */
2146    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2147            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2148
2149    /**
2150     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2151     * @hide
2152     */
2153    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2154
2155    /**
2156     * Mask for use with private flags indicating bits used for resolved text direction.
2157     * @hide
2158     */
2159    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2160            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2161
2162    /**
2163     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2164     * @hide
2165     */
2166    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2167            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2168
2169    /** @hide */
2170    @IntDef({
2171        TEXT_ALIGNMENT_INHERIT,
2172        TEXT_ALIGNMENT_GRAVITY,
2173        TEXT_ALIGNMENT_CENTER,
2174        TEXT_ALIGNMENT_TEXT_START,
2175        TEXT_ALIGNMENT_TEXT_END,
2176        TEXT_ALIGNMENT_VIEW_START,
2177        TEXT_ALIGNMENT_VIEW_END
2178    })
2179    @Retention(RetentionPolicy.SOURCE)
2180    public @interface TextAlignment {}
2181
2182    /**
2183     * Default text alignment. The text alignment of this View is inherited from its parent.
2184     * Use with {@link #setTextAlignment(int)}
2185     */
2186    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2187
2188    /**
2189     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2190     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2191     *
2192     * Use with {@link #setTextAlignment(int)}
2193     */
2194    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2195
2196    /**
2197     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2198     *
2199     * Use with {@link #setTextAlignment(int)}
2200     */
2201    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2202
2203    /**
2204     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2205     *
2206     * Use with {@link #setTextAlignment(int)}
2207     */
2208    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2209
2210    /**
2211     * Center the paragraph, e.g. ALIGN_CENTER.
2212     *
2213     * Use with {@link #setTextAlignment(int)}
2214     */
2215    public static final int TEXT_ALIGNMENT_CENTER = 4;
2216
2217    /**
2218     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2219     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2220     *
2221     * Use with {@link #setTextAlignment(int)}
2222     */
2223    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2224
2225    /**
2226     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2227     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2228     *
2229     * Use with {@link #setTextAlignment(int)}
2230     */
2231    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2232
2233    /**
2234     * Default text alignment is inherited
2235     */
2236    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2237
2238    /**
2239     * Default resolved text alignment
2240     * @hide
2241     */
2242    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2243
2244    /**
2245      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2246      * @hide
2247      */
2248    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2249
2250    /**
2251      * Mask for use with private flags indicating bits used for text alignment.
2252      * @hide
2253      */
2254    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2255
2256    /**
2257     * Array of text direction flags for mapping attribute "textAlignment" to correct
2258     * flag value.
2259     * @hide
2260     */
2261    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2262            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2263            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2264            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2265            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2266            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2267            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2268            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2269    };
2270
2271    /**
2272     * Indicates whether the view text alignment has been resolved.
2273     * @hide
2274     */
2275    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2276
2277    /**
2278     * Bit shift to get the resolved text alignment.
2279     * @hide
2280     */
2281    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2282
2283    /**
2284     * Mask for use with private flags indicating bits used for text alignment.
2285     * @hide
2286     */
2287    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2288            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2289
2290    /**
2291     * Indicates whether if the view text alignment has been resolved to gravity
2292     */
2293    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2294            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2295
2296    // Accessiblity constants for mPrivateFlags2
2297
2298    /**
2299     * Shift for the bits in {@link #mPrivateFlags2} related to the
2300     * "importantForAccessibility" attribute.
2301     */
2302    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2303
2304    /**
2305     * Automatically determine whether a view is important for accessibility.
2306     */
2307    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2308
2309    /**
2310     * The view is important for accessibility.
2311     */
2312    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2313
2314    /**
2315     * The view is not important for accessibility.
2316     */
2317    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2318
2319    /**
2320     * The view is not important for accessibility, nor are any of its
2321     * descendant views.
2322     */
2323    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2324
2325    /**
2326     * The default whether the view is important for accessibility.
2327     */
2328    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2329
2330    /**
2331     * Mask for obtainig the bits which specify how to determine
2332     * whether a view is important for accessibility.
2333     */
2334    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2335        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2336        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2337        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2338
2339    /**
2340     * Shift for the bits in {@link #mPrivateFlags2} related to the
2341     * "accessibilityLiveRegion" attribute.
2342     */
2343    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2344
2345    /**
2346     * Live region mode specifying that accessibility services should not
2347     * automatically announce changes to this view. This is the default live
2348     * region mode for most views.
2349     * <p>
2350     * Use with {@link #setAccessibilityLiveRegion(int)}.
2351     */
2352    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2353
2354    /**
2355     * Live region mode specifying that accessibility services should announce
2356     * changes to this view.
2357     * <p>
2358     * Use with {@link #setAccessibilityLiveRegion(int)}.
2359     */
2360    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2361
2362    /**
2363     * Live region mode specifying that accessibility services should interrupt
2364     * ongoing speech to immediately announce changes to this view.
2365     * <p>
2366     * Use with {@link #setAccessibilityLiveRegion(int)}.
2367     */
2368    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2369
2370    /**
2371     * The default whether the view is important for accessibility.
2372     */
2373    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2374
2375    /**
2376     * Mask for obtaining the bits which specify a view's accessibility live
2377     * region mode.
2378     */
2379    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2380            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2381            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2382
2383    /**
2384     * Flag indicating whether a view has accessibility focus.
2385     */
2386    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2387
2388    /**
2389     * Flag whether the accessibility state of the subtree rooted at this view changed.
2390     */
2391    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2392
2393    /**
2394     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2395     * is used to check whether later changes to the view's transform should invalidate the
2396     * view to force the quickReject test to run again.
2397     */
2398    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2399
2400    /**
2401     * Flag indicating that start/end padding has been resolved into left/right padding
2402     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2403     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2404     * during measurement. In some special cases this is required such as when an adapter-based
2405     * view measures prospective children without attaching them to a window.
2406     */
2407    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2408
2409    /**
2410     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2411     */
2412    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2413
2414    /**
2415     * Indicates that the view is tracking some sort of transient state
2416     * that the app should not need to be aware of, but that the framework
2417     * should take special care to preserve.
2418     */
2419    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2420
2421    /**
2422     * Group of bits indicating that RTL properties resolution is done.
2423     */
2424    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2425            PFLAG2_TEXT_DIRECTION_RESOLVED |
2426            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2427            PFLAG2_PADDING_RESOLVED |
2428            PFLAG2_DRAWABLE_RESOLVED;
2429
2430    // There are a couple of flags left in mPrivateFlags2
2431
2432    /* End of masks for mPrivateFlags2 */
2433
2434    /**
2435     * Masks for mPrivateFlags3, as generated by dumpFlags():
2436     *
2437     * |-------|-------|-------|-------|
2438     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2439     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2440     *                               1   PFLAG3_IS_LAID_OUT
2441     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2442     *                             1     PFLAG3_CALLED_SUPER
2443     *                            1      PFLAG3_APPLYING_INSETS
2444     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2445     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2446     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2447     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2448     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2449     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2450     *                     1             PFLAG3_SCROLL_INDICATOR_START
2451     *                    1              PFLAG3_SCROLL_INDICATOR_END
2452     *                   1               PFLAG3_ASSIST_BLOCKED
2453     *                  1                PFLAG3_POINTER_ICON_NULL
2454     *                 1                 PFLAG3_POINTER_ICON_VALUE_START
2455     *           11111111                PFLAG3_POINTER_ICON_MASK
2456     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2457     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2458     *        1                          PFLAG3_TEMPORARY_DETACH
2459     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2460     * |-------|-------|-------|-------|
2461     */
2462
2463    /**
2464     * Flag indicating that view has a transform animation set on it. This is used to track whether
2465     * an animation is cleared between successive frames, in order to tell the associated
2466     * DisplayList to clear its animation matrix.
2467     */
2468    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2469
2470    /**
2471     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2472     * animation is cleared between successive frames, in order to tell the associated
2473     * DisplayList to restore its alpha value.
2474     */
2475    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2476
2477    /**
2478     * Flag indicating that the view has been through at least one layout since it
2479     * was last attached to a window.
2480     */
2481    static final int PFLAG3_IS_LAID_OUT = 0x4;
2482
2483    /**
2484     * Flag indicating that a call to measure() was skipped and should be done
2485     * instead when layout() is invoked.
2486     */
2487    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2488
2489    /**
2490     * Flag indicating that an overridden method correctly called down to
2491     * the superclass implementation as required by the API spec.
2492     */
2493    static final int PFLAG3_CALLED_SUPER = 0x10;
2494
2495    /**
2496     * Flag indicating that we're in the process of applying window insets.
2497     */
2498    static final int PFLAG3_APPLYING_INSETS = 0x20;
2499
2500    /**
2501     * Flag indicating that we're in the process of fitting system windows using the old method.
2502     */
2503    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2504
2505    /**
2506     * Flag indicating that nested scrolling is enabled for this view.
2507     * The view will optionally cooperate with views up its parent chain to allow for
2508     * integrated nested scrolling along the same axis.
2509     */
2510    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2511
2512    /**
2513     * Flag indicating that the bottom scroll indicator should be displayed
2514     * when this view can scroll up.
2515     */
2516    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2517
2518    /**
2519     * Flag indicating that the bottom scroll indicator should be displayed
2520     * when this view can scroll down.
2521     */
2522    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2523
2524    /**
2525     * Flag indicating that the left scroll indicator should be displayed
2526     * when this view can scroll left.
2527     */
2528    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2529
2530    /**
2531     * Flag indicating that the right scroll indicator should be displayed
2532     * when this view can scroll right.
2533     */
2534    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2535
2536    /**
2537     * Flag indicating that the start scroll indicator should be displayed
2538     * when this view can scroll in the start direction.
2539     */
2540    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2541
2542    /**
2543     * Flag indicating that the end scroll indicator should be displayed
2544     * when this view can scroll in the end direction.
2545     */
2546    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2547
2548    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2549
2550    static final int SCROLL_INDICATORS_NONE = 0x0000;
2551
2552    /**
2553     * Mask for use with setFlags indicating bits used for indicating which
2554     * scroll indicators are enabled.
2555     */
2556    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2557            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2558            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2559            | PFLAG3_SCROLL_INDICATOR_END;
2560
2561    /**
2562     * Left-shift required to translate between public scroll indicator flags
2563     * and internal PFLAGS3 flags. When used as a right-shift, translates
2564     * PFLAGS3 flags to public flags.
2565     */
2566    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2567
2568    /** @hide */
2569    @Retention(RetentionPolicy.SOURCE)
2570    @IntDef(flag = true,
2571            value = {
2572                    SCROLL_INDICATOR_TOP,
2573                    SCROLL_INDICATOR_BOTTOM,
2574                    SCROLL_INDICATOR_LEFT,
2575                    SCROLL_INDICATOR_RIGHT,
2576                    SCROLL_INDICATOR_START,
2577                    SCROLL_INDICATOR_END,
2578            })
2579    public @interface ScrollIndicators {}
2580
2581    /**
2582     * Scroll indicator direction for the top edge of the view.
2583     *
2584     * @see #setScrollIndicators(int)
2585     * @see #setScrollIndicators(int, int)
2586     * @see #getScrollIndicators()
2587     */
2588    public static final int SCROLL_INDICATOR_TOP =
2589            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2590
2591    /**
2592     * Scroll indicator direction for the bottom edge of the view.
2593     *
2594     * @see #setScrollIndicators(int)
2595     * @see #setScrollIndicators(int, int)
2596     * @see #getScrollIndicators()
2597     */
2598    public static final int SCROLL_INDICATOR_BOTTOM =
2599            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2600
2601    /**
2602     * Scroll indicator direction for the left edge of the view.
2603     *
2604     * @see #setScrollIndicators(int)
2605     * @see #setScrollIndicators(int, int)
2606     * @see #getScrollIndicators()
2607     */
2608    public static final int SCROLL_INDICATOR_LEFT =
2609            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2610
2611    /**
2612     * Scroll indicator direction for the right edge of the view.
2613     *
2614     * @see #setScrollIndicators(int)
2615     * @see #setScrollIndicators(int, int)
2616     * @see #getScrollIndicators()
2617     */
2618    public static final int SCROLL_INDICATOR_RIGHT =
2619            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2620
2621    /**
2622     * Scroll indicator direction for the starting 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_START =
2632            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2633
2634    /**
2635     * Scroll indicator direction for the ending edge of the view.
2636     * <p>
2637     * Resolved according to the view's layout direction, see
2638     * {@link #getLayoutDirection()} for more information.
2639     *
2640     * @see #setScrollIndicators(int)
2641     * @see #setScrollIndicators(int, int)
2642     * @see #getScrollIndicators()
2643     */
2644    public static final int SCROLL_INDICATOR_END =
2645            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2646
2647    /**
2648     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2649     * into this view.<p>
2650     */
2651    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2652
2653    /**
2654     * The mask for use with private flags indicating bits used for pointer icon shapes.
2655     */
2656    static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
2657
2658    /**
2659     * Left-shift used for pointer icon shape values in private flags.
2660     */
2661    static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
2662
2663    /**
2664     * Value indicating no specific pointer icons.
2665     */
2666    private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
2667
2668    /**
2669     * Value indicating {@link PointerIcon.TYPE_NULL}.
2670     */
2671    private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
2672
2673    /**
2674     * The base value for other pointer icon shapes.
2675     */
2676    private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
2677
2678    /**
2679     * Whether this view has rendered elements that overlap (see {@link
2680     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2681     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2682     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2683     * determined by whatever {@link #hasOverlappingRendering()} returns.
2684     */
2685    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2686
2687    /**
2688     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2689     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2690     */
2691    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2692
2693    /**
2694     * Flag indicating that the view is temporarily detached from the parent view.
2695     *
2696     * @see #onStartTemporaryDetach()
2697     * @see #onFinishTemporaryDetach()
2698     */
2699    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
2700
2701    /**
2702     * Flag indicating that the view does not wish to be revealed within its parent
2703     * hierarchy when it gains focus. Expressed in the negative since the historical
2704     * default behavior is to reveal on focus; this flag suppresses that behavior.
2705     *
2706     * @see #setRevealOnFocusHint(boolean)
2707     * @see #getRevealOnFocusHint()
2708     */
2709    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
2710
2711    /* End of masks for mPrivateFlags3 */
2712
2713    /**
2714     * Always allow a user to over-scroll this view, provided it is a
2715     * view that can scroll.
2716     *
2717     * @see #getOverScrollMode()
2718     * @see #setOverScrollMode(int)
2719     */
2720    public static final int OVER_SCROLL_ALWAYS = 0;
2721
2722    /**
2723     * Allow a user to over-scroll this view only if the content is large
2724     * enough to meaningfully scroll, provided it is a view that can scroll.
2725     *
2726     * @see #getOverScrollMode()
2727     * @see #setOverScrollMode(int)
2728     */
2729    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2730
2731    /**
2732     * Never allow a user to over-scroll this view.
2733     *
2734     * @see #getOverScrollMode()
2735     * @see #setOverScrollMode(int)
2736     */
2737    public static final int OVER_SCROLL_NEVER = 2;
2738
2739    /**
2740     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2741     * requested the system UI (status bar) to be visible (the default).
2742     *
2743     * @see #setSystemUiVisibility(int)
2744     */
2745    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2746
2747    /**
2748     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2749     * system UI to enter an unobtrusive "low profile" mode.
2750     *
2751     * <p>This is for use in games, book readers, video players, or any other
2752     * "immersive" application where the usual system chrome is deemed too distracting.
2753     *
2754     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2755     *
2756     * @see #setSystemUiVisibility(int)
2757     */
2758    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2759
2760    /**
2761     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2762     * system navigation be temporarily hidden.
2763     *
2764     * <p>This is an even less obtrusive state than that called for by
2765     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2766     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2767     * those to disappear. This is useful (in conjunction with the
2768     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2769     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2770     * window flags) for displaying content using every last pixel on the display.
2771     *
2772     * <p>There is a limitation: because navigation controls are so important, the least user
2773     * interaction will cause them to reappear immediately.  When this happens, both
2774     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2775     * so that both elements reappear at the same time.
2776     *
2777     * @see #setSystemUiVisibility(int)
2778     */
2779    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2780
2781    /**
2782     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2783     * into the normal fullscreen mode so that its content can take over the screen
2784     * while still allowing the user to interact with the application.
2785     *
2786     * <p>This has the same visual effect as
2787     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2788     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2789     * meaning that non-critical screen decorations (such as the status bar) will be
2790     * hidden while the user is in the View's window, focusing the experience on
2791     * that content.  Unlike the window flag, if you are using ActionBar in
2792     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2793     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2794     * hide the action bar.
2795     *
2796     * <p>This approach to going fullscreen is best used over the window flag when
2797     * it is a transient state -- that is, the application does this at certain
2798     * points in its user interaction where it wants to allow the user to focus
2799     * on content, but not as a continuous state.  For situations where the application
2800     * would like to simply stay full screen the entire time (such as a game that
2801     * wants to take over the screen), the
2802     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2803     * is usually a better approach.  The state set here will be removed by the system
2804     * in various situations (such as the user moving to another application) like
2805     * the other system UI states.
2806     *
2807     * <p>When using this flag, the application should provide some easy facility
2808     * for the user to go out of it.  A common example would be in an e-book
2809     * reader, where tapping on the screen brings back whatever screen and UI
2810     * decorations that had been hidden while the user was immersed in reading
2811     * the book.
2812     *
2813     * @see #setSystemUiVisibility(int)
2814     */
2815    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2816
2817    /**
2818     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2819     * flags, we would like a stable view of the content insets given to
2820     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2821     * will always represent the worst case that the application can expect
2822     * as a continuous state.  In the stock Android UI this is the space for
2823     * the system bar, nav bar, and status bar, but not more transient elements
2824     * such as an input method.
2825     *
2826     * The stable layout your UI sees is based on the system UI modes you can
2827     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2828     * then you will get a stable layout for changes of the
2829     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2830     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2831     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2832     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2833     * with a stable layout.  (Note that you should avoid using
2834     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2835     *
2836     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2837     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2838     * then a hidden status bar will be considered a "stable" state for purposes
2839     * here.  This allows your UI to continually hide the status bar, while still
2840     * using the system UI flags to hide the action bar while still retaining
2841     * a stable layout.  Note that changing the window fullscreen flag will never
2842     * provide a stable layout for a clean transition.
2843     *
2844     * <p>If you are using ActionBar in
2845     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2846     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2847     * insets it adds to those given to the application.
2848     */
2849    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2850
2851    /**
2852     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2853     * to be laid out as if it has requested
2854     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2855     * allows it to avoid artifacts when switching in and out of that mode, at
2856     * the expense that some of its user interface may be covered by screen
2857     * decorations when they are shown.  You can perform layout of your inner
2858     * UI elements to account for the navigation system UI through the
2859     * {@link #fitSystemWindows(Rect)} method.
2860     */
2861    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2862
2863    /**
2864     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2865     * to be laid out as if it has requested
2866     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2867     * allows it to avoid artifacts when switching in and out of that mode, at
2868     * the expense that some of its user interface may be covered by screen
2869     * decorations when they are shown.  You can perform layout of your inner
2870     * UI elements to account for non-fullscreen system UI through the
2871     * {@link #fitSystemWindows(Rect)} method.
2872     */
2873    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2874
2875    /**
2876     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2877     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2878     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2879     * user interaction.
2880     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2881     * has an effect when used in combination with that flag.</p>
2882     */
2883    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2884
2885    /**
2886     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2887     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2888     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2889     * experience while also hiding the system bars.  If this flag is not set,
2890     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2891     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2892     * if the user swipes from the top of the screen.
2893     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2894     * system gestures, such as swiping from the top of the screen.  These transient system bars
2895     * will overlay app’s content, may have some degree of transparency, and will automatically
2896     * hide after a short timeout.
2897     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2898     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2899     * with one or both of those flags.</p>
2900     */
2901    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2902
2903    /**
2904     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2905     * is compatible with light status bar backgrounds.
2906     *
2907     * <p>For this to take effect, the window must request
2908     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2909     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2910     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2911     *         FLAG_TRANSLUCENT_STATUS}.
2912     *
2913     * @see android.R.attr#windowLightStatusBar
2914     */
2915    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2916
2917    /**
2918     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2919     */
2920    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2921
2922    /**
2923     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2924     */
2925    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2926
2927    /**
2928     * @hide
2929     *
2930     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2931     * out of the public fields to keep the undefined bits out of the developer's way.
2932     *
2933     * Flag to make the status bar not expandable.  Unless you also
2934     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2935     */
2936    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2937
2938    /**
2939     * @hide
2940     *
2941     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2942     * out of the public fields to keep the undefined bits out of the developer's way.
2943     *
2944     * Flag to hide notification icons and scrolling ticker text.
2945     */
2946    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2947
2948    /**
2949     * @hide
2950     *
2951     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2952     * out of the public fields to keep the undefined bits out of the developer's way.
2953     *
2954     * Flag to disable incoming notification alerts.  This will not block
2955     * icons, but it will block sound, vibrating and other visual or aural notifications.
2956     */
2957    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2958
2959    /**
2960     * @hide
2961     *
2962     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2963     * out of the public fields to keep the undefined bits out of the developer's way.
2964     *
2965     * Flag to hide only the scrolling ticker.  Note that
2966     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2967     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2968     */
2969    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2970
2971    /**
2972     * @hide
2973     *
2974     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2975     * out of the public fields to keep the undefined bits out of the developer's way.
2976     *
2977     * Flag to hide the center system info area.
2978     */
2979    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2980
2981    /**
2982     * @hide
2983     *
2984     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2985     * out of the public fields to keep the undefined bits out of the developer's way.
2986     *
2987     * Flag to hide only the home button.  Don't use this
2988     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2989     */
2990    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2991
2992    /**
2993     * @hide
2994     *
2995     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2996     * out of the public fields to keep the undefined bits out of the developer's way.
2997     *
2998     * Flag to hide only the back button. Don't use this
2999     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3000     */
3001    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3002
3003    /**
3004     * @hide
3005     *
3006     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3007     * out of the public fields to keep the undefined bits out of the developer's way.
3008     *
3009     * Flag to hide only the clock.  You might use this if your activity has
3010     * its own clock making the status bar's clock redundant.
3011     */
3012    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3013
3014    /**
3015     * @hide
3016     *
3017     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3018     * out of the public fields to keep the undefined bits out of the developer's way.
3019     *
3020     * Flag to hide only the recent apps button. Don't use this
3021     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3022     */
3023    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3024
3025    /**
3026     * @hide
3027     *
3028     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3029     * out of the public fields to keep the undefined bits out of the developer's way.
3030     *
3031     * Flag to disable the global search gesture. Don't use this
3032     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3033     */
3034    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3035
3036    /**
3037     * @hide
3038     *
3039     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3040     * out of the public fields to keep the undefined bits out of the developer's way.
3041     *
3042     * Flag to specify that the status bar is displayed in transient mode.
3043     */
3044    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3045
3046    /**
3047     * @hide
3048     *
3049     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3050     * out of the public fields to keep the undefined bits out of the developer's way.
3051     *
3052     * Flag to specify that the navigation bar is displayed in transient mode.
3053     */
3054    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3055
3056    /**
3057     * @hide
3058     *
3059     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3060     * out of the public fields to keep the undefined bits out of the developer's way.
3061     *
3062     * Flag to specify that the hidden status bar would like to be shown.
3063     */
3064    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3065
3066    /**
3067     * @hide
3068     *
3069     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3070     * out of the public fields to keep the undefined bits out of the developer's way.
3071     *
3072     * Flag to specify that the hidden navigation bar would like to be shown.
3073     */
3074    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3075
3076    /**
3077     * @hide
3078     *
3079     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3080     * out of the public fields to keep the undefined bits out of the developer's way.
3081     *
3082     * Flag to specify that the status bar is displayed in translucent mode.
3083     */
3084    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3085
3086    /**
3087     * @hide
3088     *
3089     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3090     * out of the public fields to keep the undefined bits out of the developer's way.
3091     *
3092     * Flag to specify that the navigation bar is displayed in translucent mode.
3093     */
3094    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3095
3096    /**
3097     * @hide
3098     *
3099     * Whether Recents is visible or not.
3100     */
3101    public static final int RECENT_APPS_VISIBLE = 0x00004000;
3102
3103    /**
3104     * @hide
3105     *
3106     * Whether the TV's picture-in-picture is visible or not.
3107     */
3108    public static final int TV_PICTURE_IN_PICTURE_VISIBLE = 0x00010000;
3109
3110    /**
3111     * @hide
3112     *
3113     * Makes navigation bar transparent (but not the status bar).
3114     */
3115    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3116
3117    /**
3118     * @hide
3119     *
3120     * Makes status bar transparent (but not the navigation bar).
3121     */
3122    public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
3123
3124    /**
3125     * @hide
3126     *
3127     * Makes both status bar and navigation bar transparent.
3128     */
3129    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3130            | STATUS_BAR_TRANSPARENT;
3131
3132    /**
3133     * @hide
3134     */
3135    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3136
3137    /**
3138     * These are the system UI flags that can be cleared by events outside
3139     * of an application.  Currently this is just the ability to tap on the
3140     * screen while hiding the navigation bar to have it return.
3141     * @hide
3142     */
3143    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3144            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3145            | SYSTEM_UI_FLAG_FULLSCREEN;
3146
3147    /**
3148     * Flags that can impact the layout in relation to system UI.
3149     */
3150    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3151            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3152            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3153
3154    /** @hide */
3155    @IntDef(flag = true,
3156            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3157    @Retention(RetentionPolicy.SOURCE)
3158    public @interface FindViewFlags {}
3159
3160    /**
3161     * Find views that render the specified text.
3162     *
3163     * @see #findViewsWithText(ArrayList, CharSequence, int)
3164     */
3165    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3166
3167    /**
3168     * Find find views that contain the specified content description.
3169     *
3170     * @see #findViewsWithText(ArrayList, CharSequence, int)
3171     */
3172    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3173
3174    /**
3175     * Find views that contain {@link AccessibilityNodeProvider}. Such
3176     * a View is a root of virtual view hierarchy and may contain the searched
3177     * text. If this flag is set Views with providers are automatically
3178     * added and it is a responsibility of the client to call the APIs of
3179     * the provider to determine whether the virtual tree rooted at this View
3180     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3181     * representing the virtual views with this text.
3182     *
3183     * @see #findViewsWithText(ArrayList, CharSequence, int)
3184     *
3185     * @hide
3186     */
3187    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3188
3189    /**
3190     * The undefined cursor position.
3191     *
3192     * @hide
3193     */
3194    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3195
3196    /**
3197     * Indicates that the screen has changed state and is now off.
3198     *
3199     * @see #onScreenStateChanged(int)
3200     */
3201    public static final int SCREEN_STATE_OFF = 0x0;
3202
3203    /**
3204     * Indicates that the screen has changed state and is now on.
3205     *
3206     * @see #onScreenStateChanged(int)
3207     */
3208    public static final int SCREEN_STATE_ON = 0x1;
3209
3210    /**
3211     * Indicates no axis of view scrolling.
3212     */
3213    public static final int SCROLL_AXIS_NONE = 0;
3214
3215    /**
3216     * Indicates scrolling along the horizontal axis.
3217     */
3218    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3219
3220    /**
3221     * Indicates scrolling along the vertical axis.
3222     */
3223    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3224
3225    /**
3226     * Controls the over-scroll mode for this view.
3227     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3228     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3229     * and {@link #OVER_SCROLL_NEVER}.
3230     */
3231    private int mOverScrollMode;
3232
3233    /**
3234     * The parent this view is attached to.
3235     * {@hide}
3236     *
3237     * @see #getParent()
3238     */
3239    protected ViewParent mParent;
3240
3241    /**
3242     * {@hide}
3243     */
3244    AttachInfo mAttachInfo;
3245
3246    /**
3247     * {@hide}
3248     */
3249    @ViewDebug.ExportedProperty(flagMapping = {
3250        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3251                name = "FORCE_LAYOUT"),
3252        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3253                name = "LAYOUT_REQUIRED"),
3254        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3255            name = "DRAWING_CACHE_INVALID", outputIf = false),
3256        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3257        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3258        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3259        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3260    }, formatToHexString = true)
3261    int mPrivateFlags;
3262    int mPrivateFlags2;
3263    int mPrivateFlags3;
3264
3265    /**
3266     * This view's request for the visibility of the status bar.
3267     * @hide
3268     */
3269    @ViewDebug.ExportedProperty(flagMapping = {
3270        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3271                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3272                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3273        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3274                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3275                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3276        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3277                                equals = SYSTEM_UI_FLAG_VISIBLE,
3278                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3279    }, formatToHexString = true)
3280    int mSystemUiVisibility;
3281
3282    /**
3283     * Reference count for transient state.
3284     * @see #setHasTransientState(boolean)
3285     */
3286    int mTransientStateCount = 0;
3287
3288    /**
3289     * Count of how many windows this view has been attached to.
3290     */
3291    int mWindowAttachCount;
3292
3293    /**
3294     * The layout parameters associated with this view and used by the parent
3295     * {@link android.view.ViewGroup} to determine how this view should be
3296     * laid out.
3297     * {@hide}
3298     */
3299    protected ViewGroup.LayoutParams mLayoutParams;
3300
3301    /**
3302     * The view flags hold various views states.
3303     * {@hide}
3304     */
3305    @ViewDebug.ExportedProperty(formatToHexString = true)
3306    int mViewFlags;
3307
3308    static class TransformationInfo {
3309        /**
3310         * The transform matrix for the View. This transform is calculated internally
3311         * based on the translation, rotation, and scale properties.
3312         *
3313         * Do *not* use this variable directly; instead call getMatrix(), which will
3314         * load the value from the View's RenderNode.
3315         */
3316        private final Matrix mMatrix = new Matrix();
3317
3318        /**
3319         * The inverse transform matrix for the View. This transform is calculated
3320         * internally based on the translation, rotation, and scale properties.
3321         *
3322         * Do *not* use this variable directly; instead call getInverseMatrix(),
3323         * which will load the value from the View's RenderNode.
3324         */
3325        private Matrix mInverseMatrix;
3326
3327        /**
3328         * The opacity of the View. This is a value from 0 to 1, where 0 means
3329         * completely transparent and 1 means completely opaque.
3330         */
3331        @ViewDebug.ExportedProperty
3332        float mAlpha = 1f;
3333
3334        /**
3335         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3336         * property only used by transitions, which is composited with the other alpha
3337         * values to calculate the final visual alpha value.
3338         */
3339        float mTransitionAlpha = 1f;
3340    }
3341
3342    TransformationInfo mTransformationInfo;
3343
3344    /**
3345     * Current clip bounds. to which all drawing of this view are constrained.
3346     */
3347    Rect mClipBounds = null;
3348
3349    private boolean mLastIsOpaque;
3350
3351    /**
3352     * The distance in pixels from the left edge of this view's parent
3353     * to the left edge of this view.
3354     * {@hide}
3355     */
3356    @ViewDebug.ExportedProperty(category = "layout")
3357    protected int mLeft;
3358    /**
3359     * The distance in pixels from the left edge of this view's parent
3360     * to the right edge of this view.
3361     * {@hide}
3362     */
3363    @ViewDebug.ExportedProperty(category = "layout")
3364    protected int mRight;
3365    /**
3366     * The distance in pixels from the top edge of this view's parent
3367     * to the top edge of this view.
3368     * {@hide}
3369     */
3370    @ViewDebug.ExportedProperty(category = "layout")
3371    protected int mTop;
3372    /**
3373     * The distance in pixels from the top edge of this view's parent
3374     * to the bottom edge of this view.
3375     * {@hide}
3376     */
3377    @ViewDebug.ExportedProperty(category = "layout")
3378    protected int mBottom;
3379
3380    /**
3381     * The offset, in pixels, by which the content of this view is scrolled
3382     * horizontally.
3383     * {@hide}
3384     */
3385    @ViewDebug.ExportedProperty(category = "scrolling")
3386    protected int mScrollX;
3387    /**
3388     * The offset, in pixels, by which the content of this view is scrolled
3389     * vertically.
3390     * {@hide}
3391     */
3392    @ViewDebug.ExportedProperty(category = "scrolling")
3393    protected int mScrollY;
3394
3395    /**
3396     * The left padding in pixels, that is the distance in pixels between the
3397     * left edge of this view and the left edge of its content.
3398     * {@hide}
3399     */
3400    @ViewDebug.ExportedProperty(category = "padding")
3401    protected int mPaddingLeft = 0;
3402    /**
3403     * The right padding in pixels, that is the distance in pixels between the
3404     * right edge of this view and the right edge of its content.
3405     * {@hide}
3406     */
3407    @ViewDebug.ExportedProperty(category = "padding")
3408    protected int mPaddingRight = 0;
3409    /**
3410     * The top padding in pixels, that is the distance in pixels between the
3411     * top edge of this view and the top edge of its content.
3412     * {@hide}
3413     */
3414    @ViewDebug.ExportedProperty(category = "padding")
3415    protected int mPaddingTop;
3416    /**
3417     * The bottom padding in pixels, that is the distance in pixels between the
3418     * bottom edge of this view and the bottom edge of its content.
3419     * {@hide}
3420     */
3421    @ViewDebug.ExportedProperty(category = "padding")
3422    protected int mPaddingBottom;
3423
3424    /**
3425     * The layout insets in pixels, that is the distance in pixels between the
3426     * visible edges of this view its bounds.
3427     */
3428    private Insets mLayoutInsets;
3429
3430    /**
3431     * Briefly describes the view and is primarily used for accessibility support.
3432     */
3433    private CharSequence mContentDescription;
3434
3435    /**
3436     * Specifies the id of a view for which this view serves as a label for
3437     * accessibility purposes.
3438     */
3439    private int mLabelForId = View.NO_ID;
3440
3441    /**
3442     * Predicate for matching labeled view id with its label for
3443     * accessibility purposes.
3444     */
3445    private MatchLabelForPredicate mMatchLabelForPredicate;
3446
3447    /**
3448     * Specifies a view before which this one is visited in accessibility traversal.
3449     */
3450    private int mAccessibilityTraversalBeforeId = NO_ID;
3451
3452    /**
3453     * Specifies a view after which this one is visited in accessibility traversal.
3454     */
3455    private int mAccessibilityTraversalAfterId = NO_ID;
3456
3457    /**
3458     * Predicate for matching a view by its id.
3459     */
3460    private MatchIdPredicate mMatchIdPredicate;
3461
3462    /**
3463     * Cache the paddingRight set by the user to append to the scrollbar's size.
3464     *
3465     * @hide
3466     */
3467    @ViewDebug.ExportedProperty(category = "padding")
3468    protected int mUserPaddingRight;
3469
3470    /**
3471     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3472     *
3473     * @hide
3474     */
3475    @ViewDebug.ExportedProperty(category = "padding")
3476    protected int mUserPaddingBottom;
3477
3478    /**
3479     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3480     *
3481     * @hide
3482     */
3483    @ViewDebug.ExportedProperty(category = "padding")
3484    protected int mUserPaddingLeft;
3485
3486    /**
3487     * Cache the paddingStart set by the user to append to the scrollbar's size.
3488     *
3489     */
3490    @ViewDebug.ExportedProperty(category = "padding")
3491    int mUserPaddingStart;
3492
3493    /**
3494     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3495     *
3496     */
3497    @ViewDebug.ExportedProperty(category = "padding")
3498    int mUserPaddingEnd;
3499
3500    /**
3501     * Cache initial left padding.
3502     *
3503     * @hide
3504     */
3505    int mUserPaddingLeftInitial;
3506
3507    /**
3508     * Cache initial right padding.
3509     *
3510     * @hide
3511     */
3512    int mUserPaddingRightInitial;
3513
3514    /**
3515     * Default undefined padding
3516     */
3517    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3518
3519    /**
3520     * Cache if a left padding has been defined
3521     */
3522    private boolean mLeftPaddingDefined = false;
3523
3524    /**
3525     * Cache if a right padding has been defined
3526     */
3527    private boolean mRightPaddingDefined = false;
3528
3529    /**
3530     * @hide
3531     */
3532    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3533    /**
3534     * @hide
3535     */
3536    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3537
3538    private LongSparseLongArray mMeasureCache;
3539
3540    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3541    private Drawable mBackground;
3542    private TintInfo mBackgroundTint;
3543
3544    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3545    private ForegroundInfo mForegroundInfo;
3546
3547    private Drawable mScrollIndicatorDrawable;
3548
3549    /**
3550     * RenderNode used for backgrounds.
3551     * <p>
3552     * When non-null and valid, this is expected to contain an up-to-date copy
3553     * of the background drawable. It is cleared on temporary detach, and reset
3554     * on cleanup.
3555     */
3556    private RenderNode mBackgroundRenderNode;
3557
3558    private int mBackgroundResource;
3559    private boolean mBackgroundSizeChanged;
3560
3561    private String mTransitionName;
3562
3563    static class TintInfo {
3564        ColorStateList mTintList;
3565        PorterDuff.Mode mTintMode;
3566        boolean mHasTintMode;
3567        boolean mHasTintList;
3568    }
3569
3570    private static class ForegroundInfo {
3571        private Drawable mDrawable;
3572        private TintInfo mTintInfo;
3573        private int mGravity = Gravity.FILL;
3574        private boolean mInsidePadding = true;
3575        private boolean mBoundsChanged = true;
3576        private final Rect mSelfBounds = new Rect();
3577        private final Rect mOverlayBounds = new Rect();
3578    }
3579
3580    static class ListenerInfo {
3581        /**
3582         * Listener used to dispatch focus change events.
3583         * This field should be made private, so it is hidden from the SDK.
3584         * {@hide}
3585         */
3586        protected OnFocusChangeListener mOnFocusChangeListener;
3587
3588        /**
3589         * Listeners for layout change events.
3590         */
3591        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3592
3593        protected OnScrollChangeListener mOnScrollChangeListener;
3594
3595        /**
3596         * Listeners for attach events.
3597         */
3598        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3599
3600        /**
3601         * Listener used to dispatch click events.
3602         * This field should be made private, so it is hidden from the SDK.
3603         * {@hide}
3604         */
3605        public OnClickListener mOnClickListener;
3606
3607        /**
3608         * Listener used to dispatch long click events.
3609         * This field should be made private, so it is hidden from the SDK.
3610         * {@hide}
3611         */
3612        protected OnLongClickListener mOnLongClickListener;
3613
3614        /**
3615         * Listener used to dispatch context click events. This field should be made private, so it
3616         * is hidden from the SDK.
3617         * {@hide}
3618         */
3619        protected OnContextClickListener mOnContextClickListener;
3620
3621        /**
3622         * Listener used to build the context menu.
3623         * This field should be made private, so it is hidden from the SDK.
3624         * {@hide}
3625         */
3626        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3627
3628        private OnKeyListener mOnKeyListener;
3629
3630        private OnTouchListener mOnTouchListener;
3631
3632        private OnHoverListener mOnHoverListener;
3633
3634        private OnGenericMotionListener mOnGenericMotionListener;
3635
3636        private OnDragListener mOnDragListener;
3637
3638        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3639
3640        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3641    }
3642
3643    ListenerInfo mListenerInfo;
3644
3645    // Temporary values used to hold (x,y) coordinates when delegating from the
3646    // two-arg performLongClick() method to the legacy no-arg version.
3647    private float mLongClickX = Float.NaN;
3648    private float mLongClickY = Float.NaN;
3649
3650    /**
3651     * The application environment this view lives in.
3652     * This field should be made private, so it is hidden from the SDK.
3653     * {@hide}
3654     */
3655    @ViewDebug.ExportedProperty(deepExport = true)
3656    protected Context mContext;
3657
3658    private final Resources mResources;
3659
3660    private ScrollabilityCache mScrollCache;
3661
3662    private int[] mDrawableState = null;
3663
3664    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3665
3666    /**
3667     * Animator that automatically runs based on state changes.
3668     */
3669    private StateListAnimator mStateListAnimator;
3670
3671    /**
3672     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3673     * the user may specify which view to go to next.
3674     */
3675    private int mNextFocusLeftId = View.NO_ID;
3676
3677    /**
3678     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3679     * the user may specify which view to go to next.
3680     */
3681    private int mNextFocusRightId = View.NO_ID;
3682
3683    /**
3684     * When this view has focus and the next focus is {@link #FOCUS_UP},
3685     * the user may specify which view to go to next.
3686     */
3687    private int mNextFocusUpId = View.NO_ID;
3688
3689    /**
3690     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3691     * the user may specify which view to go to next.
3692     */
3693    private int mNextFocusDownId = View.NO_ID;
3694
3695    /**
3696     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3697     * the user may specify which view to go to next.
3698     */
3699    int mNextFocusForwardId = View.NO_ID;
3700
3701    private CheckForLongPress mPendingCheckForLongPress;
3702    private CheckForTap mPendingCheckForTap = null;
3703    private PerformClick mPerformClick;
3704    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3705
3706    private UnsetPressedState mUnsetPressedState;
3707
3708    /**
3709     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3710     * up event while a long press is invoked as soon as the long press duration is reached, so
3711     * a long press could be performed before the tap is checked, in which case the tap's action
3712     * should not be invoked.
3713     */
3714    private boolean mHasPerformedLongPress;
3715
3716    /**
3717     * Whether a context click button is currently pressed down. This is true when the stylus is
3718     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3719     * pressed. This is false once the button is released or if the stylus has been lifted.
3720     */
3721    private boolean mInContextButtonPress;
3722
3723    /**
3724     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3725     * true after a stylus button press has occured, when the next up event should not be recognized
3726     * as a tap.
3727     */
3728    private boolean mIgnoreNextUpEvent;
3729
3730    /**
3731     * The minimum height of the view. We'll try our best to have the height
3732     * of this view to at least this amount.
3733     */
3734    @ViewDebug.ExportedProperty(category = "measurement")
3735    private int mMinHeight;
3736
3737    /**
3738     * The minimum width of the view. We'll try our best to have the width
3739     * of this view to at least this amount.
3740     */
3741    @ViewDebug.ExportedProperty(category = "measurement")
3742    private int mMinWidth;
3743
3744    /**
3745     * The delegate to handle touch events that are physically in this view
3746     * but should be handled by another view.
3747     */
3748    private TouchDelegate mTouchDelegate = null;
3749
3750    /**
3751     * Solid color to use as a background when creating the drawing cache. Enables
3752     * the cache to use 16 bit bitmaps instead of 32 bit.
3753     */
3754    private int mDrawingCacheBackgroundColor = 0;
3755
3756    /**
3757     * Special tree observer used when mAttachInfo is null.
3758     */
3759    private ViewTreeObserver mFloatingTreeObserver;
3760
3761    /**
3762     * Cache the touch slop from the context that created the view.
3763     */
3764    private int mTouchSlop;
3765
3766    /**
3767     * Object that handles automatic animation of view properties.
3768     */
3769    private ViewPropertyAnimator mAnimator = null;
3770
3771    /**
3772     * List of registered FrameMetricsObservers.
3773     */
3774    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
3775
3776    /**
3777     * Flag indicating that a drag can cross window boundaries.  When
3778     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3779     * with this flag set, all visible applications with targetSdkVersion >=
3780     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
3781     * in the drag operation and receive the dragged content.
3782     *
3783     * <p>If this is the only flag set, then the drag recipient will only have access to text data
3784     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3785     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
3786     */
3787    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3788
3789    /**
3790     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3791     * request read access to the content URI(s) contained in the {@link ClipData} object.
3792     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3793     */
3794    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3795
3796    /**
3797     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3798     * request write access to the content URI(s) contained in the {@link ClipData} object.
3799     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3800     */
3801    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3802
3803    /**
3804     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3805     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3806     * reboots until explicitly revoked with
3807     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3808     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3809     */
3810    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3811            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3812
3813    /**
3814     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3815     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3816     * match against the original granted URI.
3817     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3818     */
3819    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3820            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3821
3822    /**
3823     * Flag indicating that the drag shadow will be opaque.  When
3824     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3825     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3826     */
3827    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3828
3829    /**
3830     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3831     */
3832    private float mVerticalScrollFactor;
3833
3834    /**
3835     * Position of the vertical scroll bar.
3836     */
3837    private int mVerticalScrollbarPosition;
3838
3839    /**
3840     * Position the scroll bar at the default position as determined by the system.
3841     */
3842    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3843
3844    /**
3845     * Position the scroll bar along the left edge.
3846     */
3847    public static final int SCROLLBAR_POSITION_LEFT = 1;
3848
3849    /**
3850     * Position the scroll bar along the right edge.
3851     */
3852    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3853
3854    /**
3855     * Indicates that the view does not have a layer.
3856     *
3857     * @see #getLayerType()
3858     * @see #setLayerType(int, android.graphics.Paint)
3859     * @see #LAYER_TYPE_SOFTWARE
3860     * @see #LAYER_TYPE_HARDWARE
3861     */
3862    public static final int LAYER_TYPE_NONE = 0;
3863
3864    /**
3865     * <p>Indicates that the view has a software layer. A software layer is backed
3866     * by a bitmap and causes the view to be rendered using Android's software
3867     * rendering pipeline, even if hardware acceleration is enabled.</p>
3868     *
3869     * <p>Software layers have various usages:</p>
3870     * <p>When the application is not using hardware acceleration, a software layer
3871     * is useful to apply a specific color filter and/or blending mode and/or
3872     * translucency to a view and all its children.</p>
3873     * <p>When the application is using hardware acceleration, a software layer
3874     * is useful to render drawing primitives not supported by the hardware
3875     * accelerated pipeline. It can also be used to cache a complex view tree
3876     * into a texture and reduce the complexity of drawing operations. For instance,
3877     * when animating a complex view tree with a translation, a software layer can
3878     * be used to render the view tree only once.</p>
3879     * <p>Software layers should be avoided when the affected view tree updates
3880     * often. Every update will require to re-render the software layer, which can
3881     * potentially be slow (particularly when hardware acceleration is turned on
3882     * since the layer will have to be uploaded into a hardware texture after every
3883     * update.)</p>
3884     *
3885     * @see #getLayerType()
3886     * @see #setLayerType(int, android.graphics.Paint)
3887     * @see #LAYER_TYPE_NONE
3888     * @see #LAYER_TYPE_HARDWARE
3889     */
3890    public static final int LAYER_TYPE_SOFTWARE = 1;
3891
3892    /**
3893     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3894     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3895     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3896     * rendering pipeline, but only if hardware acceleration is turned on for the
3897     * view hierarchy. When hardware acceleration is turned off, hardware layers
3898     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3899     *
3900     * <p>A hardware layer is useful to apply a specific color filter and/or
3901     * blending mode and/or translucency to a view and all its children.</p>
3902     * <p>A hardware layer can be used to cache a complex view tree into a
3903     * texture and reduce the complexity of drawing operations. For instance,
3904     * when animating a complex view tree with a translation, a hardware layer can
3905     * be used to render the view tree only once.</p>
3906     * <p>A hardware layer can also be used to increase the rendering quality when
3907     * rotation transformations are applied on a view. It can also be used to
3908     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3909     *
3910     * @see #getLayerType()
3911     * @see #setLayerType(int, android.graphics.Paint)
3912     * @see #LAYER_TYPE_NONE
3913     * @see #LAYER_TYPE_SOFTWARE
3914     */
3915    public static final int LAYER_TYPE_HARDWARE = 2;
3916
3917    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3918            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3919            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3920            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3921    })
3922    int mLayerType = LAYER_TYPE_NONE;
3923    Paint mLayerPaint;
3924
3925    /**
3926     * Set to true when drawing cache is enabled and cannot be created.
3927     *
3928     * @hide
3929     */
3930    public boolean mCachingFailed;
3931    private Bitmap mDrawingCache;
3932    private Bitmap mUnscaledDrawingCache;
3933
3934    /**
3935     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3936     * <p>
3937     * When non-null and valid, this is expected to contain an up-to-date copy
3938     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3939     * cleanup.
3940     */
3941    final RenderNode mRenderNode;
3942
3943    /**
3944     * Set to true when the view is sending hover accessibility events because it
3945     * is the innermost hovered view.
3946     */
3947    private boolean mSendingHoverAccessibilityEvents;
3948
3949    /**
3950     * Delegate for injecting accessibility functionality.
3951     */
3952    AccessibilityDelegate mAccessibilityDelegate;
3953
3954    /**
3955     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3956     * and add/remove objects to/from the overlay directly through the Overlay methods.
3957     */
3958    ViewOverlay mOverlay;
3959
3960    /**
3961     * The currently active parent view for receiving delegated nested scrolling events.
3962     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3963     * by {@link #stopNestedScroll()} at the same point where we clear
3964     * requestDisallowInterceptTouchEvent.
3965     */
3966    private ViewParent mNestedScrollingParent;
3967
3968    /**
3969     * Consistency verifier for debugging purposes.
3970     * @hide
3971     */
3972    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3973            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3974                    new InputEventConsistencyVerifier(this, 0) : null;
3975
3976    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3977
3978    private int[] mTempNestedScrollConsumed;
3979
3980    /**
3981     * An overlay is going to draw this View instead of being drawn as part of this
3982     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3983     * when this view is invalidated.
3984     */
3985    GhostView mGhostView;
3986
3987    /**
3988     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3989     * @hide
3990     */
3991    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3992    public String[] mAttributes;
3993
3994    /**
3995     * Maps a Resource id to its name.
3996     */
3997    private static SparseArray<String> mAttributeMap;
3998
3999    /**
4000     * Queue of pending runnables. Used to postpone calls to post() until this
4001     * view is attached and has a handler.
4002     */
4003    private HandlerActionQueue mRunQueue;
4004
4005    /**
4006     * The pointer icon when the mouse hovers on this view. The default is null.
4007     */
4008    private PointerIcon mPointerIcon;
4009
4010    /**
4011     * @hide
4012     */
4013    String mStartActivityRequestWho;
4014
4015    @Nullable
4016    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4017
4018    /**
4019     * Simple constructor to use when creating a view from code.
4020     *
4021     * @param context The Context the view is running in, through which it can
4022     *        access the current theme, resources, etc.
4023     */
4024    public View(Context context) {
4025        mContext = context;
4026        mResources = context != null ? context.getResources() : null;
4027        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
4028        // Set some flags defaults
4029        mPrivateFlags2 =
4030                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4031                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4032                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4033                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4034                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4035                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4036        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4037        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4038        mUserPaddingStart = UNDEFINED_PADDING;
4039        mUserPaddingEnd = UNDEFINED_PADDING;
4040        mRenderNode = RenderNode.create(getClass().getName(), this);
4041
4042        if (!sCompatibilityDone && context != null) {
4043            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4044
4045            // Older apps may need this compatibility hack for measurement.
4046            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
4047
4048            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4049            // of whether a layout was requested on that View.
4050            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
4051
4052            Canvas.sCompatibilityRestore = targetSdkVersion < M;
4053
4054            // In M and newer, our widgets can pass a "hint" value in the size
4055            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4056            // know what the expected parent size is going to be, so e.g. list items can size
4057            // themselves at 1/3 the size of their container. It breaks older apps though,
4058            // specifically apps that use some popular open source libraries.
4059            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
4060
4061            // Old versions of the platform would give different results from
4062            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4063            // modes, so we always need to run an additional EXACTLY pass.
4064            sAlwaysRemeasureExactly = targetSdkVersion <= M;
4065
4066            // Prior to N, layout params could change without requiring a
4067            // subsequent call to setLayoutParams() and they would usually
4068            // work. Partial layout breaks this assumption.
4069            sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
4070
4071            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4072            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4073            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
4074
4075            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4076            // in apps so we target check it to avoid breaking existing apps.
4077            sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N;
4078
4079            sCascadedDragDrop = targetSdkVersion < N;
4080
4081            sCompatibilityDone = true;
4082        }
4083    }
4084
4085    /**
4086     * Constructor that is called when inflating a view from XML. This is called
4087     * when a view is being constructed from an XML file, supplying attributes
4088     * that were specified in the XML file. This version uses a default style of
4089     * 0, so the only attribute values applied are those in the Context's Theme
4090     * and the given AttributeSet.
4091     *
4092     * <p>
4093     * The method onFinishInflate() will be called after all children have been
4094     * added.
4095     *
4096     * @param context The Context the view is running in, through which it can
4097     *        access the current theme, resources, etc.
4098     * @param attrs The attributes of the XML tag that is inflating the view.
4099     * @see #View(Context, AttributeSet, int)
4100     */
4101    public View(Context context, @Nullable AttributeSet attrs) {
4102        this(context, attrs, 0);
4103    }
4104
4105    /**
4106     * Perform inflation from XML and apply a class-specific base style from a
4107     * theme attribute. This constructor of View allows subclasses to use their
4108     * own base style when they are inflating. For example, a Button class's
4109     * constructor would call this version of the super class constructor and
4110     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4111     * allows the theme's button style to modify all of the base view attributes
4112     * (in particular its background) as well as the Button class's attributes.
4113     *
4114     * @param context The Context the view is running in, through which it can
4115     *        access the current theme, resources, etc.
4116     * @param attrs The attributes of the XML tag that is inflating the view.
4117     * @param defStyleAttr An attribute in the current theme that contains a
4118     *        reference to a style resource that supplies default values for
4119     *        the view. Can be 0 to not look for defaults.
4120     * @see #View(Context, AttributeSet)
4121     */
4122    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4123        this(context, attrs, defStyleAttr, 0);
4124    }
4125
4126    /**
4127     * Perform inflation from XML and apply a class-specific base style from a
4128     * theme attribute or style resource. This constructor of View allows
4129     * subclasses to use their own base style when they are inflating.
4130     * <p>
4131     * When determining the final value of a particular attribute, there are
4132     * four inputs that come into play:
4133     * <ol>
4134     * <li>Any attribute values in the given AttributeSet.
4135     * <li>The style resource specified in the AttributeSet (named "style").
4136     * <li>The default style specified by <var>defStyleAttr</var>.
4137     * <li>The default style specified by <var>defStyleRes</var>.
4138     * <li>The base values in this theme.
4139     * </ol>
4140     * <p>
4141     * Each of these inputs is considered in-order, with the first listed taking
4142     * precedence over the following ones. In other words, if in the
4143     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4144     * , then the button's text will <em>always</em> be black, regardless of
4145     * what is specified in any of the styles.
4146     *
4147     * @param context The Context the view is running in, through which it can
4148     *        access the current theme, resources, etc.
4149     * @param attrs The attributes of the XML tag that is inflating the view.
4150     * @param defStyleAttr An attribute in the current theme that contains a
4151     *        reference to a style resource that supplies default values for
4152     *        the view. Can be 0 to not look for defaults.
4153     * @param defStyleRes A resource identifier of a style resource that
4154     *        supplies default values for the view, used only if
4155     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4156     *        to not look for defaults.
4157     * @see #View(Context, AttributeSet, int)
4158     */
4159    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4160        this(context);
4161
4162        final TypedArray a = context.obtainStyledAttributes(
4163                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4164
4165        if (mDebugViewAttributes) {
4166            saveAttributeData(attrs, a);
4167        }
4168
4169        Drawable background = null;
4170
4171        int leftPadding = -1;
4172        int topPadding = -1;
4173        int rightPadding = -1;
4174        int bottomPadding = -1;
4175        int startPadding = UNDEFINED_PADDING;
4176        int endPadding = UNDEFINED_PADDING;
4177
4178        int padding = -1;
4179
4180        int viewFlagValues = 0;
4181        int viewFlagMasks = 0;
4182
4183        boolean setScrollContainer = false;
4184
4185        int x = 0;
4186        int y = 0;
4187
4188        float tx = 0;
4189        float ty = 0;
4190        float tz = 0;
4191        float elevation = 0;
4192        float rotation = 0;
4193        float rotationX = 0;
4194        float rotationY = 0;
4195        float sx = 1f;
4196        float sy = 1f;
4197        boolean transformSet = false;
4198
4199        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4200        int overScrollMode = mOverScrollMode;
4201        boolean initializeScrollbars = false;
4202        boolean initializeScrollIndicators = false;
4203
4204        boolean startPaddingDefined = false;
4205        boolean endPaddingDefined = false;
4206        boolean leftPaddingDefined = false;
4207        boolean rightPaddingDefined = false;
4208
4209        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4210
4211        final int N = a.getIndexCount();
4212        for (int i = 0; i < N; i++) {
4213            int attr = a.getIndex(i);
4214            switch (attr) {
4215                case com.android.internal.R.styleable.View_background:
4216                    background = a.getDrawable(attr);
4217                    break;
4218                case com.android.internal.R.styleable.View_padding:
4219                    padding = a.getDimensionPixelSize(attr, -1);
4220                    mUserPaddingLeftInitial = padding;
4221                    mUserPaddingRightInitial = padding;
4222                    leftPaddingDefined = true;
4223                    rightPaddingDefined = true;
4224                    break;
4225                 case com.android.internal.R.styleable.View_paddingLeft:
4226                    leftPadding = a.getDimensionPixelSize(attr, -1);
4227                    mUserPaddingLeftInitial = leftPadding;
4228                    leftPaddingDefined = true;
4229                    break;
4230                case com.android.internal.R.styleable.View_paddingTop:
4231                    topPadding = a.getDimensionPixelSize(attr, -1);
4232                    break;
4233                case com.android.internal.R.styleable.View_paddingRight:
4234                    rightPadding = a.getDimensionPixelSize(attr, -1);
4235                    mUserPaddingRightInitial = rightPadding;
4236                    rightPaddingDefined = true;
4237                    break;
4238                case com.android.internal.R.styleable.View_paddingBottom:
4239                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4240                    break;
4241                case com.android.internal.R.styleable.View_paddingStart:
4242                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4243                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4244                    break;
4245                case com.android.internal.R.styleable.View_paddingEnd:
4246                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4247                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4248                    break;
4249                case com.android.internal.R.styleable.View_scrollX:
4250                    x = a.getDimensionPixelOffset(attr, 0);
4251                    break;
4252                case com.android.internal.R.styleable.View_scrollY:
4253                    y = a.getDimensionPixelOffset(attr, 0);
4254                    break;
4255                case com.android.internal.R.styleable.View_alpha:
4256                    setAlpha(a.getFloat(attr, 1f));
4257                    break;
4258                case com.android.internal.R.styleable.View_transformPivotX:
4259                    setPivotX(a.getDimension(attr, 0));
4260                    break;
4261                case com.android.internal.R.styleable.View_transformPivotY:
4262                    setPivotY(a.getDimension(attr, 0));
4263                    break;
4264                case com.android.internal.R.styleable.View_translationX:
4265                    tx = a.getDimension(attr, 0);
4266                    transformSet = true;
4267                    break;
4268                case com.android.internal.R.styleable.View_translationY:
4269                    ty = a.getDimension(attr, 0);
4270                    transformSet = true;
4271                    break;
4272                case com.android.internal.R.styleable.View_translationZ:
4273                    tz = a.getDimension(attr, 0);
4274                    transformSet = true;
4275                    break;
4276                case com.android.internal.R.styleable.View_elevation:
4277                    elevation = a.getDimension(attr, 0);
4278                    transformSet = true;
4279                    break;
4280                case com.android.internal.R.styleable.View_rotation:
4281                    rotation = a.getFloat(attr, 0);
4282                    transformSet = true;
4283                    break;
4284                case com.android.internal.R.styleable.View_rotationX:
4285                    rotationX = a.getFloat(attr, 0);
4286                    transformSet = true;
4287                    break;
4288                case com.android.internal.R.styleable.View_rotationY:
4289                    rotationY = a.getFloat(attr, 0);
4290                    transformSet = true;
4291                    break;
4292                case com.android.internal.R.styleable.View_scaleX:
4293                    sx = a.getFloat(attr, 1f);
4294                    transformSet = true;
4295                    break;
4296                case com.android.internal.R.styleable.View_scaleY:
4297                    sy = a.getFloat(attr, 1f);
4298                    transformSet = true;
4299                    break;
4300                case com.android.internal.R.styleable.View_id:
4301                    mID = a.getResourceId(attr, NO_ID);
4302                    break;
4303                case com.android.internal.R.styleable.View_tag:
4304                    mTag = a.getText(attr);
4305                    break;
4306                case com.android.internal.R.styleable.View_fitsSystemWindows:
4307                    if (a.getBoolean(attr, false)) {
4308                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4309                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4310                    }
4311                    break;
4312                case com.android.internal.R.styleable.View_focusable:
4313                    if (a.getBoolean(attr, false)) {
4314                        viewFlagValues |= FOCUSABLE;
4315                        viewFlagMasks |= FOCUSABLE_MASK;
4316                    }
4317                    break;
4318                case com.android.internal.R.styleable.View_focusableInTouchMode:
4319                    if (a.getBoolean(attr, false)) {
4320                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4321                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4322                    }
4323                    break;
4324                case com.android.internal.R.styleable.View_clickable:
4325                    if (a.getBoolean(attr, false)) {
4326                        viewFlagValues |= CLICKABLE;
4327                        viewFlagMasks |= CLICKABLE;
4328                    }
4329                    break;
4330                case com.android.internal.R.styleable.View_longClickable:
4331                    if (a.getBoolean(attr, false)) {
4332                        viewFlagValues |= LONG_CLICKABLE;
4333                        viewFlagMasks |= LONG_CLICKABLE;
4334                    }
4335                    break;
4336                case com.android.internal.R.styleable.View_contextClickable:
4337                    if (a.getBoolean(attr, false)) {
4338                        viewFlagValues |= CONTEXT_CLICKABLE;
4339                        viewFlagMasks |= CONTEXT_CLICKABLE;
4340                    }
4341                    break;
4342                case com.android.internal.R.styleable.View_saveEnabled:
4343                    if (!a.getBoolean(attr, true)) {
4344                        viewFlagValues |= SAVE_DISABLED;
4345                        viewFlagMasks |= SAVE_DISABLED_MASK;
4346                    }
4347                    break;
4348                case com.android.internal.R.styleable.View_duplicateParentState:
4349                    if (a.getBoolean(attr, false)) {
4350                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4351                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4352                    }
4353                    break;
4354                case com.android.internal.R.styleable.View_visibility:
4355                    final int visibility = a.getInt(attr, 0);
4356                    if (visibility != 0) {
4357                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4358                        viewFlagMasks |= VISIBILITY_MASK;
4359                    }
4360                    break;
4361                case com.android.internal.R.styleable.View_layoutDirection:
4362                    // Clear any layout direction flags (included resolved bits) already set
4363                    mPrivateFlags2 &=
4364                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4365                    // Set the layout direction flags depending on the value of the attribute
4366                    final int layoutDirection = a.getInt(attr, -1);
4367                    final int value = (layoutDirection != -1) ?
4368                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4369                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4370                    break;
4371                case com.android.internal.R.styleable.View_drawingCacheQuality:
4372                    final int cacheQuality = a.getInt(attr, 0);
4373                    if (cacheQuality != 0) {
4374                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4375                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4376                    }
4377                    break;
4378                case com.android.internal.R.styleable.View_contentDescription:
4379                    setContentDescription(a.getString(attr));
4380                    break;
4381                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4382                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4383                    break;
4384                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4385                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4386                    break;
4387                case com.android.internal.R.styleable.View_labelFor:
4388                    setLabelFor(a.getResourceId(attr, NO_ID));
4389                    break;
4390                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4391                    if (!a.getBoolean(attr, true)) {
4392                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4393                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4394                    }
4395                    break;
4396                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4397                    if (!a.getBoolean(attr, true)) {
4398                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4399                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4400                    }
4401                    break;
4402                case R.styleable.View_scrollbars:
4403                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4404                    if (scrollbars != SCROLLBARS_NONE) {
4405                        viewFlagValues |= scrollbars;
4406                        viewFlagMasks |= SCROLLBARS_MASK;
4407                        initializeScrollbars = true;
4408                    }
4409                    break;
4410                //noinspection deprecation
4411                case R.styleable.View_fadingEdge:
4412                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4413                        // Ignore the attribute starting with ICS
4414                        break;
4415                    }
4416                    // With builds < ICS, fall through and apply fading edges
4417                case R.styleable.View_requiresFadingEdge:
4418                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4419                    if (fadingEdge != FADING_EDGE_NONE) {
4420                        viewFlagValues |= fadingEdge;
4421                        viewFlagMasks |= FADING_EDGE_MASK;
4422                        initializeFadingEdgeInternal(a);
4423                    }
4424                    break;
4425                case R.styleable.View_scrollbarStyle:
4426                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4427                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4428                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4429                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4430                    }
4431                    break;
4432                case R.styleable.View_isScrollContainer:
4433                    setScrollContainer = true;
4434                    if (a.getBoolean(attr, false)) {
4435                        setScrollContainer(true);
4436                    }
4437                    break;
4438                case com.android.internal.R.styleable.View_keepScreenOn:
4439                    if (a.getBoolean(attr, false)) {
4440                        viewFlagValues |= KEEP_SCREEN_ON;
4441                        viewFlagMasks |= KEEP_SCREEN_ON;
4442                    }
4443                    break;
4444                case R.styleable.View_filterTouchesWhenObscured:
4445                    if (a.getBoolean(attr, false)) {
4446                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4447                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4448                    }
4449                    break;
4450                case R.styleable.View_nextFocusLeft:
4451                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4452                    break;
4453                case R.styleable.View_nextFocusRight:
4454                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4455                    break;
4456                case R.styleable.View_nextFocusUp:
4457                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4458                    break;
4459                case R.styleable.View_nextFocusDown:
4460                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4461                    break;
4462                case R.styleable.View_nextFocusForward:
4463                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4464                    break;
4465                case R.styleable.View_minWidth:
4466                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4467                    break;
4468                case R.styleable.View_minHeight:
4469                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4470                    break;
4471                case R.styleable.View_onClick:
4472                    if (context.isRestricted()) {
4473                        throw new IllegalStateException("The android:onClick attribute cannot "
4474                                + "be used within a restricted context");
4475                    }
4476
4477                    final String handlerName = a.getString(attr);
4478                    if (handlerName != null) {
4479                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4480                    }
4481                    break;
4482                case R.styleable.View_overScrollMode:
4483                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4484                    break;
4485                case R.styleable.View_verticalScrollbarPosition:
4486                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4487                    break;
4488                case R.styleable.View_layerType:
4489                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4490                    break;
4491                case R.styleable.View_textDirection:
4492                    // Clear any text direction flag already set
4493                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4494                    // Set the text direction flags depending on the value of the attribute
4495                    final int textDirection = a.getInt(attr, -1);
4496                    if (textDirection != -1) {
4497                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4498                    }
4499                    break;
4500                case R.styleable.View_textAlignment:
4501                    // Clear any text alignment flag already set
4502                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4503                    // Set the text alignment flag depending on the value of the attribute
4504                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4505                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4506                    break;
4507                case R.styleable.View_importantForAccessibility:
4508                    setImportantForAccessibility(a.getInt(attr,
4509                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4510                    break;
4511                case R.styleable.View_accessibilityLiveRegion:
4512                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4513                    break;
4514                case R.styleable.View_transitionName:
4515                    setTransitionName(a.getString(attr));
4516                    break;
4517                case R.styleable.View_nestedScrollingEnabled:
4518                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4519                    break;
4520                case R.styleable.View_stateListAnimator:
4521                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4522                            a.getResourceId(attr, 0)));
4523                    break;
4524                case R.styleable.View_backgroundTint:
4525                    // This will get applied later during setBackground().
4526                    if (mBackgroundTint == null) {
4527                        mBackgroundTint = new TintInfo();
4528                    }
4529                    mBackgroundTint.mTintList = a.getColorStateList(
4530                            R.styleable.View_backgroundTint);
4531                    mBackgroundTint.mHasTintList = true;
4532                    break;
4533                case R.styleable.View_backgroundTintMode:
4534                    // This will get applied later during setBackground().
4535                    if (mBackgroundTint == null) {
4536                        mBackgroundTint = new TintInfo();
4537                    }
4538                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4539                            R.styleable.View_backgroundTintMode, -1), null);
4540                    mBackgroundTint.mHasTintMode = true;
4541                    break;
4542                case R.styleable.View_outlineProvider:
4543                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4544                            PROVIDER_BACKGROUND));
4545                    break;
4546                case R.styleable.View_foreground:
4547                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4548                        setForeground(a.getDrawable(attr));
4549                    }
4550                    break;
4551                case R.styleable.View_foregroundGravity:
4552                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4553                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4554                    }
4555                    break;
4556                case R.styleable.View_foregroundTintMode:
4557                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4558                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4559                    }
4560                    break;
4561                case R.styleable.View_foregroundTint:
4562                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4563                        setForegroundTintList(a.getColorStateList(attr));
4564                    }
4565                    break;
4566                case R.styleable.View_foregroundInsidePadding:
4567                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4568                        if (mForegroundInfo == null) {
4569                            mForegroundInfo = new ForegroundInfo();
4570                        }
4571                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4572                                mForegroundInfo.mInsidePadding);
4573                    }
4574                    break;
4575                case R.styleable.View_scrollIndicators:
4576                    final int scrollIndicators =
4577                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4578                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4579                    if (scrollIndicators != 0) {
4580                        mPrivateFlags3 |= scrollIndicators;
4581                        initializeScrollIndicators = true;
4582                    }
4583                    break;
4584                case R.styleable.View_pointerIcon:
4585                    final int resourceId = a.getResourceId(attr, 0);
4586                    if (resourceId != 0) {
4587                        setPointerIcon(PointerIcon.load(
4588                                context.getResources(), resourceId));
4589                    } else {
4590                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4591                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4592                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
4593                        }
4594                    }
4595                    break;
4596                case R.styleable.View_forceHasOverlappingRendering:
4597                    if (a.peekValue(attr) != null) {
4598                        forceHasOverlappingRendering(a.getBoolean(attr, true));
4599                    }
4600                    break;
4601
4602            }
4603        }
4604
4605        setOverScrollMode(overScrollMode);
4606
4607        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4608        // the resolved layout direction). Those cached values will be used later during padding
4609        // resolution.
4610        mUserPaddingStart = startPadding;
4611        mUserPaddingEnd = endPadding;
4612
4613        if (background != null) {
4614            setBackground(background);
4615        }
4616
4617        // setBackground above will record that padding is currently provided by the background.
4618        // If we have padding specified via xml, record that here instead and use it.
4619        mLeftPaddingDefined = leftPaddingDefined;
4620        mRightPaddingDefined = rightPaddingDefined;
4621
4622        if (padding >= 0) {
4623            leftPadding = padding;
4624            topPadding = padding;
4625            rightPadding = padding;
4626            bottomPadding = padding;
4627            mUserPaddingLeftInitial = padding;
4628            mUserPaddingRightInitial = padding;
4629        }
4630
4631        if (isRtlCompatibilityMode()) {
4632            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4633            // left / right padding are used if defined (meaning here nothing to do). If they are not
4634            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4635            // start / end and resolve them as left / right (layout direction is not taken into account).
4636            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4637            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4638            // defined.
4639            if (!mLeftPaddingDefined && startPaddingDefined) {
4640                leftPadding = startPadding;
4641            }
4642            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4643            if (!mRightPaddingDefined && endPaddingDefined) {
4644                rightPadding = endPadding;
4645            }
4646            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4647        } else {
4648            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4649            // values defined. Otherwise, left /right values are used.
4650            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4651            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4652            // defined.
4653            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4654
4655            if (mLeftPaddingDefined && !hasRelativePadding) {
4656                mUserPaddingLeftInitial = leftPadding;
4657            }
4658            if (mRightPaddingDefined && !hasRelativePadding) {
4659                mUserPaddingRightInitial = rightPadding;
4660            }
4661        }
4662
4663        internalSetPadding(
4664                mUserPaddingLeftInitial,
4665                topPadding >= 0 ? topPadding : mPaddingTop,
4666                mUserPaddingRightInitial,
4667                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4668
4669        if (viewFlagMasks != 0) {
4670            setFlags(viewFlagValues, viewFlagMasks);
4671        }
4672
4673        if (initializeScrollbars) {
4674            initializeScrollbarsInternal(a);
4675        }
4676
4677        if (initializeScrollIndicators) {
4678            initializeScrollIndicatorsInternal();
4679        }
4680
4681        a.recycle();
4682
4683        // Needs to be called after mViewFlags is set
4684        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4685            recomputePadding();
4686        }
4687
4688        if (x != 0 || y != 0) {
4689            scrollTo(x, y);
4690        }
4691
4692        if (transformSet) {
4693            setTranslationX(tx);
4694            setTranslationY(ty);
4695            setTranslationZ(tz);
4696            setElevation(elevation);
4697            setRotation(rotation);
4698            setRotationX(rotationX);
4699            setRotationY(rotationY);
4700            setScaleX(sx);
4701            setScaleY(sy);
4702        }
4703
4704        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4705            setScrollContainer(true);
4706        }
4707
4708        computeOpaqueFlags();
4709    }
4710
4711    /**
4712     * An implementation of OnClickListener that attempts to lazily load a
4713     * named click handling method from a parent or ancestor context.
4714     */
4715    private static class DeclaredOnClickListener implements OnClickListener {
4716        private final View mHostView;
4717        private final String mMethodName;
4718
4719        private Method mResolvedMethod;
4720        private Context mResolvedContext;
4721
4722        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4723            mHostView = hostView;
4724            mMethodName = methodName;
4725        }
4726
4727        @Override
4728        public void onClick(@NonNull View v) {
4729            if (mResolvedMethod == null) {
4730                resolveMethod(mHostView.getContext(), mMethodName);
4731            }
4732
4733            try {
4734                mResolvedMethod.invoke(mResolvedContext, v);
4735            } catch (IllegalAccessException e) {
4736                throw new IllegalStateException(
4737                        "Could not execute non-public method for android:onClick", e);
4738            } catch (InvocationTargetException e) {
4739                throw new IllegalStateException(
4740                        "Could not execute method for android:onClick", e);
4741            }
4742        }
4743
4744        @NonNull
4745        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4746            while (context != null) {
4747                try {
4748                    if (!context.isRestricted()) {
4749                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4750                        if (method != null) {
4751                            mResolvedMethod = method;
4752                            mResolvedContext = context;
4753                            return;
4754                        }
4755                    }
4756                } catch (NoSuchMethodException e) {
4757                    // Failed to find method, keep searching up the hierarchy.
4758                }
4759
4760                if (context instanceof ContextWrapper) {
4761                    context = ((ContextWrapper) context).getBaseContext();
4762                } else {
4763                    // Can't search up the hierarchy, null out and fail.
4764                    context = null;
4765                }
4766            }
4767
4768            final int id = mHostView.getId();
4769            final String idText = id == NO_ID ? "" : " with id '"
4770                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4771            throw new IllegalStateException("Could not find method " + mMethodName
4772                    + "(View) in a parent or ancestor Context for android:onClick "
4773                    + "attribute defined on view " + mHostView.getClass() + idText);
4774        }
4775    }
4776
4777    /**
4778     * Non-public constructor for use in testing
4779     */
4780    View() {
4781        mResources = null;
4782        mRenderNode = RenderNode.create(getClass().getName(), this);
4783    }
4784
4785    private static SparseArray<String> getAttributeMap() {
4786        if (mAttributeMap == null) {
4787            mAttributeMap = new SparseArray<>();
4788        }
4789        return mAttributeMap;
4790    }
4791
4792    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4793        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4794        final int indexCount = t.getIndexCount();
4795        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4796
4797        int i = 0;
4798
4799        // Store raw XML attributes.
4800        for (int j = 0; j < attrsCount; ++j) {
4801            attributes[i] = attrs.getAttributeName(j);
4802            attributes[i + 1] = attrs.getAttributeValue(j);
4803            i += 2;
4804        }
4805
4806        // Store resolved styleable attributes.
4807        final Resources res = t.getResources();
4808        final SparseArray<String> attributeMap = getAttributeMap();
4809        for (int j = 0; j < indexCount; ++j) {
4810            final int index = t.getIndex(j);
4811            if (!t.hasValueOrEmpty(index)) {
4812                // Value is undefined. Skip it.
4813                continue;
4814            }
4815
4816            final int resourceId = t.getResourceId(index, 0);
4817            if (resourceId == 0) {
4818                // Value is not a reference. Skip it.
4819                continue;
4820            }
4821
4822            String resourceName = attributeMap.get(resourceId);
4823            if (resourceName == null) {
4824                try {
4825                    resourceName = res.getResourceName(resourceId);
4826                } catch (Resources.NotFoundException e) {
4827                    resourceName = "0x" + Integer.toHexString(resourceId);
4828                }
4829                attributeMap.put(resourceId, resourceName);
4830            }
4831
4832            attributes[i] = resourceName;
4833            attributes[i + 1] = t.getString(index);
4834            i += 2;
4835        }
4836
4837        // Trim to fit contents.
4838        final String[] trimmed = new String[i];
4839        System.arraycopy(attributes, 0, trimmed, 0, i);
4840        mAttributes = trimmed;
4841    }
4842
4843    public String toString() {
4844        StringBuilder out = new StringBuilder(128);
4845        out.append(getClass().getName());
4846        out.append('{');
4847        out.append(Integer.toHexString(System.identityHashCode(this)));
4848        out.append(' ');
4849        switch (mViewFlags&VISIBILITY_MASK) {
4850            case VISIBLE: out.append('V'); break;
4851            case INVISIBLE: out.append('I'); break;
4852            case GONE: out.append('G'); break;
4853            default: out.append('.'); break;
4854        }
4855        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4856        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4857        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4858        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4859        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4860        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4861        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4862        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4863        out.append(' ');
4864        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4865        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4866        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4867        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4868            out.append('p');
4869        } else {
4870            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4871        }
4872        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4873        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4874        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4875        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4876        out.append(' ');
4877        out.append(mLeft);
4878        out.append(',');
4879        out.append(mTop);
4880        out.append('-');
4881        out.append(mRight);
4882        out.append(',');
4883        out.append(mBottom);
4884        final int id = getId();
4885        if (id != NO_ID) {
4886            out.append(" #");
4887            out.append(Integer.toHexString(id));
4888            final Resources r = mResources;
4889            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4890                try {
4891                    String pkgname;
4892                    switch (id&0xff000000) {
4893                        case 0x7f000000:
4894                            pkgname="app";
4895                            break;
4896                        case 0x01000000:
4897                            pkgname="android";
4898                            break;
4899                        default:
4900                            pkgname = r.getResourcePackageName(id);
4901                            break;
4902                    }
4903                    String typename = r.getResourceTypeName(id);
4904                    String entryname = r.getResourceEntryName(id);
4905                    out.append(" ");
4906                    out.append(pkgname);
4907                    out.append(":");
4908                    out.append(typename);
4909                    out.append("/");
4910                    out.append(entryname);
4911                } catch (Resources.NotFoundException e) {
4912                }
4913            }
4914        }
4915        out.append("}");
4916        return out.toString();
4917    }
4918
4919    /**
4920     * <p>
4921     * Initializes the fading edges from a given set of styled attributes. This
4922     * method should be called by subclasses that need fading edges and when an
4923     * instance of these subclasses is created programmatically rather than
4924     * being inflated from XML. This method is automatically called when the XML
4925     * is inflated.
4926     * </p>
4927     *
4928     * @param a the styled attributes set to initialize the fading edges from
4929     *
4930     * @removed
4931     */
4932    protected void initializeFadingEdge(TypedArray a) {
4933        // This method probably shouldn't have been included in the SDK to begin with.
4934        // It relies on 'a' having been initialized using an attribute filter array that is
4935        // not publicly available to the SDK. The old method has been renamed
4936        // to initializeFadingEdgeInternal and hidden for framework use only;
4937        // this one initializes using defaults to make it safe to call for apps.
4938
4939        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4940
4941        initializeFadingEdgeInternal(arr);
4942
4943        arr.recycle();
4944    }
4945
4946    /**
4947     * <p>
4948     * Initializes the fading edges from a given set of styled attributes. This
4949     * method should be called by subclasses that need fading edges and when an
4950     * instance of these subclasses is created programmatically rather than
4951     * being inflated from XML. This method is automatically called when the XML
4952     * is inflated.
4953     * </p>
4954     *
4955     * @param a the styled attributes set to initialize the fading edges from
4956     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4957     */
4958    protected void initializeFadingEdgeInternal(TypedArray a) {
4959        initScrollCache();
4960
4961        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4962                R.styleable.View_fadingEdgeLength,
4963                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4964    }
4965
4966    /**
4967     * Returns the size of the vertical faded edges used to indicate that more
4968     * content in this view is visible.
4969     *
4970     * @return The size in pixels of the vertical faded edge or 0 if vertical
4971     *         faded edges are not enabled for this view.
4972     * @attr ref android.R.styleable#View_fadingEdgeLength
4973     */
4974    public int getVerticalFadingEdgeLength() {
4975        if (isVerticalFadingEdgeEnabled()) {
4976            ScrollabilityCache cache = mScrollCache;
4977            if (cache != null) {
4978                return cache.fadingEdgeLength;
4979            }
4980        }
4981        return 0;
4982    }
4983
4984    /**
4985     * Set the size of the faded edge used to indicate that more content in this
4986     * view is available.  Will not change whether the fading edge is enabled; use
4987     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4988     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4989     * for the vertical or horizontal fading edges.
4990     *
4991     * @param length The size in pixels of the faded edge used to indicate that more
4992     *        content in this view is visible.
4993     */
4994    public void setFadingEdgeLength(int length) {
4995        initScrollCache();
4996        mScrollCache.fadingEdgeLength = length;
4997    }
4998
4999    /**
5000     * Returns the size of the horizontal faded edges used to indicate that more
5001     * content in this view is visible.
5002     *
5003     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5004     *         faded edges are not enabled for this view.
5005     * @attr ref android.R.styleable#View_fadingEdgeLength
5006     */
5007    public int getHorizontalFadingEdgeLength() {
5008        if (isHorizontalFadingEdgeEnabled()) {
5009            ScrollabilityCache cache = mScrollCache;
5010            if (cache != null) {
5011                return cache.fadingEdgeLength;
5012            }
5013        }
5014        return 0;
5015    }
5016
5017    /**
5018     * Returns the width of the vertical scrollbar.
5019     *
5020     * @return The width in pixels of the vertical scrollbar or 0 if there
5021     *         is no vertical scrollbar.
5022     */
5023    public int getVerticalScrollbarWidth() {
5024        ScrollabilityCache cache = mScrollCache;
5025        if (cache != null) {
5026            ScrollBarDrawable scrollBar = cache.scrollBar;
5027            if (scrollBar != null) {
5028                int size = scrollBar.getSize(true);
5029                if (size <= 0) {
5030                    size = cache.scrollBarSize;
5031                }
5032                return size;
5033            }
5034            return 0;
5035        }
5036        return 0;
5037    }
5038
5039    /**
5040     * Returns the height of the horizontal scrollbar.
5041     *
5042     * @return The height in pixels of the horizontal scrollbar or 0 if
5043     *         there is no horizontal scrollbar.
5044     */
5045    protected int getHorizontalScrollbarHeight() {
5046        ScrollabilityCache cache = mScrollCache;
5047        if (cache != null) {
5048            ScrollBarDrawable scrollBar = cache.scrollBar;
5049            if (scrollBar != null) {
5050                int size = scrollBar.getSize(false);
5051                if (size <= 0) {
5052                    size = cache.scrollBarSize;
5053                }
5054                return size;
5055            }
5056            return 0;
5057        }
5058        return 0;
5059    }
5060
5061    /**
5062     * <p>
5063     * Initializes the scrollbars from a given set of styled attributes. This
5064     * method should be called by subclasses that need scrollbars and when an
5065     * instance of these subclasses is created programmatically rather than
5066     * being inflated from XML. This method is automatically called when the XML
5067     * is inflated.
5068     * </p>
5069     *
5070     * @param a the styled attributes set to initialize the scrollbars from
5071     *
5072     * @removed
5073     */
5074    protected void initializeScrollbars(TypedArray a) {
5075        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5076        // using the View filter array which is not available to the SDK. As such, internal
5077        // framework usage now uses initializeScrollbarsInternal and we grab a default
5078        // TypedArray with the right filter instead here.
5079        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5080
5081        initializeScrollbarsInternal(arr);
5082
5083        // We ignored the method parameter. Recycle the one we actually did use.
5084        arr.recycle();
5085    }
5086
5087    /**
5088     * <p>
5089     * Initializes the scrollbars from a given set of styled attributes. This
5090     * method should be called by subclasses that need scrollbars and when an
5091     * instance of these subclasses is created programmatically rather than
5092     * being inflated from XML. This method is automatically called when the XML
5093     * is inflated.
5094     * </p>
5095     *
5096     * @param a the styled attributes set to initialize the scrollbars from
5097     * @hide
5098     */
5099    protected void initializeScrollbarsInternal(TypedArray a) {
5100        initScrollCache();
5101
5102        final ScrollabilityCache scrollabilityCache = mScrollCache;
5103
5104        if (scrollabilityCache.scrollBar == null) {
5105            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5106            scrollabilityCache.scrollBar.setState(getDrawableState());
5107            scrollabilityCache.scrollBar.setCallback(this);
5108        }
5109
5110        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5111
5112        if (!fadeScrollbars) {
5113            scrollabilityCache.state = ScrollabilityCache.ON;
5114        }
5115        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5116
5117
5118        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5119                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5120                        .getScrollBarFadeDuration());
5121        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5122                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5123                ViewConfiguration.getScrollDefaultDelay());
5124
5125
5126        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5127                com.android.internal.R.styleable.View_scrollbarSize,
5128                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5129
5130        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5131        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5132
5133        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5134        if (thumb != null) {
5135            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5136        }
5137
5138        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5139                false);
5140        if (alwaysDraw) {
5141            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5142        }
5143
5144        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5145        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5146
5147        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5148        if (thumb != null) {
5149            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5150        }
5151
5152        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5153                false);
5154        if (alwaysDraw) {
5155            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5156        }
5157
5158        // Apply layout direction to the new Drawables if needed
5159        final int layoutDirection = getLayoutDirection();
5160        if (track != null) {
5161            track.setLayoutDirection(layoutDirection);
5162        }
5163        if (thumb != null) {
5164            thumb.setLayoutDirection(layoutDirection);
5165        }
5166
5167        // Re-apply user/background padding so that scrollbar(s) get added
5168        resolvePadding();
5169    }
5170
5171    private void initializeScrollIndicatorsInternal() {
5172        // Some day maybe we'll break this into top/left/start/etc. and let the
5173        // client control it. Until then, you can have any scroll indicator you
5174        // want as long as it's a 1dp foreground-colored rectangle.
5175        if (mScrollIndicatorDrawable == null) {
5176            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5177        }
5178    }
5179
5180    /**
5181     * <p>
5182     * Initalizes the scrollability cache if necessary.
5183     * </p>
5184     */
5185    private void initScrollCache() {
5186        if (mScrollCache == null) {
5187            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5188        }
5189    }
5190
5191    private ScrollabilityCache getScrollCache() {
5192        initScrollCache();
5193        return mScrollCache;
5194    }
5195
5196    /**
5197     * Set the position of the vertical scroll bar. Should be one of
5198     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5199     * {@link #SCROLLBAR_POSITION_RIGHT}.
5200     *
5201     * @param position Where the vertical scroll bar should be positioned.
5202     */
5203    public void setVerticalScrollbarPosition(int position) {
5204        if (mVerticalScrollbarPosition != position) {
5205            mVerticalScrollbarPosition = position;
5206            computeOpaqueFlags();
5207            resolvePadding();
5208        }
5209    }
5210
5211    /**
5212     * @return The position where the vertical scroll bar will show, if applicable.
5213     * @see #setVerticalScrollbarPosition(int)
5214     */
5215    public int getVerticalScrollbarPosition() {
5216        return mVerticalScrollbarPosition;
5217    }
5218
5219    boolean isOnScrollbar(float x, float y) {
5220        if (mScrollCache == null) {
5221            return false;
5222        }
5223        x += getScrollX();
5224        y += getScrollY();
5225        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5226            final Rect bounds = mScrollCache.mScrollBarBounds;
5227            getVerticalScrollBarBounds(bounds);
5228            if (bounds.contains((int)x, (int)y)) {
5229                return true;
5230            }
5231        }
5232        if (isHorizontalScrollBarEnabled()) {
5233            final Rect bounds = mScrollCache.mScrollBarBounds;
5234            getHorizontalScrollBarBounds(bounds);
5235            if (bounds.contains((int)x, (int)y)) {
5236                return true;
5237            }
5238        }
5239        return false;
5240    }
5241
5242    boolean isOnScrollbarThumb(float x, float y) {
5243        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5244    }
5245
5246    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5247        if (mScrollCache == null) {
5248            return false;
5249        }
5250        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5251            x += getScrollX();
5252            y += getScrollY();
5253            final Rect bounds = mScrollCache.mScrollBarBounds;
5254            getVerticalScrollBarBounds(bounds);
5255            final int range = computeVerticalScrollRange();
5256            final int offset = computeVerticalScrollOffset();
5257            final int extent = computeVerticalScrollExtent();
5258            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5259                    extent, range);
5260            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5261                    extent, range, offset);
5262            final int thumbTop = bounds.top + thumbOffset;
5263            if (x >= bounds.left && x <= bounds.right && y >= thumbTop
5264                    && y <= thumbTop + thumbLength) {
5265                return true;
5266            }
5267        }
5268        return false;
5269    }
5270
5271    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5272        if (mScrollCache == null) {
5273            return false;
5274        }
5275        if (isHorizontalScrollBarEnabled()) {
5276            x += getScrollX();
5277            y += getScrollY();
5278            final Rect bounds = mScrollCache.mScrollBarBounds;
5279            getHorizontalScrollBarBounds(bounds);
5280            final int range = computeHorizontalScrollRange();
5281            final int offset = computeHorizontalScrollOffset();
5282            final int extent = computeHorizontalScrollExtent();
5283            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5284                    extent, range);
5285            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5286                    extent, range, offset);
5287            final int thumbLeft = bounds.left + thumbOffset;
5288            if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
5289                    && y <= bounds.bottom) {
5290                return true;
5291            }
5292        }
5293        return false;
5294    }
5295
5296    boolean isDraggingScrollBar() {
5297        return mScrollCache != null
5298                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5299    }
5300
5301    /**
5302     * Sets the state of all scroll indicators.
5303     * <p>
5304     * See {@link #setScrollIndicators(int, int)} for usage information.
5305     *
5306     * @param indicators a bitmask of indicators that should be enabled, or
5307     *                   {@code 0} to disable all indicators
5308     * @see #setScrollIndicators(int, int)
5309     * @see #getScrollIndicators()
5310     * @attr ref android.R.styleable#View_scrollIndicators
5311     */
5312    public void setScrollIndicators(@ScrollIndicators int indicators) {
5313        setScrollIndicators(indicators,
5314                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5315    }
5316
5317    /**
5318     * Sets the state of the scroll indicators specified by the mask. To change
5319     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5320     * <p>
5321     * When a scroll indicator is enabled, it will be displayed if the view
5322     * can scroll in the direction of the indicator.
5323     * <p>
5324     * Multiple indicator types may be enabled or disabled by passing the
5325     * logical OR of the desired types. If multiple types are specified, they
5326     * will all be set to the same enabled state.
5327     * <p>
5328     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5329     *
5330     * @param indicators the indicator direction, or the logical OR of multiple
5331     *             indicator directions. One or more of:
5332     *             <ul>
5333     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5334     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5335     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5336     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5337     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5338     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5339     *             </ul>
5340     * @see #setScrollIndicators(int)
5341     * @see #getScrollIndicators()
5342     * @attr ref android.R.styleable#View_scrollIndicators
5343     */
5344    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5345        // Shift and sanitize mask.
5346        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5347        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5348
5349        // Shift and mask indicators.
5350        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5351        indicators &= mask;
5352
5353        // Merge with non-masked flags.
5354        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5355
5356        if (mPrivateFlags3 != updatedFlags) {
5357            mPrivateFlags3 = updatedFlags;
5358
5359            if (indicators != 0) {
5360                initializeScrollIndicatorsInternal();
5361            }
5362            invalidate();
5363        }
5364    }
5365
5366    /**
5367     * Returns a bitmask representing the enabled scroll indicators.
5368     * <p>
5369     * For example, if the top and left scroll indicators are enabled and all
5370     * other indicators are disabled, the return value will be
5371     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5372     * <p>
5373     * To check whether the bottom scroll indicator is enabled, use the value
5374     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5375     *
5376     * @return a bitmask representing the enabled scroll indicators
5377     */
5378    @ScrollIndicators
5379    public int getScrollIndicators() {
5380        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5381                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5382    }
5383
5384    ListenerInfo getListenerInfo() {
5385        if (mListenerInfo != null) {
5386            return mListenerInfo;
5387        }
5388        mListenerInfo = new ListenerInfo();
5389        return mListenerInfo;
5390    }
5391
5392    /**
5393     * Register a callback to be invoked when the scroll X or Y positions of
5394     * this view change.
5395     * <p>
5396     * <b>Note:</b> Some views handle scrolling independently from View and may
5397     * have their own separate listeners for scroll-type events. For example,
5398     * {@link android.widget.ListView ListView} allows clients to register an
5399     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5400     * to listen for changes in list scroll position.
5401     *
5402     * @param l The listener to notify when the scroll X or Y position changes.
5403     * @see android.view.View#getScrollX()
5404     * @see android.view.View#getScrollY()
5405     */
5406    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5407        getListenerInfo().mOnScrollChangeListener = l;
5408    }
5409
5410    /**
5411     * Register a callback to be invoked when focus of this view changed.
5412     *
5413     * @param l The callback that will run.
5414     */
5415    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5416        getListenerInfo().mOnFocusChangeListener = l;
5417    }
5418
5419    /**
5420     * Add a listener that will be called when the bounds of the view change due to
5421     * layout processing.
5422     *
5423     * @param listener The listener that will be called when layout bounds change.
5424     */
5425    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5426        ListenerInfo li = getListenerInfo();
5427        if (li.mOnLayoutChangeListeners == null) {
5428            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5429        }
5430        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5431            li.mOnLayoutChangeListeners.add(listener);
5432        }
5433    }
5434
5435    /**
5436     * Remove a listener for layout changes.
5437     *
5438     * @param listener The listener for layout bounds change.
5439     */
5440    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5441        ListenerInfo li = mListenerInfo;
5442        if (li == null || li.mOnLayoutChangeListeners == null) {
5443            return;
5444        }
5445        li.mOnLayoutChangeListeners.remove(listener);
5446    }
5447
5448    /**
5449     * Add a listener for attach state changes.
5450     *
5451     * This listener will be called whenever this view is attached or detached
5452     * from a window. Remove the listener using
5453     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5454     *
5455     * @param listener Listener to attach
5456     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5457     */
5458    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5459        ListenerInfo li = getListenerInfo();
5460        if (li.mOnAttachStateChangeListeners == null) {
5461            li.mOnAttachStateChangeListeners
5462                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5463        }
5464        li.mOnAttachStateChangeListeners.add(listener);
5465    }
5466
5467    /**
5468     * Remove a listener for attach state changes. The listener will receive no further
5469     * notification of window attach/detach events.
5470     *
5471     * @param listener Listener to remove
5472     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5473     */
5474    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5475        ListenerInfo li = mListenerInfo;
5476        if (li == null || li.mOnAttachStateChangeListeners == null) {
5477            return;
5478        }
5479        li.mOnAttachStateChangeListeners.remove(listener);
5480    }
5481
5482    /**
5483     * Returns the focus-change callback registered for this view.
5484     *
5485     * @return The callback, or null if one is not registered.
5486     */
5487    public OnFocusChangeListener getOnFocusChangeListener() {
5488        ListenerInfo li = mListenerInfo;
5489        return li != null ? li.mOnFocusChangeListener : null;
5490    }
5491
5492    /**
5493     * Register a callback to be invoked when this view is clicked. If this view is not
5494     * clickable, it becomes clickable.
5495     *
5496     * @param l The callback that will run
5497     *
5498     * @see #setClickable(boolean)
5499     */
5500    public void setOnClickListener(@Nullable OnClickListener l) {
5501        if (!isClickable()) {
5502            setClickable(true);
5503        }
5504        getListenerInfo().mOnClickListener = l;
5505    }
5506
5507    /**
5508     * Return whether this view has an attached OnClickListener.  Returns
5509     * true if there is a listener, false if there is none.
5510     */
5511    public boolean hasOnClickListeners() {
5512        ListenerInfo li = mListenerInfo;
5513        return (li != null && li.mOnClickListener != null);
5514    }
5515
5516    /**
5517     * Register a callback to be invoked when this view is clicked and held. If this view is not
5518     * long clickable, it becomes long clickable.
5519     *
5520     * @param l The callback that will run
5521     *
5522     * @see #setLongClickable(boolean)
5523     */
5524    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5525        if (!isLongClickable()) {
5526            setLongClickable(true);
5527        }
5528        getListenerInfo().mOnLongClickListener = l;
5529    }
5530
5531    /**
5532     * Register a callback to be invoked when this view is context clicked. If the view is not
5533     * context clickable, it becomes context clickable.
5534     *
5535     * @param l The callback that will run
5536     * @see #setContextClickable(boolean)
5537     */
5538    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5539        if (!isContextClickable()) {
5540            setContextClickable(true);
5541        }
5542        getListenerInfo().mOnContextClickListener = l;
5543    }
5544
5545    /**
5546     * Register a callback to be invoked when the context menu for this view is
5547     * being built. If this view is not long clickable, it becomes long clickable.
5548     *
5549     * @param l The callback that will run
5550     *
5551     */
5552    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5553        if (!isLongClickable()) {
5554            setLongClickable(true);
5555        }
5556        getListenerInfo().mOnCreateContextMenuListener = l;
5557    }
5558
5559    /**
5560     * Set an observer to collect stats for each frame rendered for this view.
5561     *
5562     * @hide
5563     */
5564    public void addFrameMetricsListener(Window window,
5565            Window.OnFrameMetricsAvailableListener listener,
5566            Handler handler) {
5567        if (mAttachInfo != null) {
5568            if (mAttachInfo.mHardwareRenderer != null) {
5569                if (mFrameMetricsObservers == null) {
5570                    mFrameMetricsObservers = new ArrayList<>();
5571                }
5572
5573                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5574                        handler.getLooper(), listener);
5575                mFrameMetricsObservers.add(fmo);
5576                mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo);
5577            } else {
5578                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5579            }
5580        } else {
5581            if (mFrameMetricsObservers == null) {
5582                mFrameMetricsObservers = new ArrayList<>();
5583            }
5584
5585            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5586                    handler.getLooper(), listener);
5587            mFrameMetricsObservers.add(fmo);
5588        }
5589    }
5590
5591    /**
5592     * Remove observer configured to collect frame stats for this view.
5593     *
5594     * @hide
5595     */
5596    public void removeFrameMetricsListener(
5597            Window.OnFrameMetricsAvailableListener listener) {
5598        ThreadedRenderer renderer = getHardwareRenderer();
5599        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
5600        if (fmo == null) {
5601            throw new IllegalArgumentException(
5602                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
5603        }
5604
5605        if (mFrameMetricsObservers != null) {
5606            mFrameMetricsObservers.remove(fmo);
5607            if (renderer != null) {
5608                renderer.removeFrameMetricsObserver(fmo);
5609            }
5610        }
5611    }
5612
5613    private void registerPendingFrameMetricsObservers() {
5614        if (mFrameMetricsObservers != null) {
5615            ThreadedRenderer renderer = getHardwareRenderer();
5616            if (renderer != null) {
5617                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
5618                    renderer.addFrameMetricsObserver(fmo);
5619                }
5620            } else {
5621                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5622            }
5623        }
5624    }
5625
5626    private FrameMetricsObserver findFrameMetricsObserver(
5627            Window.OnFrameMetricsAvailableListener listener) {
5628        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
5629            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
5630            if (observer.mListener == listener) {
5631                return observer;
5632            }
5633        }
5634
5635        return null;
5636    }
5637
5638    /**
5639     * Call this view's OnClickListener, if it is defined.  Performs all normal
5640     * actions associated with clicking: reporting accessibility event, playing
5641     * a sound, etc.
5642     *
5643     * @return True there was an assigned OnClickListener that was called, false
5644     *         otherwise is returned.
5645     */
5646    public boolean performClick() {
5647        final boolean result;
5648        final ListenerInfo li = mListenerInfo;
5649        if (li != null && li.mOnClickListener != null) {
5650            playSoundEffect(SoundEffectConstants.CLICK);
5651            li.mOnClickListener.onClick(this);
5652            result = true;
5653        } else {
5654            result = false;
5655        }
5656
5657        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5658        return result;
5659    }
5660
5661    /**
5662     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5663     * this only calls the listener, and does not do any associated clicking
5664     * actions like reporting an accessibility event.
5665     *
5666     * @return True there was an assigned OnClickListener that was called, false
5667     *         otherwise is returned.
5668     */
5669    public boolean callOnClick() {
5670        ListenerInfo li = mListenerInfo;
5671        if (li != null && li.mOnClickListener != null) {
5672            li.mOnClickListener.onClick(this);
5673            return true;
5674        }
5675        return false;
5676    }
5677
5678    /**
5679     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5680     * context menu if the OnLongClickListener did not consume the event.
5681     *
5682     * @return {@code true} if one of the above receivers consumed the event,
5683     *         {@code false} otherwise
5684     */
5685    public boolean performLongClick() {
5686        return performLongClickInternal(mLongClickX, mLongClickY);
5687    }
5688
5689    /**
5690     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5691     * context menu if the OnLongClickListener did not consume the event,
5692     * anchoring it to an (x,y) coordinate.
5693     *
5694     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5695     *          to disable anchoring
5696     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5697     *          to disable anchoring
5698     * @return {@code true} if one of the above receivers consumed the event,
5699     *         {@code false} otherwise
5700     */
5701    public boolean performLongClick(float x, float y) {
5702        mLongClickX = x;
5703        mLongClickY = y;
5704        final boolean handled = performLongClick();
5705        mLongClickX = Float.NaN;
5706        mLongClickY = Float.NaN;
5707        return handled;
5708    }
5709
5710    /**
5711     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5712     * context menu if the OnLongClickListener did not consume the event,
5713     * optionally anchoring it to an (x,y) coordinate.
5714     *
5715     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5716     *          to disable anchoring
5717     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5718     *          to disable anchoring
5719     * @return {@code true} if one of the above receivers consumed the event,
5720     *         {@code false} otherwise
5721     */
5722    private boolean performLongClickInternal(float x, float y) {
5723        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5724
5725        boolean handled = false;
5726        final ListenerInfo li = mListenerInfo;
5727        if (li != null && li.mOnLongClickListener != null) {
5728            handled = li.mOnLongClickListener.onLongClick(View.this);
5729        }
5730        if (!handled) {
5731            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5732            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5733        }
5734        if (handled) {
5735            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5736        }
5737        return handled;
5738    }
5739
5740    /**
5741     * Call this view's OnContextClickListener, if it is defined.
5742     *
5743     * @param x the x coordinate of the context click
5744     * @param y the y coordinate of the context click
5745     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5746     *         otherwise.
5747     */
5748    public boolean performContextClick(float x, float y) {
5749        return performContextClick();
5750    }
5751
5752    /**
5753     * Call this view's OnContextClickListener, if it is defined.
5754     *
5755     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5756     *         otherwise.
5757     */
5758    public boolean performContextClick() {
5759        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5760
5761        boolean handled = false;
5762        ListenerInfo li = mListenerInfo;
5763        if (li != null && li.mOnContextClickListener != null) {
5764            handled = li.mOnContextClickListener.onContextClick(View.this);
5765        }
5766        if (handled) {
5767            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5768        }
5769        return handled;
5770    }
5771
5772    /**
5773     * Performs button-related actions during a touch down event.
5774     *
5775     * @param event The event.
5776     * @return True if the down was consumed.
5777     *
5778     * @hide
5779     */
5780    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5781        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5782            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5783            showContextMenu(event.getX(), event.getY());
5784            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5785            return true;
5786        }
5787        return false;
5788    }
5789
5790    /**
5791     * Shows the context menu for this view.
5792     *
5793     * @return {@code true} if the context menu was shown, {@code false}
5794     *         otherwise
5795     * @see #showContextMenu(float, float)
5796     */
5797    public boolean showContextMenu() {
5798        return getParent().showContextMenuForChild(this);
5799    }
5800
5801    /**
5802     * Shows the context menu for this view anchored to the specified
5803     * view-relative coordinate.
5804     *
5805     * @param x the X coordinate in pixels relative to the view to which the
5806     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5807     * @param y the Y coordinate in pixels relative to the view to which the
5808     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5809     * @return {@code true} if the context menu was shown, {@code false}
5810     *         otherwise
5811     */
5812    public boolean showContextMenu(float x, float y) {
5813        return getParent().showContextMenuForChild(this, x, y);
5814    }
5815
5816    /**
5817     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5818     *
5819     * @param callback Callback that will control the lifecycle of the action mode
5820     * @return The new action mode if it is started, null otherwise
5821     *
5822     * @see ActionMode
5823     * @see #startActionMode(android.view.ActionMode.Callback, int)
5824     */
5825    public ActionMode startActionMode(ActionMode.Callback callback) {
5826        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5827    }
5828
5829    /**
5830     * Start an action mode with the given type.
5831     *
5832     * @param callback Callback that will control the lifecycle of the action mode
5833     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5834     * @return The new action mode if it is started, null otherwise
5835     *
5836     * @see ActionMode
5837     */
5838    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5839        ViewParent parent = getParent();
5840        if (parent == null) return null;
5841        try {
5842            return parent.startActionModeForChild(this, callback, type);
5843        } catch (AbstractMethodError ame) {
5844            // Older implementations of custom views might not implement this.
5845            return parent.startActionModeForChild(this, callback);
5846        }
5847    }
5848
5849    /**
5850     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5851     * Context, creating a unique View identifier to retrieve the result.
5852     *
5853     * @param intent The Intent to be started.
5854     * @param requestCode The request code to use.
5855     * @hide
5856     */
5857    public void startActivityForResult(Intent intent, int requestCode) {
5858        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5859        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5860    }
5861
5862    /**
5863     * If this View corresponds to the calling who, dispatches the activity result.
5864     * @param who The identifier for the targeted View to receive the result.
5865     * @param requestCode The integer request code originally supplied to
5866     *                    startActivityForResult(), allowing you to identify who this
5867     *                    result came from.
5868     * @param resultCode The integer result code returned by the child activity
5869     *                   through its setResult().
5870     * @param data An Intent, which can return result data to the caller
5871     *               (various data can be attached to Intent "extras").
5872     * @return {@code true} if the activity result was dispatched.
5873     * @hide
5874     */
5875    public boolean dispatchActivityResult(
5876            String who, int requestCode, int resultCode, Intent data) {
5877        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5878            onActivityResult(requestCode, resultCode, data);
5879            mStartActivityRequestWho = null;
5880            return true;
5881        }
5882        return false;
5883    }
5884
5885    /**
5886     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5887     *
5888     * @param requestCode The integer request code originally supplied to
5889     *                    startActivityForResult(), allowing you to identify who this
5890     *                    result came from.
5891     * @param resultCode The integer result code returned by the child activity
5892     *                   through its setResult().
5893     * @param data An Intent, which can return result data to the caller
5894     *               (various data can be attached to Intent "extras").
5895     * @hide
5896     */
5897    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5898        // Do nothing.
5899    }
5900
5901    /**
5902     * Register a callback to be invoked when a hardware key is pressed in this view.
5903     * Key presses in software input methods will generally not trigger the methods of
5904     * this listener.
5905     * @param l the key listener to attach to this view
5906     */
5907    public void setOnKeyListener(OnKeyListener l) {
5908        getListenerInfo().mOnKeyListener = l;
5909    }
5910
5911    /**
5912     * Register a callback to be invoked when a touch event is sent to this view.
5913     * @param l the touch listener to attach to this view
5914     */
5915    public void setOnTouchListener(OnTouchListener l) {
5916        getListenerInfo().mOnTouchListener = l;
5917    }
5918
5919    /**
5920     * Register a callback to be invoked when a generic motion event is sent to this view.
5921     * @param l the generic motion listener to attach to this view
5922     */
5923    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5924        getListenerInfo().mOnGenericMotionListener = l;
5925    }
5926
5927    /**
5928     * Register a callback to be invoked when a hover event is sent to this view.
5929     * @param l the hover listener to attach to this view
5930     */
5931    public void setOnHoverListener(OnHoverListener l) {
5932        getListenerInfo().mOnHoverListener = l;
5933    }
5934
5935    /**
5936     * Register a drag event listener callback object for this View. The parameter is
5937     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5938     * View, the system calls the
5939     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5940     * @param l An implementation of {@link android.view.View.OnDragListener}.
5941     */
5942    public void setOnDragListener(OnDragListener l) {
5943        getListenerInfo().mOnDragListener = l;
5944    }
5945
5946    /**
5947     * Give this view focus. This will cause
5948     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5949     *
5950     * Note: this does not check whether this {@link View} should get focus, it just
5951     * gives it focus no matter what.  It should only be called internally by framework
5952     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5953     *
5954     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5955     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5956     *        focus moved when requestFocus() is called. It may not always
5957     *        apply, in which case use the default View.FOCUS_DOWN.
5958     * @param previouslyFocusedRect The rectangle of the view that had focus
5959     *        prior in this View's coordinate system.
5960     */
5961    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5962        if (DBG) {
5963            System.out.println(this + " requestFocus()");
5964        }
5965
5966        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5967            mPrivateFlags |= PFLAG_FOCUSED;
5968
5969            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5970
5971            if (mParent != null) {
5972                mParent.requestChildFocus(this, this);
5973            }
5974
5975            if (mAttachInfo != null) {
5976                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5977            }
5978
5979            onFocusChanged(true, direction, previouslyFocusedRect);
5980            refreshDrawableState();
5981        }
5982    }
5983
5984    /**
5985     * Sets this view's preference for reveal behavior when it gains focus.
5986     *
5987     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
5988     * this view would prefer to be brought fully into view when it gains focus.
5989     * For example, a text field that a user is meant to type into. Other views such
5990     * as scrolling containers may prefer to opt-out of this behavior.</p>
5991     *
5992     * <p>The default value for views is true, though subclasses may change this
5993     * based on their preferred behavior.</p>
5994     *
5995     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
5996     *
5997     * @see #getRevealOnFocusHint()
5998     */
5999    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6000        if (revealOnFocus) {
6001            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6002        } else {
6003            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6004        }
6005    }
6006
6007    /**
6008     * Returns this view's preference for reveal behavior when it gains focus.
6009     *
6010     * <p>When this method returns true for a child view requesting focus, ancestor
6011     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6012     * should make a best effort to make the newly focused child fully visible to the user.
6013     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6014     * other properties affecting visibility to the user as part of the focus change.</p>
6015     *
6016     * @return true if this view would prefer to become fully visible when it gains focus,
6017     *         false if it would prefer not to disrupt scroll positioning
6018     *
6019     * @see #setRevealOnFocusHint(boolean)
6020     */
6021    public final boolean getRevealOnFocusHint() {
6022        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6023    }
6024
6025    /**
6026     * Populates <code>outRect</code> with the hotspot bounds. By default,
6027     * the hotspot bounds are identical to the screen bounds.
6028     *
6029     * @param outRect rect to populate with hotspot bounds
6030     * @hide Only for internal use by views and widgets.
6031     */
6032    public void getHotspotBounds(Rect outRect) {
6033        final Drawable background = getBackground();
6034        if (background != null) {
6035            background.getHotspotBounds(outRect);
6036        } else {
6037            getBoundsOnScreen(outRect);
6038        }
6039    }
6040
6041    /**
6042     * Request that a rectangle of this view be visible on the screen,
6043     * scrolling if necessary just enough.
6044     *
6045     * <p>A View should call this if it maintains some notion of which part
6046     * of its content is interesting.  For example, a text editing view
6047     * should call this when its cursor moves.
6048     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6049     * It should not be affected by which part of the View is currently visible or its scroll
6050     * position.
6051     *
6052     * @param rectangle The rectangle in the View's content coordinate space
6053     * @return Whether any parent scrolled.
6054     */
6055    public boolean requestRectangleOnScreen(Rect rectangle) {
6056        return requestRectangleOnScreen(rectangle, false);
6057    }
6058
6059    /**
6060     * Request that a rectangle of this view be visible on the screen,
6061     * scrolling if necessary just enough.
6062     *
6063     * <p>A View should call this if it maintains some notion of which part
6064     * of its content is interesting.  For example, a text editing view
6065     * should call this when its cursor moves.
6066     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6067     * It should not be affected by which part of the View is currently visible or its scroll
6068     * position.
6069     * <p>When <code>immediate</code> is set to true, scrolling will not be
6070     * animated.
6071     *
6072     * @param rectangle The rectangle in the View's content coordinate space
6073     * @param immediate True to forbid animated scrolling, false otherwise
6074     * @return Whether any parent scrolled.
6075     */
6076    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6077        if (mParent == null) {
6078            return false;
6079        }
6080
6081        View child = this;
6082
6083        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6084        position.set(rectangle);
6085
6086        ViewParent parent = mParent;
6087        boolean scrolled = false;
6088        while (parent != null) {
6089            rectangle.set((int) position.left, (int) position.top,
6090                    (int) position.right, (int) position.bottom);
6091
6092            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6093
6094            if (!(parent instanceof View)) {
6095                break;
6096            }
6097
6098            // move it from child's content coordinate space to parent's content coordinate space
6099            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6100
6101            child = (View) parent;
6102            parent = child.getParent();
6103        }
6104
6105        return scrolled;
6106    }
6107
6108    /**
6109     * Called when this view wants to give up focus. If focus is cleared
6110     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6111     * <p>
6112     * <strong>Note:</strong> When a View clears focus the framework is trying
6113     * to give focus to the first focusable View from the top. Hence, if this
6114     * View is the first from the top that can take focus, then all callbacks
6115     * related to clearing focus will be invoked after which the framework will
6116     * give focus to this view.
6117     * </p>
6118     */
6119    public void clearFocus() {
6120        if (DBG) {
6121            System.out.println(this + " clearFocus()");
6122        }
6123
6124        clearFocusInternal(null, true, true);
6125    }
6126
6127    /**
6128     * Clears focus from the view, optionally propagating the change up through
6129     * the parent hierarchy and requesting that the root view place new focus.
6130     *
6131     * @param propagate whether to propagate the change up through the parent
6132     *            hierarchy
6133     * @param refocus when propagate is true, specifies whether to request the
6134     *            root view place new focus
6135     */
6136    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6137        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6138            mPrivateFlags &= ~PFLAG_FOCUSED;
6139
6140            if (propagate && mParent != null) {
6141                mParent.clearChildFocus(this);
6142            }
6143
6144            onFocusChanged(false, 0, null);
6145            refreshDrawableState();
6146
6147            if (propagate && (!refocus || !rootViewRequestFocus())) {
6148                notifyGlobalFocusCleared(this);
6149            }
6150        }
6151    }
6152
6153    void notifyGlobalFocusCleared(View oldFocus) {
6154        if (oldFocus != null && mAttachInfo != null) {
6155            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6156        }
6157    }
6158
6159    boolean rootViewRequestFocus() {
6160        final View root = getRootView();
6161        return root != null && root.requestFocus();
6162    }
6163
6164    /**
6165     * Called internally by the view system when a new view is getting focus.
6166     * This is what clears the old focus.
6167     * <p>
6168     * <b>NOTE:</b> The parent view's focused child must be updated manually
6169     * after calling this method. Otherwise, the view hierarchy may be left in
6170     * an inconstent state.
6171     */
6172    void unFocus(View focused) {
6173        if (DBG) {
6174            System.out.println(this + " unFocus()");
6175        }
6176
6177        clearFocusInternal(focused, false, false);
6178    }
6179
6180    /**
6181     * Returns true if this view has focus itself, or is the ancestor of the
6182     * view that has focus.
6183     *
6184     * @return True if this view has or contains focus, false otherwise.
6185     */
6186    @ViewDebug.ExportedProperty(category = "focus")
6187    public boolean hasFocus() {
6188        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6189    }
6190
6191    /**
6192     * Returns true if this view is focusable or if it contains a reachable View
6193     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
6194     * is a View whose parents do not block descendants focus.
6195     *
6196     * Only {@link #VISIBLE} views are considered focusable.
6197     *
6198     * @return True if the view is focusable or if the view contains a focusable
6199     *         View, false otherwise.
6200     *
6201     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6202     * @see ViewGroup#getTouchscreenBlocksFocus()
6203     */
6204    public boolean hasFocusable() {
6205        if (!isFocusableInTouchMode()) {
6206            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6207                final ViewGroup g = (ViewGroup) p;
6208                if (g.shouldBlockFocusForTouchscreen()) {
6209                    return false;
6210                }
6211            }
6212        }
6213        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
6214    }
6215
6216    /**
6217     * Called by the view system when the focus state of this view changes.
6218     * When the focus change event is caused by directional navigation, direction
6219     * and previouslyFocusedRect provide insight into where the focus is coming from.
6220     * When overriding, be sure to call up through to the super class so that
6221     * the standard focus handling will occur.
6222     *
6223     * @param gainFocus True if the View has focus; false otherwise.
6224     * @param direction The direction focus has moved when requestFocus()
6225     *                  is called to give this view focus. Values are
6226     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6227     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6228     *                  It may not always apply, in which case use the default.
6229     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6230     *        system, of the previously focused view.  If applicable, this will be
6231     *        passed in as finer grained information about where the focus is coming
6232     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6233     */
6234    @CallSuper
6235    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6236            @Nullable Rect previouslyFocusedRect) {
6237        if (gainFocus) {
6238            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6239        } else {
6240            notifyViewAccessibilityStateChangedIfNeeded(
6241                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6242        }
6243
6244        InputMethodManager imm = InputMethodManager.peekInstance();
6245        if (!gainFocus) {
6246            if (isPressed()) {
6247                setPressed(false);
6248            }
6249            if (imm != null && mAttachInfo != null
6250                    && mAttachInfo.mHasWindowFocus) {
6251                imm.focusOut(this);
6252            }
6253            onFocusLost();
6254        } else if (imm != null && mAttachInfo != null
6255                && mAttachInfo.mHasWindowFocus) {
6256            imm.focusIn(this);
6257        }
6258
6259        invalidate(true);
6260        ListenerInfo li = mListenerInfo;
6261        if (li != null && li.mOnFocusChangeListener != null) {
6262            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6263        }
6264
6265        if (mAttachInfo != null) {
6266            mAttachInfo.mKeyDispatchState.reset(this);
6267        }
6268    }
6269
6270    /**
6271     * Sends an accessibility event of the given type. If accessibility is
6272     * not enabled this method has no effect. The default implementation calls
6273     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6274     * to populate information about the event source (this View), then calls
6275     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6276     * populate the text content of the event source including its descendants,
6277     * and last calls
6278     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6279     * on its parent to request sending of the event to interested parties.
6280     * <p>
6281     * If an {@link AccessibilityDelegate} has been specified via calling
6282     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6283     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6284     * responsible for handling this call.
6285     * </p>
6286     *
6287     * @param eventType The type of the event to send, as defined by several types from
6288     * {@link android.view.accessibility.AccessibilityEvent}, such as
6289     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6290     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6291     *
6292     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6293     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6294     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6295     * @see AccessibilityDelegate
6296     */
6297    public void sendAccessibilityEvent(int eventType) {
6298        if (mAccessibilityDelegate != null) {
6299            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6300        } else {
6301            sendAccessibilityEventInternal(eventType);
6302        }
6303    }
6304
6305    /**
6306     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6307     * {@link AccessibilityEvent} to make an announcement which is related to some
6308     * sort of a context change for which none of the events representing UI transitions
6309     * is a good fit. For example, announcing a new page in a book. If accessibility
6310     * is not enabled this method does nothing.
6311     *
6312     * @param text The announcement text.
6313     */
6314    public void announceForAccessibility(CharSequence text) {
6315        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6316            AccessibilityEvent event = AccessibilityEvent.obtain(
6317                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6318            onInitializeAccessibilityEvent(event);
6319            event.getText().add(text);
6320            event.setContentDescription(null);
6321            mParent.requestSendAccessibilityEvent(this, event);
6322        }
6323    }
6324
6325    /**
6326     * @see #sendAccessibilityEvent(int)
6327     *
6328     * Note: Called from the default {@link AccessibilityDelegate}.
6329     *
6330     * @hide
6331     */
6332    public void sendAccessibilityEventInternal(int eventType) {
6333        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6334            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6335        }
6336    }
6337
6338    /**
6339     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6340     * takes as an argument an empty {@link AccessibilityEvent} and does not
6341     * perform a check whether accessibility is enabled.
6342     * <p>
6343     * If an {@link AccessibilityDelegate} has been specified via calling
6344     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6345     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6346     * is responsible for handling this call.
6347     * </p>
6348     *
6349     * @param event The event to send.
6350     *
6351     * @see #sendAccessibilityEvent(int)
6352     */
6353    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6354        if (mAccessibilityDelegate != null) {
6355            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6356        } else {
6357            sendAccessibilityEventUncheckedInternal(event);
6358        }
6359    }
6360
6361    /**
6362     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6363     *
6364     * Note: Called from the default {@link AccessibilityDelegate}.
6365     *
6366     * @hide
6367     */
6368    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6369        if (!isShown()) {
6370            return;
6371        }
6372        onInitializeAccessibilityEvent(event);
6373        // Only a subset of accessibility events populates text content.
6374        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6375            dispatchPopulateAccessibilityEvent(event);
6376        }
6377        // In the beginning we called #isShown(), so we know that getParent() is not null.
6378        getParent().requestSendAccessibilityEvent(this, event);
6379    }
6380
6381    /**
6382     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6383     * to its children for adding their text content to the event. Note that the
6384     * event text is populated in a separate dispatch path since we add to the
6385     * event not only the text of the source but also the text of all its descendants.
6386     * A typical implementation will call
6387     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6388     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6389     * on each child. Override this method if custom population of the event text
6390     * content is required.
6391     * <p>
6392     * If an {@link AccessibilityDelegate} has been specified via calling
6393     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6394     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6395     * is responsible for handling this call.
6396     * </p>
6397     * <p>
6398     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6399     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6400     * </p>
6401     *
6402     * @param event The event.
6403     *
6404     * @return True if the event population was completed.
6405     */
6406    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6407        if (mAccessibilityDelegate != null) {
6408            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6409        } else {
6410            return dispatchPopulateAccessibilityEventInternal(event);
6411        }
6412    }
6413
6414    /**
6415     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6416     *
6417     * Note: Called from the default {@link AccessibilityDelegate}.
6418     *
6419     * @hide
6420     */
6421    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6422        onPopulateAccessibilityEvent(event);
6423        return false;
6424    }
6425
6426    /**
6427     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6428     * giving a chance to this View to populate the accessibility event with its
6429     * text content. While this method is free to modify event
6430     * attributes other than text content, doing so should normally be performed in
6431     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6432     * <p>
6433     * Example: Adding formatted date string to an accessibility event in addition
6434     *          to the text added by the super implementation:
6435     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6436     *     super.onPopulateAccessibilityEvent(event);
6437     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6438     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6439     *         mCurrentDate.getTimeInMillis(), flags);
6440     *     event.getText().add(selectedDateUtterance);
6441     * }</pre>
6442     * <p>
6443     * If an {@link AccessibilityDelegate} has been specified via calling
6444     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6445     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6446     * is responsible for handling this call.
6447     * </p>
6448     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6449     * information to the event, in case the default implementation has basic information to add.
6450     * </p>
6451     *
6452     * @param event The accessibility event which to populate.
6453     *
6454     * @see #sendAccessibilityEvent(int)
6455     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6456     */
6457    @CallSuper
6458    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6459        if (mAccessibilityDelegate != null) {
6460            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6461        } else {
6462            onPopulateAccessibilityEventInternal(event);
6463        }
6464    }
6465
6466    /**
6467     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6468     *
6469     * Note: Called from the default {@link AccessibilityDelegate}.
6470     *
6471     * @hide
6472     */
6473    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6474    }
6475
6476    /**
6477     * Initializes an {@link AccessibilityEvent} with information about
6478     * this View which is the event source. In other words, the source of
6479     * an accessibility event is the view whose state change triggered firing
6480     * the event.
6481     * <p>
6482     * Example: Setting the password property of an event in addition
6483     *          to properties set by the super implementation:
6484     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6485     *     super.onInitializeAccessibilityEvent(event);
6486     *     event.setPassword(true);
6487     * }</pre>
6488     * <p>
6489     * If an {@link AccessibilityDelegate} has been specified via calling
6490     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6491     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6492     * is responsible for handling this call.
6493     * </p>
6494     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6495     * information to the event, in case the default implementation has basic information to add.
6496     * </p>
6497     * @param event The event to initialize.
6498     *
6499     * @see #sendAccessibilityEvent(int)
6500     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6501     */
6502    @CallSuper
6503    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6504        if (mAccessibilityDelegate != null) {
6505            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6506        } else {
6507            onInitializeAccessibilityEventInternal(event);
6508        }
6509    }
6510
6511    /**
6512     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6513     *
6514     * Note: Called from the default {@link AccessibilityDelegate}.
6515     *
6516     * @hide
6517     */
6518    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6519        event.setSource(this);
6520        event.setClassName(getAccessibilityClassName());
6521        event.setPackageName(getContext().getPackageName());
6522        event.setEnabled(isEnabled());
6523        event.setContentDescription(mContentDescription);
6524
6525        switch (event.getEventType()) {
6526            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6527                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6528                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6529                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6530                event.setItemCount(focusablesTempList.size());
6531                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6532                if (mAttachInfo != null) {
6533                    focusablesTempList.clear();
6534                }
6535            } break;
6536            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6537                CharSequence text = getIterableTextForAccessibility();
6538                if (text != null && text.length() > 0) {
6539                    event.setFromIndex(getAccessibilitySelectionStart());
6540                    event.setToIndex(getAccessibilitySelectionEnd());
6541                    event.setItemCount(text.length());
6542                }
6543            } break;
6544        }
6545    }
6546
6547    /**
6548     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6549     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6550     * This method is responsible for obtaining an accessibility node info from a
6551     * pool of reusable instances and calling
6552     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6553     * initialize the former.
6554     * <p>
6555     * Note: The client is responsible for recycling the obtained instance by calling
6556     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6557     * </p>
6558     *
6559     * @return A populated {@link AccessibilityNodeInfo}.
6560     *
6561     * @see AccessibilityNodeInfo
6562     */
6563    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6564        if (mAccessibilityDelegate != null) {
6565            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6566        } else {
6567            return createAccessibilityNodeInfoInternal();
6568        }
6569    }
6570
6571    /**
6572     * @see #createAccessibilityNodeInfo()
6573     *
6574     * @hide
6575     */
6576    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6577        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6578        if (provider != null) {
6579            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6580        } else {
6581            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6582            onInitializeAccessibilityNodeInfo(info);
6583            return info;
6584        }
6585    }
6586
6587    /**
6588     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6589     * The base implementation sets:
6590     * <ul>
6591     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6592     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6593     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6594     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6595     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6596     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6597     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6598     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6599     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6600     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6601     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6602     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6603     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6604     * </ul>
6605     * <p>
6606     * Subclasses should override this method, call the super implementation,
6607     * and set additional attributes.
6608     * </p>
6609     * <p>
6610     * If an {@link AccessibilityDelegate} has been specified via calling
6611     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6612     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6613     * is responsible for handling this call.
6614     * </p>
6615     *
6616     * @param info The instance to initialize.
6617     */
6618    @CallSuper
6619    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6620        if (mAccessibilityDelegate != null) {
6621            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6622        } else {
6623            onInitializeAccessibilityNodeInfoInternal(info);
6624        }
6625    }
6626
6627    /**
6628     * Gets the location of this view in screen coordinates.
6629     *
6630     * @param outRect The output location
6631     * @hide
6632     */
6633    public void getBoundsOnScreen(Rect outRect) {
6634        getBoundsOnScreen(outRect, false);
6635    }
6636
6637    /**
6638     * Gets the location of this view in screen coordinates.
6639     *
6640     * @param outRect The output location
6641     * @param clipToParent Whether to clip child bounds to the parent ones.
6642     * @hide
6643     */
6644    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6645        if (mAttachInfo == null) {
6646            return;
6647        }
6648
6649        RectF position = mAttachInfo.mTmpTransformRect;
6650        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6651
6652        if (!hasIdentityMatrix()) {
6653            getMatrix().mapRect(position);
6654        }
6655
6656        position.offset(mLeft, mTop);
6657
6658        ViewParent parent = mParent;
6659        while (parent instanceof View) {
6660            View parentView = (View) parent;
6661
6662            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6663
6664            if (clipToParent) {
6665                position.left = Math.max(position.left, 0);
6666                position.top = Math.max(position.top, 0);
6667                position.right = Math.min(position.right, parentView.getWidth());
6668                position.bottom = Math.min(position.bottom, parentView.getHeight());
6669            }
6670
6671            if (!parentView.hasIdentityMatrix()) {
6672                parentView.getMatrix().mapRect(position);
6673            }
6674
6675            position.offset(parentView.mLeft, parentView.mTop);
6676
6677            parent = parentView.mParent;
6678        }
6679
6680        if (parent instanceof ViewRootImpl) {
6681            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6682            position.offset(0, -viewRootImpl.mCurScrollY);
6683        }
6684
6685        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6686
6687        outRect.set(Math.round(position.left), Math.round(position.top),
6688                Math.round(position.right), Math.round(position.bottom));
6689    }
6690
6691    /**
6692     * Return the class name of this object to be used for accessibility purposes.
6693     * Subclasses should only override this if they are implementing something that
6694     * should be seen as a completely new class of view when used by accessibility,
6695     * unrelated to the class it is deriving from.  This is used to fill in
6696     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6697     */
6698    public CharSequence getAccessibilityClassName() {
6699        return View.class.getName();
6700    }
6701
6702    /**
6703     * Called when assist structure is being retrieved from a view as part of
6704     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6705     * @param structure Fill in with structured view data.  The default implementation
6706     * fills in all data that can be inferred from the view itself.
6707     */
6708    public void onProvideStructure(ViewStructure structure) {
6709        final int id = mID;
6710        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6711                && (id&0x0000ffff) != 0) {
6712            String pkg, type, entry;
6713            try {
6714                final Resources res = getResources();
6715                entry = res.getResourceEntryName(id);
6716                type = res.getResourceTypeName(id);
6717                pkg = res.getResourcePackageName(id);
6718            } catch (Resources.NotFoundException e) {
6719                entry = type = pkg = null;
6720            }
6721            structure.setId(id, pkg, type, entry);
6722        } else {
6723            structure.setId(id, null, null, null);
6724        }
6725        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6726        if (!hasIdentityMatrix()) {
6727            structure.setTransformation(getMatrix());
6728        }
6729        structure.setElevation(getZ());
6730        structure.setVisibility(getVisibility());
6731        structure.setEnabled(isEnabled());
6732        if (isClickable()) {
6733            structure.setClickable(true);
6734        }
6735        if (isFocusable()) {
6736            structure.setFocusable(true);
6737        }
6738        if (isFocused()) {
6739            structure.setFocused(true);
6740        }
6741        if (isAccessibilityFocused()) {
6742            structure.setAccessibilityFocused(true);
6743        }
6744        if (isSelected()) {
6745            structure.setSelected(true);
6746        }
6747        if (isActivated()) {
6748            structure.setActivated(true);
6749        }
6750        if (isLongClickable()) {
6751            structure.setLongClickable(true);
6752        }
6753        if (this instanceof Checkable) {
6754            structure.setCheckable(true);
6755            if (((Checkable)this).isChecked()) {
6756                structure.setChecked(true);
6757            }
6758        }
6759        if (isContextClickable()) {
6760            structure.setContextClickable(true);
6761        }
6762        structure.setClassName(getAccessibilityClassName().toString());
6763        structure.setContentDescription(getContentDescription());
6764    }
6765
6766    /**
6767     * Called when assist structure is being retrieved from a view as part of
6768     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6769     * generate additional virtual structure under this view.  The defaullt implementation
6770     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6771     * view's virtual accessibility nodes, if any.  You can override this for a more
6772     * optimal implementation providing this data.
6773     */
6774    public void onProvideVirtualStructure(ViewStructure structure) {
6775        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6776        if (provider != null) {
6777            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6778            structure.setChildCount(1);
6779            ViewStructure root = structure.newChild(0);
6780            populateVirtualStructure(root, provider, info);
6781            info.recycle();
6782        }
6783    }
6784
6785    private void populateVirtualStructure(ViewStructure structure,
6786            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6787        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6788                null, null, null);
6789        Rect rect = structure.getTempRect();
6790        info.getBoundsInParent(rect);
6791        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6792        structure.setVisibility(VISIBLE);
6793        structure.setEnabled(info.isEnabled());
6794        if (info.isClickable()) {
6795            structure.setClickable(true);
6796        }
6797        if (info.isFocusable()) {
6798            structure.setFocusable(true);
6799        }
6800        if (info.isFocused()) {
6801            structure.setFocused(true);
6802        }
6803        if (info.isAccessibilityFocused()) {
6804            structure.setAccessibilityFocused(true);
6805        }
6806        if (info.isSelected()) {
6807            structure.setSelected(true);
6808        }
6809        if (info.isLongClickable()) {
6810            structure.setLongClickable(true);
6811        }
6812        if (info.isCheckable()) {
6813            structure.setCheckable(true);
6814            if (info.isChecked()) {
6815                structure.setChecked(true);
6816            }
6817        }
6818        if (info.isContextClickable()) {
6819            structure.setContextClickable(true);
6820        }
6821        CharSequence cname = info.getClassName();
6822        structure.setClassName(cname != null ? cname.toString() : null);
6823        structure.setContentDescription(info.getContentDescription());
6824        if (info.getText() != null || info.getError() != null) {
6825            structure.setText(info.getText(), info.getTextSelectionStart(),
6826                    info.getTextSelectionEnd());
6827        }
6828        final int NCHILDREN = info.getChildCount();
6829        if (NCHILDREN > 0) {
6830            structure.setChildCount(NCHILDREN);
6831            for (int i=0; i<NCHILDREN; i++) {
6832                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6833                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6834                ViewStructure child = structure.newChild(i);
6835                populateVirtualStructure(child, provider, cinfo);
6836                cinfo.recycle();
6837            }
6838        }
6839    }
6840
6841    /**
6842     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6843     * implementation calls {@link #onProvideStructure} and
6844     * {@link #onProvideVirtualStructure}.
6845     */
6846    public void dispatchProvideStructure(ViewStructure structure) {
6847        if (!isAssistBlocked()) {
6848            onProvideStructure(structure);
6849            onProvideVirtualStructure(structure);
6850        } else {
6851            structure.setClassName(getAccessibilityClassName().toString());
6852            structure.setAssistBlocked(true);
6853        }
6854    }
6855
6856    /**
6857     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6858     *
6859     * Note: Called from the default {@link AccessibilityDelegate}.
6860     *
6861     * @hide
6862     */
6863    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6864        if (mAttachInfo == null) {
6865            return;
6866        }
6867
6868        Rect bounds = mAttachInfo.mTmpInvalRect;
6869
6870        getDrawingRect(bounds);
6871        info.setBoundsInParent(bounds);
6872
6873        getBoundsOnScreen(bounds, true);
6874        info.setBoundsInScreen(bounds);
6875
6876        ViewParent parent = getParentForAccessibility();
6877        if (parent instanceof View) {
6878            info.setParent((View) parent);
6879        }
6880
6881        if (mID != View.NO_ID) {
6882            View rootView = getRootView();
6883            if (rootView == null) {
6884                rootView = this;
6885            }
6886
6887            View label = rootView.findLabelForView(this, mID);
6888            if (label != null) {
6889                info.setLabeledBy(label);
6890            }
6891
6892            if ((mAttachInfo.mAccessibilityFetchFlags
6893                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6894                    && Resources.resourceHasPackage(mID)) {
6895                try {
6896                    String viewId = getResources().getResourceName(mID);
6897                    info.setViewIdResourceName(viewId);
6898                } catch (Resources.NotFoundException nfe) {
6899                    /* ignore */
6900                }
6901            }
6902        }
6903
6904        if (mLabelForId != View.NO_ID) {
6905            View rootView = getRootView();
6906            if (rootView == null) {
6907                rootView = this;
6908            }
6909            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6910            if (labeled != null) {
6911                info.setLabelFor(labeled);
6912            }
6913        }
6914
6915        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6916            View rootView = getRootView();
6917            if (rootView == null) {
6918                rootView = this;
6919            }
6920            View next = rootView.findViewInsideOutShouldExist(this,
6921                    mAccessibilityTraversalBeforeId);
6922            if (next != null && next.includeForAccessibility()) {
6923                info.setTraversalBefore(next);
6924            }
6925        }
6926
6927        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6928            View rootView = getRootView();
6929            if (rootView == null) {
6930                rootView = this;
6931            }
6932            View next = rootView.findViewInsideOutShouldExist(this,
6933                    mAccessibilityTraversalAfterId);
6934            if (next != null && next.includeForAccessibility()) {
6935                info.setTraversalAfter(next);
6936            }
6937        }
6938
6939        info.setVisibleToUser(isVisibleToUser());
6940
6941        if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags
6942                & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) {
6943            info.setImportantForAccessibility(isImportantForAccessibility());
6944        } else {
6945            info.setImportantForAccessibility(true);
6946        }
6947
6948        info.setPackageName(mContext.getPackageName());
6949        info.setClassName(getAccessibilityClassName());
6950        info.setContentDescription(getContentDescription());
6951
6952        info.setEnabled(isEnabled());
6953        info.setClickable(isClickable());
6954        info.setFocusable(isFocusable());
6955        info.setFocused(isFocused());
6956        info.setAccessibilityFocused(isAccessibilityFocused());
6957        info.setSelected(isSelected());
6958        info.setLongClickable(isLongClickable());
6959        info.setContextClickable(isContextClickable());
6960        info.setLiveRegion(getAccessibilityLiveRegion());
6961
6962        // TODO: These make sense only if we are in an AdapterView but all
6963        // views can be selected. Maybe from accessibility perspective
6964        // we should report as selectable view in an AdapterView.
6965        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6966        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6967
6968        if (isFocusable()) {
6969            if (isFocused()) {
6970                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6971            } else {
6972                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6973            }
6974        }
6975
6976        if (!isAccessibilityFocused()) {
6977            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6978        } else {
6979            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6980        }
6981
6982        if (isClickable() && isEnabled()) {
6983            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6984        }
6985
6986        if (isLongClickable() && isEnabled()) {
6987            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6988        }
6989
6990        if (isContextClickable() && isEnabled()) {
6991            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6992        }
6993
6994        CharSequence text = getIterableTextForAccessibility();
6995        if (text != null && text.length() > 0) {
6996            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6997
6998            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6999            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
7000            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
7001            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
7002                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
7003                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
7004        }
7005
7006        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
7007        populateAccessibilityNodeInfoDrawingOrderInParent(info);
7008    }
7009
7010    /**
7011     * Determine the order in which this view will be drawn relative to its siblings for a11y
7012     *
7013     * @param info The info whose drawing order should be populated
7014     */
7015    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7016        /*
7017         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7018         * drawing order may not be well-defined, and some Views with custom drawing order may
7019         * not be initialized sufficiently to respond properly getChildDrawingOrder.
7020         */
7021        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7022            info.setDrawingOrder(0);
7023            return;
7024        }
7025        int drawingOrderInParent = 1;
7026        // Iterate up the hierarchy if parents are not important for a11y
7027        View viewAtDrawingLevel = this;
7028        final ViewParent parent = getParentForAccessibility();
7029        while (viewAtDrawingLevel != parent) {
7030            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7031            if (!(currentParent instanceof ViewGroup)) {
7032                // Should only happen for the Decor
7033                drawingOrderInParent = 0;
7034                break;
7035            } else {
7036                final ViewGroup parentGroup = (ViewGroup) currentParent;
7037                final int childCount = parentGroup.getChildCount();
7038                if (childCount > 1) {
7039                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7040                    if (preorderedList != null) {
7041                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7042                        for (int i = 0; i < childDrawIndex; i++) {
7043                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7044                        }
7045                    } else {
7046                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7047                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7048                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7049                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7050                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7051                        if (childDrawIndex != 0) {
7052                            for (int i = 0; i < numChildrenToIterate; i++) {
7053                                final int otherDrawIndex = (customOrder ?
7054                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7055                                if (otherDrawIndex < childDrawIndex) {
7056                                    drawingOrderInParent +=
7057                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7058                                }
7059                            }
7060                        }
7061                    }
7062                }
7063            }
7064            viewAtDrawingLevel = (View) currentParent;
7065        }
7066        info.setDrawingOrder(drawingOrderInParent);
7067    }
7068
7069    private static int numViewsForAccessibility(View view) {
7070        if (view != null) {
7071            if (view.includeForAccessibility()) {
7072                return 1;
7073            } else if (view instanceof ViewGroup) {
7074                return ((ViewGroup) view).getNumChildrenForAccessibility();
7075            }
7076        }
7077        return 0;
7078    }
7079
7080    private View findLabelForView(View view, int labeledId) {
7081        if (mMatchLabelForPredicate == null) {
7082            mMatchLabelForPredicate = new MatchLabelForPredicate();
7083        }
7084        mMatchLabelForPredicate.mLabeledId = labeledId;
7085        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7086    }
7087
7088    /**
7089     * Computes whether this view is visible to the user. Such a view is
7090     * attached, visible, all its predecessors are visible, it is not clipped
7091     * entirely by its predecessors, and has an alpha greater than zero.
7092     *
7093     * @return Whether the view is visible on the screen.
7094     *
7095     * @hide
7096     */
7097    protected boolean isVisibleToUser() {
7098        return isVisibleToUser(null);
7099    }
7100
7101    /**
7102     * Computes whether the given portion of this view is visible to the user.
7103     * Such a view is attached, visible, all its predecessors are visible,
7104     * has an alpha greater than zero, and the specified portion is not
7105     * clipped entirely by its predecessors.
7106     *
7107     * @param boundInView the portion of the view to test; coordinates should be relative; may be
7108     *                    <code>null</code>, and the entire view will be tested in this case.
7109     *                    When <code>true</code> is returned by the function, the actual visible
7110     *                    region will be stored in this parameter; that is, if boundInView is fully
7111     *                    contained within the view, no modification will be made, otherwise regions
7112     *                    outside of the visible area of the view will be clipped.
7113     *
7114     * @return Whether the specified portion of the view is visible on the screen.
7115     *
7116     * @hide
7117     */
7118    protected boolean isVisibleToUser(Rect boundInView) {
7119        if (mAttachInfo != null) {
7120            // Attached to invisible window means this view is not visible.
7121            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
7122                return false;
7123            }
7124            // An invisible predecessor or one with alpha zero means
7125            // that this view is not visible to the user.
7126            Object current = this;
7127            while (current instanceof View) {
7128                View view = (View) current;
7129                // We have attach info so this view is attached and there is no
7130                // need to check whether we reach to ViewRootImpl on the way up.
7131                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
7132                        view.getVisibility() != VISIBLE) {
7133                    return false;
7134                }
7135                current = view.mParent;
7136            }
7137            // Check if the view is entirely covered by its predecessors.
7138            Rect visibleRect = mAttachInfo.mTmpInvalRect;
7139            Point offset = mAttachInfo.mPoint;
7140            if (!getGlobalVisibleRect(visibleRect, offset)) {
7141                return false;
7142            }
7143            // Check if the visible portion intersects the rectangle of interest.
7144            if (boundInView != null) {
7145                visibleRect.offset(-offset.x, -offset.y);
7146                return boundInView.intersect(visibleRect);
7147            }
7148            return true;
7149        }
7150        return false;
7151    }
7152
7153    /**
7154     * Returns the delegate for implementing accessibility support via
7155     * composition. For more details see {@link AccessibilityDelegate}.
7156     *
7157     * @return The delegate, or null if none set.
7158     *
7159     * @hide
7160     */
7161    public AccessibilityDelegate getAccessibilityDelegate() {
7162        return mAccessibilityDelegate;
7163    }
7164
7165    /**
7166     * Sets a delegate for implementing accessibility support via composition
7167     * (as opposed to inheritance). For more details, see
7168     * {@link AccessibilityDelegate}.
7169     * <p>
7170     * <strong>Note:</strong> On platform versions prior to
7171     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
7172     * views in the {@code android.widget.*} package are called <i>before</i>
7173     * host methods. This prevents certain properties such as class name from
7174     * being modified by overriding
7175     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
7176     * as any changes will be overwritten by the host class.
7177     * <p>
7178     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
7179     * methods are called <i>after</i> host methods, which all properties to be
7180     * modified without being overwritten by the host class.
7181     *
7182     * @param delegate the object to which accessibility method calls should be
7183     *                 delegated
7184     * @see AccessibilityDelegate
7185     */
7186    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
7187        mAccessibilityDelegate = delegate;
7188    }
7189
7190    /**
7191     * Gets the provider for managing a virtual view hierarchy rooted at this View
7192     * and reported to {@link android.accessibilityservice.AccessibilityService}s
7193     * that explore the window content.
7194     * <p>
7195     * If this method returns an instance, this instance is responsible for managing
7196     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
7197     * View including the one representing the View itself. Similarly the returned
7198     * instance is responsible for performing accessibility actions on any virtual
7199     * view or the root view itself.
7200     * </p>
7201     * <p>
7202     * If an {@link AccessibilityDelegate} has been specified via calling
7203     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7204     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
7205     * is responsible for handling this call.
7206     * </p>
7207     *
7208     * @return The provider.
7209     *
7210     * @see AccessibilityNodeProvider
7211     */
7212    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
7213        if (mAccessibilityDelegate != null) {
7214            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
7215        } else {
7216            return null;
7217        }
7218    }
7219
7220    /**
7221     * Gets the unique identifier of this view on the screen for accessibility purposes.
7222     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
7223     *
7224     * @return The view accessibility id.
7225     *
7226     * @hide
7227     */
7228    public int getAccessibilityViewId() {
7229        if (mAccessibilityViewId == NO_ID) {
7230            mAccessibilityViewId = sNextAccessibilityViewId++;
7231        }
7232        return mAccessibilityViewId;
7233    }
7234
7235    /**
7236     * Gets the unique identifier of the window in which this View reseides.
7237     *
7238     * @return The window accessibility id.
7239     *
7240     * @hide
7241     */
7242    public int getAccessibilityWindowId() {
7243        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
7244                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
7245    }
7246
7247    /**
7248     * Returns the {@link View}'s content description.
7249     * <p>
7250     * <strong>Note:</strong> Do not override this method, as it will have no
7251     * effect on the content description presented to accessibility services.
7252     * You must call {@link #setContentDescription(CharSequence)} to modify the
7253     * content description.
7254     *
7255     * @return the content description
7256     * @see #setContentDescription(CharSequence)
7257     * @attr ref android.R.styleable#View_contentDescription
7258     */
7259    @ViewDebug.ExportedProperty(category = "accessibility")
7260    public CharSequence getContentDescription() {
7261        return mContentDescription;
7262    }
7263
7264    /**
7265     * Sets the {@link View}'s content description.
7266     * <p>
7267     * A content description briefly describes the view and is primarily used
7268     * for accessibility support to determine how a view should be presented to
7269     * the user. In the case of a view with no textual representation, such as
7270     * {@link android.widget.ImageButton}, a useful content description
7271     * explains what the view does. For example, an image button with a phone
7272     * icon that is used to place a call may use "Call" as its content
7273     * description. An image of a floppy disk that is used to save a file may
7274     * use "Save".
7275     *
7276     * @param contentDescription The content description.
7277     * @see #getContentDescription()
7278     * @attr ref android.R.styleable#View_contentDescription
7279     */
7280    @RemotableViewMethod
7281    public void setContentDescription(CharSequence contentDescription) {
7282        if (mContentDescription == null) {
7283            if (contentDescription == null) {
7284                return;
7285            }
7286        } else if (mContentDescription.equals(contentDescription)) {
7287            return;
7288        }
7289        mContentDescription = contentDescription;
7290        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
7291        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
7292            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
7293            notifySubtreeAccessibilityStateChangedIfNeeded();
7294        } else {
7295            notifyViewAccessibilityStateChangedIfNeeded(
7296                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
7297        }
7298    }
7299
7300    /**
7301     * Sets the id of a view before which this one is visited in accessibility traversal.
7302     * A screen-reader must visit the content of this view before the content of the one
7303     * it precedes. For example, if view B is set to be before view A, then a screen-reader
7304     * will traverse the entire content of B before traversing the entire content of A,
7305     * regardles of what traversal strategy it is using.
7306     * <p>
7307     * Views that do not have specified before/after relationships are traversed in order
7308     * determined by the screen-reader.
7309     * </p>
7310     * <p>
7311     * Setting that this view is before a view that is not important for accessibility
7312     * or if this view is not important for accessibility will have no effect as the
7313     * screen-reader is not aware of unimportant views.
7314     * </p>
7315     *
7316     * @param beforeId The id of a view this one precedes in accessibility traversal.
7317     *
7318     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
7319     *
7320     * @see #setImportantForAccessibility(int)
7321     */
7322    @RemotableViewMethod
7323    public void setAccessibilityTraversalBefore(int beforeId) {
7324        if (mAccessibilityTraversalBeforeId == beforeId) {
7325            return;
7326        }
7327        mAccessibilityTraversalBeforeId = beforeId;
7328        notifyViewAccessibilityStateChangedIfNeeded(
7329                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7330    }
7331
7332    /**
7333     * Gets the id of a view before which this one is visited in accessibility traversal.
7334     *
7335     * @return The id of a view this one precedes in accessibility traversal if
7336     *         specified, otherwise {@link #NO_ID}.
7337     *
7338     * @see #setAccessibilityTraversalBefore(int)
7339     */
7340    public int getAccessibilityTraversalBefore() {
7341        return mAccessibilityTraversalBeforeId;
7342    }
7343
7344    /**
7345     * Sets the id of a view after which this one is visited in accessibility traversal.
7346     * A screen-reader must visit the content of the other view before the content of this
7347     * one. For example, if view B is set to be after view A, then a screen-reader
7348     * will traverse the entire content of A before traversing the entire content of B,
7349     * regardles of what traversal strategy it is using.
7350     * <p>
7351     * Views that do not have specified before/after relationships are traversed in order
7352     * determined by the screen-reader.
7353     * </p>
7354     * <p>
7355     * Setting that this view is after a view that is not important for accessibility
7356     * or if this view is not important for accessibility will have no effect as the
7357     * screen-reader is not aware of unimportant views.
7358     * </p>
7359     *
7360     * @param afterId The id of a view this one succedees in accessibility traversal.
7361     *
7362     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
7363     *
7364     * @see #setImportantForAccessibility(int)
7365     */
7366    @RemotableViewMethod
7367    public void setAccessibilityTraversalAfter(int afterId) {
7368        if (mAccessibilityTraversalAfterId == afterId) {
7369            return;
7370        }
7371        mAccessibilityTraversalAfterId = afterId;
7372        notifyViewAccessibilityStateChangedIfNeeded(
7373                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7374    }
7375
7376    /**
7377     * Gets the id of a view after which this one is visited in accessibility traversal.
7378     *
7379     * @return The id of a view this one succeedes in accessibility traversal if
7380     *         specified, otherwise {@link #NO_ID}.
7381     *
7382     * @see #setAccessibilityTraversalAfter(int)
7383     */
7384    public int getAccessibilityTraversalAfter() {
7385        return mAccessibilityTraversalAfterId;
7386    }
7387
7388    /**
7389     * Gets the id of a view for which this view serves as a label for
7390     * accessibility purposes.
7391     *
7392     * @return The labeled view id.
7393     */
7394    @ViewDebug.ExportedProperty(category = "accessibility")
7395    public int getLabelFor() {
7396        return mLabelForId;
7397    }
7398
7399    /**
7400     * Sets the id of a view for which this view serves as a label for
7401     * accessibility purposes.
7402     *
7403     * @param id The labeled view id.
7404     */
7405    @RemotableViewMethod
7406    public void setLabelFor(@IdRes int id) {
7407        if (mLabelForId == id) {
7408            return;
7409        }
7410        mLabelForId = id;
7411        if (mLabelForId != View.NO_ID
7412                && mID == View.NO_ID) {
7413            mID = generateViewId();
7414        }
7415        notifyViewAccessibilityStateChangedIfNeeded(
7416                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7417    }
7418
7419    /**
7420     * Invoked whenever this view loses focus, either by losing window focus or by losing
7421     * focus within its window. This method can be used to clear any state tied to the
7422     * focus. For instance, if a button is held pressed with the trackball and the window
7423     * loses focus, this method can be used to cancel the press.
7424     *
7425     * Subclasses of View overriding this method should always call super.onFocusLost().
7426     *
7427     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7428     * @see #onWindowFocusChanged(boolean)
7429     *
7430     * @hide pending API council approval
7431     */
7432    @CallSuper
7433    protected void onFocusLost() {
7434        resetPressedState();
7435    }
7436
7437    private void resetPressedState() {
7438        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7439            return;
7440        }
7441
7442        if (isPressed()) {
7443            setPressed(false);
7444
7445            if (!mHasPerformedLongPress) {
7446                removeLongPressCallback();
7447            }
7448        }
7449    }
7450
7451    /**
7452     * Returns true if this view has focus
7453     *
7454     * @return True if this view has focus, false otherwise.
7455     */
7456    @ViewDebug.ExportedProperty(category = "focus")
7457    public boolean isFocused() {
7458        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7459    }
7460
7461    /**
7462     * Find the view in the hierarchy rooted at this view that currently has
7463     * focus.
7464     *
7465     * @return The view that currently has focus, or null if no focused view can
7466     *         be found.
7467     */
7468    public View findFocus() {
7469        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7470    }
7471
7472    /**
7473     * Indicates whether this view is one of the set of scrollable containers in
7474     * its window.
7475     *
7476     * @return whether this view is one of the set of scrollable containers in
7477     * its window
7478     *
7479     * @attr ref android.R.styleable#View_isScrollContainer
7480     */
7481    public boolean isScrollContainer() {
7482        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7483    }
7484
7485    /**
7486     * Change whether this view is one of the set of scrollable containers in
7487     * its window.  This will be used to determine whether the window can
7488     * resize or must pan when a soft input area is open -- scrollable
7489     * containers allow the window to use resize mode since the container
7490     * will appropriately shrink.
7491     *
7492     * @attr ref android.R.styleable#View_isScrollContainer
7493     */
7494    public void setScrollContainer(boolean isScrollContainer) {
7495        if (isScrollContainer) {
7496            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7497                mAttachInfo.mScrollContainers.add(this);
7498                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7499            }
7500            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7501        } else {
7502            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7503                mAttachInfo.mScrollContainers.remove(this);
7504            }
7505            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7506        }
7507    }
7508
7509    /**
7510     * Returns the quality of the drawing cache.
7511     *
7512     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7513     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7514     *
7515     * @see #setDrawingCacheQuality(int)
7516     * @see #setDrawingCacheEnabled(boolean)
7517     * @see #isDrawingCacheEnabled()
7518     *
7519     * @attr ref android.R.styleable#View_drawingCacheQuality
7520     */
7521    @DrawingCacheQuality
7522    public int getDrawingCacheQuality() {
7523        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7524    }
7525
7526    /**
7527     * Set the drawing cache quality of this view. This value is used only when the
7528     * drawing cache is enabled
7529     *
7530     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7531     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7532     *
7533     * @see #getDrawingCacheQuality()
7534     * @see #setDrawingCacheEnabled(boolean)
7535     * @see #isDrawingCacheEnabled()
7536     *
7537     * @attr ref android.R.styleable#View_drawingCacheQuality
7538     */
7539    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7540        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7541    }
7542
7543    /**
7544     * Returns whether the screen should remain on, corresponding to the current
7545     * value of {@link #KEEP_SCREEN_ON}.
7546     *
7547     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7548     *
7549     * @see #setKeepScreenOn(boolean)
7550     *
7551     * @attr ref android.R.styleable#View_keepScreenOn
7552     */
7553    public boolean getKeepScreenOn() {
7554        return (mViewFlags & KEEP_SCREEN_ON) != 0;
7555    }
7556
7557    /**
7558     * Controls whether the screen should remain on, modifying the
7559     * value of {@link #KEEP_SCREEN_ON}.
7560     *
7561     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7562     *
7563     * @see #getKeepScreenOn()
7564     *
7565     * @attr ref android.R.styleable#View_keepScreenOn
7566     */
7567    public void setKeepScreenOn(boolean keepScreenOn) {
7568        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7569    }
7570
7571    /**
7572     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7573     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7574     *
7575     * @attr ref android.R.styleable#View_nextFocusLeft
7576     */
7577    public int getNextFocusLeftId() {
7578        return mNextFocusLeftId;
7579    }
7580
7581    /**
7582     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7583     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7584     * decide automatically.
7585     *
7586     * @attr ref android.R.styleable#View_nextFocusLeft
7587     */
7588    public void setNextFocusLeftId(int nextFocusLeftId) {
7589        mNextFocusLeftId = nextFocusLeftId;
7590    }
7591
7592    /**
7593     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7594     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7595     *
7596     * @attr ref android.R.styleable#View_nextFocusRight
7597     */
7598    public int getNextFocusRightId() {
7599        return mNextFocusRightId;
7600    }
7601
7602    /**
7603     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7604     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7605     * decide automatically.
7606     *
7607     * @attr ref android.R.styleable#View_nextFocusRight
7608     */
7609    public void setNextFocusRightId(int nextFocusRightId) {
7610        mNextFocusRightId = nextFocusRightId;
7611    }
7612
7613    /**
7614     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7615     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7616     *
7617     * @attr ref android.R.styleable#View_nextFocusUp
7618     */
7619    public int getNextFocusUpId() {
7620        return mNextFocusUpId;
7621    }
7622
7623    /**
7624     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7625     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7626     * decide automatically.
7627     *
7628     * @attr ref android.R.styleable#View_nextFocusUp
7629     */
7630    public void setNextFocusUpId(int nextFocusUpId) {
7631        mNextFocusUpId = nextFocusUpId;
7632    }
7633
7634    /**
7635     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7636     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7637     *
7638     * @attr ref android.R.styleable#View_nextFocusDown
7639     */
7640    public int getNextFocusDownId() {
7641        return mNextFocusDownId;
7642    }
7643
7644    /**
7645     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7646     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7647     * decide automatically.
7648     *
7649     * @attr ref android.R.styleable#View_nextFocusDown
7650     */
7651    public void setNextFocusDownId(int nextFocusDownId) {
7652        mNextFocusDownId = nextFocusDownId;
7653    }
7654
7655    /**
7656     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7657     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7658     *
7659     * @attr ref android.R.styleable#View_nextFocusForward
7660     */
7661    public int getNextFocusForwardId() {
7662        return mNextFocusForwardId;
7663    }
7664
7665    /**
7666     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7667     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7668     * decide automatically.
7669     *
7670     * @attr ref android.R.styleable#View_nextFocusForward
7671     */
7672    public void setNextFocusForwardId(int nextFocusForwardId) {
7673        mNextFocusForwardId = nextFocusForwardId;
7674    }
7675
7676    /**
7677     * Returns the visibility of this view and all of its ancestors
7678     *
7679     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7680     */
7681    public boolean isShown() {
7682        View current = this;
7683        //noinspection ConstantConditions
7684        do {
7685            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7686                return false;
7687            }
7688            ViewParent parent = current.mParent;
7689            if (parent == null) {
7690                return false; // We are not attached to the view root
7691            }
7692            if (!(parent instanceof View)) {
7693                return true;
7694            }
7695            current = (View) parent;
7696        } while (current != null);
7697
7698        return false;
7699    }
7700
7701    /**
7702     * Called by the view hierarchy when the content insets for a window have
7703     * changed, to allow it to adjust its content to fit within those windows.
7704     * The content insets tell you the space that the status bar, input method,
7705     * and other system windows infringe on the application's window.
7706     *
7707     * <p>You do not normally need to deal with this function, since the default
7708     * window decoration given to applications takes care of applying it to the
7709     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7710     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7711     * and your content can be placed under those system elements.  You can then
7712     * use this method within your view hierarchy if you have parts of your UI
7713     * which you would like to ensure are not being covered.
7714     *
7715     * <p>The default implementation of this method simply applies the content
7716     * insets to the view's padding, consuming that content (modifying the
7717     * insets to be 0), and returning true.  This behavior is off by default, but can
7718     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7719     *
7720     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7721     * insets object is propagated down the hierarchy, so any changes made to it will
7722     * be seen by all following views (including potentially ones above in
7723     * the hierarchy since this is a depth-first traversal).  The first view
7724     * that returns true will abort the entire traversal.
7725     *
7726     * <p>The default implementation works well for a situation where it is
7727     * used with a container that covers the entire window, allowing it to
7728     * apply the appropriate insets to its content on all edges.  If you need
7729     * a more complicated layout (such as two different views fitting system
7730     * windows, one on the top of the window, and one on the bottom),
7731     * you can override the method and handle the insets however you would like.
7732     * Note that the insets provided by the framework are always relative to the
7733     * far edges of the window, not accounting for the location of the called view
7734     * within that window.  (In fact when this method is called you do not yet know
7735     * where the layout will place the view, as it is done before layout happens.)
7736     *
7737     * <p>Note: unlike many View methods, there is no dispatch phase to this
7738     * call.  If you are overriding it in a ViewGroup and want to allow the
7739     * call to continue to your children, you must be sure to call the super
7740     * implementation.
7741     *
7742     * <p>Here is a sample layout that makes use of fitting system windows
7743     * to have controls for a video view placed inside of the window decorations
7744     * that it hides and shows.  This can be used with code like the second
7745     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7746     *
7747     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7748     *
7749     * @param insets Current content insets of the window.  Prior to
7750     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7751     * the insets or else you and Android will be unhappy.
7752     *
7753     * @return {@code true} if this view applied the insets and it should not
7754     * continue propagating further down the hierarchy, {@code false} otherwise.
7755     * @see #getFitsSystemWindows()
7756     * @see #setFitsSystemWindows(boolean)
7757     * @see #setSystemUiVisibility(int)
7758     *
7759     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7760     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7761     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7762     * to implement handling their own insets.
7763     */
7764    protected boolean fitSystemWindows(Rect insets) {
7765        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7766            if (insets == null) {
7767                // Null insets by definition have already been consumed.
7768                // This call cannot apply insets since there are none to apply,
7769                // so return false.
7770                return false;
7771            }
7772            // If we're not in the process of dispatching the newer apply insets call,
7773            // that means we're not in the compatibility path. Dispatch into the newer
7774            // apply insets path and take things from there.
7775            try {
7776                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7777                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7778            } finally {
7779                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7780            }
7781        } else {
7782            // We're being called from the newer apply insets path.
7783            // Perform the standard fallback behavior.
7784            return fitSystemWindowsInt(insets);
7785        }
7786    }
7787
7788    private boolean fitSystemWindowsInt(Rect insets) {
7789        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7790            mUserPaddingStart = UNDEFINED_PADDING;
7791            mUserPaddingEnd = UNDEFINED_PADDING;
7792            Rect localInsets = sThreadLocal.get();
7793            if (localInsets == null) {
7794                localInsets = new Rect();
7795                sThreadLocal.set(localInsets);
7796            }
7797            boolean res = computeFitSystemWindows(insets, localInsets);
7798            mUserPaddingLeftInitial = localInsets.left;
7799            mUserPaddingRightInitial = localInsets.right;
7800            internalSetPadding(localInsets.left, localInsets.top,
7801                    localInsets.right, localInsets.bottom);
7802            return res;
7803        }
7804        return false;
7805    }
7806
7807    /**
7808     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7809     *
7810     * <p>This method should be overridden by views that wish to apply a policy different from or
7811     * in addition to the default behavior. Clients that wish to force a view subtree
7812     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7813     *
7814     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7815     * it will be called during dispatch instead of this method. The listener may optionally
7816     * call this method from its own implementation if it wishes to apply the view's default
7817     * insets policy in addition to its own.</p>
7818     *
7819     * <p>Implementations of this method should either return the insets parameter unchanged
7820     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7821     * that this view applied itself. This allows new inset types added in future platform
7822     * versions to pass through existing implementations unchanged without being erroneously
7823     * consumed.</p>
7824     *
7825     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7826     * property is set then the view will consume the system window insets and apply them
7827     * as padding for the view.</p>
7828     *
7829     * @param insets Insets to apply
7830     * @return The supplied insets with any applied insets consumed
7831     */
7832    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7833        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7834            // We weren't called from within a direct call to fitSystemWindows,
7835            // call into it as a fallback in case we're in a class that overrides it
7836            // and has logic to perform.
7837            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7838                return insets.consumeSystemWindowInsets();
7839            }
7840        } else {
7841            // We were called from within a direct call to fitSystemWindows.
7842            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7843                return insets.consumeSystemWindowInsets();
7844            }
7845        }
7846        return insets;
7847    }
7848
7849    /**
7850     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7851     * window insets to this view. The listener's
7852     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7853     * method will be called instead of the view's
7854     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7855     *
7856     * @param listener Listener to set
7857     *
7858     * @see #onApplyWindowInsets(WindowInsets)
7859     */
7860    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7861        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7862    }
7863
7864    /**
7865     * Request to apply the given window insets to this view or another view in its subtree.
7866     *
7867     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7868     * obscured by window decorations or overlays. This can include the status and navigation bars,
7869     * action bars, input methods and more. New inset categories may be added in the future.
7870     * The method returns the insets provided minus any that were applied by this view or its
7871     * children.</p>
7872     *
7873     * <p>Clients wishing to provide custom behavior should override the
7874     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7875     * {@link OnApplyWindowInsetsListener} via the
7876     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7877     * method.</p>
7878     *
7879     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7880     * </p>
7881     *
7882     * @param insets Insets to apply
7883     * @return The provided insets minus the insets that were consumed
7884     */
7885    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7886        try {
7887            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7888            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7889                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7890            } else {
7891                return onApplyWindowInsets(insets);
7892            }
7893        } finally {
7894            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7895        }
7896    }
7897
7898    /**
7899     * Compute the view's coordinate within the surface.
7900     *
7901     * <p>Computes the coordinates of this view in its surface. The argument
7902     * must be an array of two integers. After the method returns, the array
7903     * contains the x and y location in that order.</p>
7904     * @hide
7905     * @param location an array of two integers in which to hold the coordinates
7906     */
7907    public void getLocationInSurface(@Size(2) int[] location) {
7908        getLocationInWindow(location);
7909        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
7910            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
7911            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
7912        }
7913    }
7914
7915    /**
7916     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7917     * only available if the view is attached.
7918     *
7919     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7920     */
7921    public WindowInsets getRootWindowInsets() {
7922        if (mAttachInfo != null) {
7923            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7924        }
7925        return null;
7926    }
7927
7928    /**
7929     * @hide Compute the insets that should be consumed by this view and the ones
7930     * that should propagate to those under it.
7931     */
7932    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7933        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7934                || mAttachInfo == null
7935                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7936                        && !mAttachInfo.mOverscanRequested)) {
7937            outLocalInsets.set(inoutInsets);
7938            inoutInsets.set(0, 0, 0, 0);
7939            return true;
7940        } else {
7941            // The application wants to take care of fitting system window for
7942            // the content...  however we still need to take care of any overscan here.
7943            final Rect overscan = mAttachInfo.mOverscanInsets;
7944            outLocalInsets.set(overscan);
7945            inoutInsets.left -= overscan.left;
7946            inoutInsets.top -= overscan.top;
7947            inoutInsets.right -= overscan.right;
7948            inoutInsets.bottom -= overscan.bottom;
7949            return false;
7950        }
7951    }
7952
7953    /**
7954     * Compute insets that should be consumed by this view and the ones that should propagate
7955     * to those under it.
7956     *
7957     * @param in Insets currently being processed by this View, likely received as a parameter
7958     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7959     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7960     *                       by this view
7961     * @return Insets that should be passed along to views under this one
7962     */
7963    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7964        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7965                || mAttachInfo == null
7966                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7967            outLocalInsets.set(in.getSystemWindowInsets());
7968            return in.consumeSystemWindowInsets();
7969        } else {
7970            outLocalInsets.set(0, 0, 0, 0);
7971            return in;
7972        }
7973    }
7974
7975    /**
7976     * Sets whether or not this view should account for system screen decorations
7977     * such as the status bar and inset its content; that is, controlling whether
7978     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7979     * executed.  See that method for more details.
7980     *
7981     * <p>Note that if you are providing your own implementation of
7982     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7983     * flag to true -- your implementation will be overriding the default
7984     * implementation that checks this flag.
7985     *
7986     * @param fitSystemWindows If true, then the default implementation of
7987     * {@link #fitSystemWindows(Rect)} will be executed.
7988     *
7989     * @attr ref android.R.styleable#View_fitsSystemWindows
7990     * @see #getFitsSystemWindows()
7991     * @see #fitSystemWindows(Rect)
7992     * @see #setSystemUiVisibility(int)
7993     */
7994    public void setFitsSystemWindows(boolean fitSystemWindows) {
7995        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7996    }
7997
7998    /**
7999     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
8000     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
8001     * will be executed.
8002     *
8003     * @return {@code true} if the default implementation of
8004     * {@link #fitSystemWindows(Rect)} will be executed.
8005     *
8006     * @attr ref android.R.styleable#View_fitsSystemWindows
8007     * @see #setFitsSystemWindows(boolean)
8008     * @see #fitSystemWindows(Rect)
8009     * @see #setSystemUiVisibility(int)
8010     */
8011    @ViewDebug.ExportedProperty
8012    public boolean getFitsSystemWindows() {
8013        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8014    }
8015
8016    /** @hide */
8017    public boolean fitsSystemWindows() {
8018        return getFitsSystemWindows();
8019    }
8020
8021    /**
8022     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8023     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8024     */
8025    public void requestFitSystemWindows() {
8026        if (mParent != null) {
8027            mParent.requestFitSystemWindows();
8028        }
8029    }
8030
8031    /**
8032     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8033     */
8034    public void requestApplyInsets() {
8035        requestFitSystemWindows();
8036    }
8037
8038    /**
8039     * For use by PhoneWindow to make its own system window fitting optional.
8040     * @hide
8041     */
8042    public void makeOptionalFitsSystemWindows() {
8043        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8044    }
8045
8046    /**
8047     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8048     * treat them as such.
8049     * @hide
8050     */
8051    public void getOutsets(Rect outOutsetRect) {
8052        if (mAttachInfo != null) {
8053            outOutsetRect.set(mAttachInfo.mOutsets);
8054        } else {
8055            outOutsetRect.setEmpty();
8056        }
8057    }
8058
8059    /**
8060     * Returns the visibility status for this view.
8061     *
8062     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8063     * @attr ref android.R.styleable#View_visibility
8064     */
8065    @ViewDebug.ExportedProperty(mapping = {
8066        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8067        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8068        @ViewDebug.IntToString(from = GONE,      to = "GONE")
8069    })
8070    @Visibility
8071    public int getVisibility() {
8072        return mViewFlags & VISIBILITY_MASK;
8073    }
8074
8075    /**
8076     * Set the enabled state of this view.
8077     *
8078     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8079     * @attr ref android.R.styleable#View_visibility
8080     */
8081    @RemotableViewMethod
8082    public void setVisibility(@Visibility int visibility) {
8083        setFlags(visibility, VISIBILITY_MASK);
8084    }
8085
8086    /**
8087     * Returns the enabled status for this view. The interpretation of the
8088     * enabled state varies by subclass.
8089     *
8090     * @return True if this view is enabled, false otherwise.
8091     */
8092    @ViewDebug.ExportedProperty
8093    public boolean isEnabled() {
8094        return (mViewFlags & ENABLED_MASK) == ENABLED;
8095    }
8096
8097    /**
8098     * Set the enabled state of this view. The interpretation of the enabled
8099     * state varies by subclass.
8100     *
8101     * @param enabled True if this view is enabled, false otherwise.
8102     */
8103    @RemotableViewMethod
8104    public void setEnabled(boolean enabled) {
8105        if (enabled == isEnabled()) return;
8106
8107        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
8108
8109        /*
8110         * The View most likely has to change its appearance, so refresh
8111         * the drawable state.
8112         */
8113        refreshDrawableState();
8114
8115        // Invalidate too, since the default behavior for views is to be
8116        // be drawn at 50% alpha rather than to change the drawable.
8117        invalidate(true);
8118
8119        if (!enabled) {
8120            cancelPendingInputEvents();
8121        }
8122    }
8123
8124    /**
8125     * Set whether this view can receive the focus.
8126     *
8127     * Setting this to false will also ensure that this view is not focusable
8128     * in touch mode.
8129     *
8130     * @param focusable If true, this view can receive the focus.
8131     *
8132     * @see #setFocusableInTouchMode(boolean)
8133     * @attr ref android.R.styleable#View_focusable
8134     */
8135    public void setFocusable(boolean focusable) {
8136        if (!focusable) {
8137            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
8138        }
8139        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
8140    }
8141
8142    /**
8143     * Set whether this view can receive focus while in touch mode.
8144     *
8145     * Setting this to true will also ensure that this view is focusable.
8146     *
8147     * @param focusableInTouchMode If true, this view can receive the focus while
8148     *   in touch mode.
8149     *
8150     * @see #setFocusable(boolean)
8151     * @attr ref android.R.styleable#View_focusableInTouchMode
8152     */
8153    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
8154        // Focusable in touch mode should always be set before the focusable flag
8155        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
8156        // which, in touch mode, will not successfully request focus on this view
8157        // because the focusable in touch mode flag is not set
8158        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
8159        if (focusableInTouchMode) {
8160            setFlags(FOCUSABLE, FOCUSABLE_MASK);
8161        }
8162    }
8163
8164    /**
8165     * Set whether this view should have sound effects enabled for events such as
8166     * clicking and touching.
8167     *
8168     * <p>You may wish to disable sound effects for a view if you already play sounds,
8169     * for instance, a dial key that plays dtmf tones.
8170     *
8171     * @param soundEffectsEnabled whether sound effects are enabled for this view.
8172     * @see #isSoundEffectsEnabled()
8173     * @see #playSoundEffect(int)
8174     * @attr ref android.R.styleable#View_soundEffectsEnabled
8175     */
8176    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
8177        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
8178    }
8179
8180    /**
8181     * @return whether this view should have sound effects enabled for events such as
8182     *     clicking and touching.
8183     *
8184     * @see #setSoundEffectsEnabled(boolean)
8185     * @see #playSoundEffect(int)
8186     * @attr ref android.R.styleable#View_soundEffectsEnabled
8187     */
8188    @ViewDebug.ExportedProperty
8189    public boolean isSoundEffectsEnabled() {
8190        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
8191    }
8192
8193    /**
8194     * Set whether this view should have haptic feedback for events such as
8195     * long presses.
8196     *
8197     * <p>You may wish to disable haptic feedback if your view already controls
8198     * its own haptic feedback.
8199     *
8200     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
8201     * @see #isHapticFeedbackEnabled()
8202     * @see #performHapticFeedback(int)
8203     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8204     */
8205    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
8206        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
8207    }
8208
8209    /**
8210     * @return whether this view should have haptic feedback enabled for events
8211     * long presses.
8212     *
8213     * @see #setHapticFeedbackEnabled(boolean)
8214     * @see #performHapticFeedback(int)
8215     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8216     */
8217    @ViewDebug.ExportedProperty
8218    public boolean isHapticFeedbackEnabled() {
8219        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
8220    }
8221
8222    /**
8223     * Returns the layout direction for this view.
8224     *
8225     * @return One of {@link #LAYOUT_DIRECTION_LTR},
8226     *   {@link #LAYOUT_DIRECTION_RTL},
8227     *   {@link #LAYOUT_DIRECTION_INHERIT} or
8228     *   {@link #LAYOUT_DIRECTION_LOCALE}.
8229     *
8230     * @attr ref android.R.styleable#View_layoutDirection
8231     *
8232     * @hide
8233     */
8234    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8235        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
8236        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
8237        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
8238        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
8239    })
8240    @LayoutDir
8241    public int getRawLayoutDirection() {
8242        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
8243    }
8244
8245    /**
8246     * Set the layout direction for this view. This will propagate a reset of layout direction
8247     * resolution to the view's children and resolve layout direction for this view.
8248     *
8249     * @param layoutDirection the layout direction to set. Should be one of:
8250     *
8251     * {@link #LAYOUT_DIRECTION_LTR},
8252     * {@link #LAYOUT_DIRECTION_RTL},
8253     * {@link #LAYOUT_DIRECTION_INHERIT},
8254     * {@link #LAYOUT_DIRECTION_LOCALE}.
8255     *
8256     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
8257     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
8258     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
8259     *
8260     * @attr ref android.R.styleable#View_layoutDirection
8261     */
8262    @RemotableViewMethod
8263    public void setLayoutDirection(@LayoutDir int layoutDirection) {
8264        if (getRawLayoutDirection() != layoutDirection) {
8265            // Reset the current layout direction and the resolved one
8266            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
8267            resetRtlProperties();
8268            // Set the new layout direction (filtered)
8269            mPrivateFlags2 |=
8270                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
8271            // We need to resolve all RTL properties as they all depend on layout direction
8272            resolveRtlPropertiesIfNeeded();
8273            requestLayout();
8274            invalidate(true);
8275        }
8276    }
8277
8278    /**
8279     * Returns the resolved layout direction for this view.
8280     *
8281     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
8282     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
8283     *
8284     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
8285     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
8286     *
8287     * @attr ref android.R.styleable#View_layoutDirection
8288     */
8289    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8290        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
8291        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
8292    })
8293    @ResolvedLayoutDir
8294    public int getLayoutDirection() {
8295        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
8296        if (targetSdkVersion < JELLY_BEAN_MR1) {
8297            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
8298            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
8299        }
8300        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
8301                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
8302    }
8303
8304    /**
8305     * Indicates whether or not this view's layout is right-to-left. This is resolved from
8306     * layout attribute and/or the inherited value from the parent
8307     *
8308     * @return true if the layout is right-to-left.
8309     *
8310     * @hide
8311     */
8312    @ViewDebug.ExportedProperty(category = "layout")
8313    public boolean isLayoutRtl() {
8314        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
8315    }
8316
8317    /**
8318     * Indicates whether the view is currently tracking transient state that the
8319     * app should not need to concern itself with saving and restoring, but that
8320     * the framework should take special note to preserve when possible.
8321     *
8322     * <p>A view with transient state cannot be trivially rebound from an external
8323     * data source, such as an adapter binding item views in a list. This may be
8324     * because the view is performing an animation, tracking user selection
8325     * of content, or similar.</p>
8326     *
8327     * @return true if the view has transient state
8328     */
8329    @ViewDebug.ExportedProperty(category = "layout")
8330    public boolean hasTransientState() {
8331        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
8332    }
8333
8334    /**
8335     * Set whether this view is currently tracking transient state that the
8336     * framework should attempt to preserve when possible. This flag is reference counted,
8337     * so every call to setHasTransientState(true) should be paired with a later call
8338     * to setHasTransientState(false).
8339     *
8340     * <p>A view with transient state cannot be trivially rebound from an external
8341     * data source, such as an adapter binding item views in a list. This may be
8342     * because the view is performing an animation, tracking user selection
8343     * of content, or similar.</p>
8344     *
8345     * @param hasTransientState true if this view has transient state
8346     */
8347    public void setHasTransientState(boolean hasTransientState) {
8348        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
8349                mTransientStateCount - 1;
8350        if (mTransientStateCount < 0) {
8351            mTransientStateCount = 0;
8352            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
8353                    "unmatched pair of setHasTransientState calls");
8354        } else if ((hasTransientState && mTransientStateCount == 1) ||
8355                (!hasTransientState && mTransientStateCount == 0)) {
8356            // update flag if we've just incremented up from 0 or decremented down to 0
8357            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
8358                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
8359            if (mParent != null) {
8360                try {
8361                    mParent.childHasTransientStateChanged(this, hasTransientState);
8362                } catch (AbstractMethodError e) {
8363                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8364                            " does not fully implement ViewParent", e);
8365                }
8366            }
8367        }
8368    }
8369
8370    /**
8371     * Returns true if this view is currently attached to a window.
8372     */
8373    public boolean isAttachedToWindow() {
8374        return mAttachInfo != null;
8375    }
8376
8377    /**
8378     * Returns true if this view has been through at least one layout since it
8379     * was last attached to or detached from a window.
8380     */
8381    public boolean isLaidOut() {
8382        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
8383    }
8384
8385    /**
8386     * If this view doesn't do any drawing on its own, set this flag to
8387     * allow further optimizations. By default, this flag is not set on
8388     * View, but could be set on some View subclasses such as ViewGroup.
8389     *
8390     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8391     * you should clear this flag.
8392     *
8393     * @param willNotDraw whether or not this View draw on its own
8394     */
8395    public void setWillNotDraw(boolean willNotDraw) {
8396        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8397    }
8398
8399    /**
8400     * Returns whether or not this View draws on its own.
8401     *
8402     * @return true if this view has nothing to draw, false otherwise
8403     */
8404    @ViewDebug.ExportedProperty(category = "drawing")
8405    public boolean willNotDraw() {
8406        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8407    }
8408
8409    /**
8410     * When a View's drawing cache is enabled, drawing is redirected to an
8411     * offscreen bitmap. Some views, like an ImageView, must be able to
8412     * bypass this mechanism if they already draw a single bitmap, to avoid
8413     * unnecessary usage of the memory.
8414     *
8415     * @param willNotCacheDrawing true if this view does not cache its
8416     *        drawing, false otherwise
8417     */
8418    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8419        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8420    }
8421
8422    /**
8423     * Returns whether or not this View can cache its drawing or not.
8424     *
8425     * @return true if this view does not cache its drawing, false otherwise
8426     */
8427    @ViewDebug.ExportedProperty(category = "drawing")
8428    public boolean willNotCacheDrawing() {
8429        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8430    }
8431
8432    /**
8433     * Indicates whether this view reacts to click events or not.
8434     *
8435     * @return true if the view is clickable, false otherwise
8436     *
8437     * @see #setClickable(boolean)
8438     * @attr ref android.R.styleable#View_clickable
8439     */
8440    @ViewDebug.ExportedProperty
8441    public boolean isClickable() {
8442        return (mViewFlags & CLICKABLE) == CLICKABLE;
8443    }
8444
8445    /**
8446     * Enables or disables click events for this view. When a view
8447     * is clickable it will change its state to "pressed" on every click.
8448     * Subclasses should set the view clickable to visually react to
8449     * user's clicks.
8450     *
8451     * @param clickable true to make the view clickable, false otherwise
8452     *
8453     * @see #isClickable()
8454     * @attr ref android.R.styleable#View_clickable
8455     */
8456    public void setClickable(boolean clickable) {
8457        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8458    }
8459
8460    /**
8461     * Indicates whether this view reacts to long click events or not.
8462     *
8463     * @return true if the view is long clickable, false otherwise
8464     *
8465     * @see #setLongClickable(boolean)
8466     * @attr ref android.R.styleable#View_longClickable
8467     */
8468    public boolean isLongClickable() {
8469        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8470    }
8471
8472    /**
8473     * Enables or disables long click events for this view. When a view is long
8474     * clickable it reacts to the user holding down the button for a longer
8475     * duration than a tap. This event can either launch the listener or a
8476     * context menu.
8477     *
8478     * @param longClickable true to make the view long clickable, false otherwise
8479     * @see #isLongClickable()
8480     * @attr ref android.R.styleable#View_longClickable
8481     */
8482    public void setLongClickable(boolean longClickable) {
8483        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8484    }
8485
8486    /**
8487     * Indicates whether this view reacts to context clicks or not.
8488     *
8489     * @return true if the view is context clickable, false otherwise
8490     * @see #setContextClickable(boolean)
8491     * @attr ref android.R.styleable#View_contextClickable
8492     */
8493    public boolean isContextClickable() {
8494        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8495    }
8496
8497    /**
8498     * Enables or disables context clicking for this view. This event can launch the listener.
8499     *
8500     * @param contextClickable true to make the view react to a context click, false otherwise
8501     * @see #isContextClickable()
8502     * @attr ref android.R.styleable#View_contextClickable
8503     */
8504    public void setContextClickable(boolean contextClickable) {
8505        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8506    }
8507
8508    /**
8509     * Sets the pressed state for this view and provides a touch coordinate for
8510     * animation hinting.
8511     *
8512     * @param pressed Pass true to set the View's internal state to "pressed",
8513     *            or false to reverts the View's internal state from a
8514     *            previously set "pressed" state.
8515     * @param x The x coordinate of the touch that caused the press
8516     * @param y The y coordinate of the touch that caused the press
8517     */
8518    private void setPressed(boolean pressed, float x, float y) {
8519        if (pressed) {
8520            drawableHotspotChanged(x, y);
8521        }
8522
8523        setPressed(pressed);
8524    }
8525
8526    /**
8527     * Sets the pressed state for this view.
8528     *
8529     * @see #isClickable()
8530     * @see #setClickable(boolean)
8531     *
8532     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8533     *        the View's internal state from a previously set "pressed" state.
8534     */
8535    public void setPressed(boolean pressed) {
8536        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8537
8538        if (pressed) {
8539            mPrivateFlags |= PFLAG_PRESSED;
8540        } else {
8541            mPrivateFlags &= ~PFLAG_PRESSED;
8542        }
8543
8544        if (needsRefresh) {
8545            refreshDrawableState();
8546        }
8547        dispatchSetPressed(pressed);
8548    }
8549
8550    /**
8551     * Dispatch setPressed to all of this View's children.
8552     *
8553     * @see #setPressed(boolean)
8554     *
8555     * @param pressed The new pressed state
8556     */
8557    protected void dispatchSetPressed(boolean pressed) {
8558    }
8559
8560    /**
8561     * Indicates whether the view is currently in pressed state. Unless
8562     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8563     * the pressed state.
8564     *
8565     * @see #setPressed(boolean)
8566     * @see #isClickable()
8567     * @see #setClickable(boolean)
8568     *
8569     * @return true if the view is currently pressed, false otherwise
8570     */
8571    @ViewDebug.ExportedProperty
8572    public boolean isPressed() {
8573        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8574    }
8575
8576    /**
8577     * @hide
8578     * Indicates whether this view will participate in data collection through
8579     * {@link ViewStructure}.  If true, it will not provide any data
8580     * for itself or its children.  If false, the normal data collection will be allowed.
8581     *
8582     * @return Returns false if assist data collection is not blocked, else true.
8583     *
8584     * @see #setAssistBlocked(boolean)
8585     * @attr ref android.R.styleable#View_assistBlocked
8586     */
8587    public boolean isAssistBlocked() {
8588        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8589    }
8590
8591    /**
8592     * @hide
8593     * Controls whether assist data collection from this view and its children is enabled
8594     * (that is, whether {@link #onProvideStructure} and
8595     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8596     * allowing normal assist collection.  Setting this to false will disable assist collection.
8597     *
8598     * @param enabled Set to true to <em>disable</em> assist data collection, or false
8599     * (the default) to allow it.
8600     *
8601     * @see #isAssistBlocked()
8602     * @see #onProvideStructure
8603     * @see #onProvideVirtualStructure
8604     * @attr ref android.R.styleable#View_assistBlocked
8605     */
8606    public void setAssistBlocked(boolean enabled) {
8607        if (enabled) {
8608            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8609        } else {
8610            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8611        }
8612    }
8613
8614    /**
8615     * Indicates whether this view will save its state (that is,
8616     * whether its {@link #onSaveInstanceState} method will be called).
8617     *
8618     * @return Returns true if the view state saving is enabled, else false.
8619     *
8620     * @see #setSaveEnabled(boolean)
8621     * @attr ref android.R.styleable#View_saveEnabled
8622     */
8623    public boolean isSaveEnabled() {
8624        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8625    }
8626
8627    /**
8628     * Controls whether the saving of this view's state is
8629     * enabled (that is, whether its {@link #onSaveInstanceState} method
8630     * will be called).  Note that even if freezing is enabled, the
8631     * view still must have an id assigned to it (via {@link #setId(int)})
8632     * for its state to be saved.  This flag can only disable the
8633     * saving of this view; any child views may still have their state saved.
8634     *
8635     * @param enabled Set to false to <em>disable</em> state saving, or true
8636     * (the default) to allow it.
8637     *
8638     * @see #isSaveEnabled()
8639     * @see #setId(int)
8640     * @see #onSaveInstanceState()
8641     * @attr ref android.R.styleable#View_saveEnabled
8642     */
8643    public void setSaveEnabled(boolean enabled) {
8644        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8645    }
8646
8647    /**
8648     * Gets whether the framework should discard touches when the view's
8649     * window is obscured by another visible window.
8650     * Refer to the {@link View} security documentation for more details.
8651     *
8652     * @return True if touch filtering is enabled.
8653     *
8654     * @see #setFilterTouchesWhenObscured(boolean)
8655     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8656     */
8657    @ViewDebug.ExportedProperty
8658    public boolean getFilterTouchesWhenObscured() {
8659        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8660    }
8661
8662    /**
8663     * Sets whether the framework should discard touches when the view's
8664     * window is obscured by another visible window.
8665     * Refer to the {@link View} security documentation for more details.
8666     *
8667     * @param enabled True if touch filtering should be enabled.
8668     *
8669     * @see #getFilterTouchesWhenObscured
8670     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8671     */
8672    public void setFilterTouchesWhenObscured(boolean enabled) {
8673        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8674                FILTER_TOUCHES_WHEN_OBSCURED);
8675    }
8676
8677    /**
8678     * Indicates whether the entire hierarchy under this view will save its
8679     * state when a state saving traversal occurs from its parent.  The default
8680     * is true; if false, these views will not be saved unless
8681     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8682     *
8683     * @return Returns true if the view state saving from parent is enabled, else false.
8684     *
8685     * @see #setSaveFromParentEnabled(boolean)
8686     */
8687    public boolean isSaveFromParentEnabled() {
8688        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8689    }
8690
8691    /**
8692     * Controls whether the entire hierarchy under this view will save its
8693     * state when a state saving traversal occurs from its parent.  The default
8694     * is true; if false, these views will not be saved unless
8695     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8696     *
8697     * @param enabled Set to false to <em>disable</em> state saving, or true
8698     * (the default) to allow it.
8699     *
8700     * @see #isSaveFromParentEnabled()
8701     * @see #setId(int)
8702     * @see #onSaveInstanceState()
8703     */
8704    public void setSaveFromParentEnabled(boolean enabled) {
8705        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8706    }
8707
8708
8709    /**
8710     * Returns whether this View is able to take focus.
8711     *
8712     * @return True if this view can take focus, or false otherwise.
8713     * @attr ref android.R.styleable#View_focusable
8714     */
8715    @ViewDebug.ExportedProperty(category = "focus")
8716    public final boolean isFocusable() {
8717        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8718    }
8719
8720    /**
8721     * When a view is focusable, it may not want to take focus when in touch mode.
8722     * For example, a button would like focus when the user is navigating via a D-pad
8723     * so that the user can click on it, but once the user starts touching the screen,
8724     * the button shouldn't take focus
8725     * @return Whether the view is focusable in touch mode.
8726     * @attr ref android.R.styleable#View_focusableInTouchMode
8727     */
8728    @ViewDebug.ExportedProperty
8729    public final boolean isFocusableInTouchMode() {
8730        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8731    }
8732
8733    /**
8734     * Find the nearest view in the specified direction that can take focus.
8735     * This does not actually give focus to that view.
8736     *
8737     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8738     *
8739     * @return The nearest focusable in the specified direction, or null if none
8740     *         can be found.
8741     */
8742    public View focusSearch(@FocusRealDirection int direction) {
8743        if (mParent != null) {
8744            return mParent.focusSearch(this, direction);
8745        } else {
8746            return null;
8747        }
8748    }
8749
8750    /**
8751     * This method is the last chance for the focused view and its ancestors to
8752     * respond to an arrow key. This is called when the focused view did not
8753     * consume the key internally, nor could the view system find a new view in
8754     * the requested direction to give focus to.
8755     *
8756     * @param focused The currently focused view.
8757     * @param direction The direction focus wants to move. One of FOCUS_UP,
8758     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8759     * @return True if the this view consumed this unhandled move.
8760     */
8761    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8762        return false;
8763    }
8764
8765    /**
8766     * If a user manually specified the next view id for a particular direction,
8767     * use the root to look up the view.
8768     * @param root The root view of the hierarchy containing this view.
8769     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8770     * or FOCUS_BACKWARD.
8771     * @return The user specified next view, or null if there is none.
8772     */
8773    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8774        switch (direction) {
8775            case FOCUS_LEFT:
8776                if (mNextFocusLeftId == View.NO_ID) return null;
8777                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8778            case FOCUS_RIGHT:
8779                if (mNextFocusRightId == View.NO_ID) return null;
8780                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8781            case FOCUS_UP:
8782                if (mNextFocusUpId == View.NO_ID) return null;
8783                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8784            case FOCUS_DOWN:
8785                if (mNextFocusDownId == View.NO_ID) return null;
8786                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8787            case FOCUS_FORWARD:
8788                if (mNextFocusForwardId == View.NO_ID) return null;
8789                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8790            case FOCUS_BACKWARD: {
8791                if (mID == View.NO_ID) return null;
8792                final int id = mID;
8793                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8794                    @Override
8795                    public boolean apply(View t) {
8796                        return t.mNextFocusForwardId == id;
8797                    }
8798                });
8799            }
8800        }
8801        return null;
8802    }
8803
8804    private View findViewInsideOutShouldExist(View root, int id) {
8805        if (mMatchIdPredicate == null) {
8806            mMatchIdPredicate = new MatchIdPredicate();
8807        }
8808        mMatchIdPredicate.mId = id;
8809        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8810        if (result == null) {
8811            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8812        }
8813        return result;
8814    }
8815
8816    /**
8817     * Find and return all focusable views that are descendants of this view,
8818     * possibly including this view if it is focusable itself.
8819     *
8820     * @param direction The direction of the focus
8821     * @return A list of focusable views
8822     */
8823    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8824        ArrayList<View> result = new ArrayList<View>(24);
8825        addFocusables(result, direction);
8826        return result;
8827    }
8828
8829    /**
8830     * Add any focusable views that are descendants of this view (possibly
8831     * including this view if it is focusable itself) to views.  If we are in touch mode,
8832     * only add views that are also focusable in touch mode.
8833     *
8834     * @param views Focusable views found so far
8835     * @param direction The direction of the focus
8836     */
8837    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8838        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
8839    }
8840
8841    /**
8842     * Adds any focusable views that are descendants of this view (possibly
8843     * including this view if it is focusable itself) to views. This method
8844     * adds all focusable views regardless if we are in touch mode or
8845     * only views focusable in touch mode if we are in touch mode or
8846     * only views that can take accessibility focus if accessibility is enabled
8847     * depending on the focusable mode parameter.
8848     *
8849     * @param views Focusable views found so far or null if all we are interested is
8850     *        the number of focusables.
8851     * @param direction The direction of the focus.
8852     * @param focusableMode The type of focusables to be added.
8853     *
8854     * @see #FOCUSABLES_ALL
8855     * @see #FOCUSABLES_TOUCH_MODE
8856     */
8857    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8858            @FocusableMode int focusableMode) {
8859        if (views == null) {
8860            return;
8861        }
8862        if (!isFocusable()) {
8863            return;
8864        }
8865        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8866                && !isFocusableInTouchMode()) {
8867            return;
8868        }
8869        views.add(this);
8870    }
8871
8872    /**
8873     * Finds the Views that contain given text. The containment is case insensitive.
8874     * The search is performed by either the text that the View renders or the content
8875     * description that describes the view for accessibility purposes and the view does
8876     * not render or both. Clients can specify how the search is to be performed via
8877     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8878     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8879     *
8880     * @param outViews The output list of matching Views.
8881     * @param searched The text to match against.
8882     *
8883     * @see #FIND_VIEWS_WITH_TEXT
8884     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8885     * @see #setContentDescription(CharSequence)
8886     */
8887    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8888            @FindViewFlags int flags) {
8889        if (getAccessibilityNodeProvider() != null) {
8890            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8891                outViews.add(this);
8892            }
8893        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8894                && (searched != null && searched.length() > 0)
8895                && (mContentDescription != null && mContentDescription.length() > 0)) {
8896            String searchedLowerCase = searched.toString().toLowerCase();
8897            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8898            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8899                outViews.add(this);
8900            }
8901        }
8902    }
8903
8904    /**
8905     * Find and return all touchable views that are descendants of this view,
8906     * possibly including this view if it is touchable itself.
8907     *
8908     * @return A list of touchable views
8909     */
8910    public ArrayList<View> getTouchables() {
8911        ArrayList<View> result = new ArrayList<View>();
8912        addTouchables(result);
8913        return result;
8914    }
8915
8916    /**
8917     * Add any touchable views that are descendants of this view (possibly
8918     * including this view if it is touchable itself) to views.
8919     *
8920     * @param views Touchable views found so far
8921     */
8922    public void addTouchables(ArrayList<View> views) {
8923        final int viewFlags = mViewFlags;
8924
8925        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8926                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8927                && (viewFlags & ENABLED_MASK) == ENABLED) {
8928            views.add(this);
8929        }
8930    }
8931
8932    /**
8933     * Returns whether this View is accessibility focused.
8934     *
8935     * @return True if this View is accessibility focused.
8936     */
8937    public boolean isAccessibilityFocused() {
8938        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8939    }
8940
8941    /**
8942     * Call this to try to give accessibility focus to this view.
8943     *
8944     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8945     * returns false or the view is no visible or the view already has accessibility
8946     * focus.
8947     *
8948     * See also {@link #focusSearch(int)}, which is what you call to say that you
8949     * have focus, and you want your parent to look for the next one.
8950     *
8951     * @return Whether this view actually took accessibility focus.
8952     *
8953     * @hide
8954     */
8955    public boolean requestAccessibilityFocus() {
8956        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8957        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8958            return false;
8959        }
8960        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8961            return false;
8962        }
8963        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8964            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8965            ViewRootImpl viewRootImpl = getViewRootImpl();
8966            if (viewRootImpl != null) {
8967                viewRootImpl.setAccessibilityFocus(this, null);
8968            }
8969            invalidate();
8970            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8971            return true;
8972        }
8973        return false;
8974    }
8975
8976    /**
8977     * Call this to try to clear accessibility focus of this view.
8978     *
8979     * See also {@link #focusSearch(int)}, which is what you call to say that you
8980     * have focus, and you want your parent to look for the next one.
8981     *
8982     * @hide
8983     */
8984    public void clearAccessibilityFocus() {
8985        clearAccessibilityFocusNoCallbacks(0);
8986
8987        // Clear the global reference of accessibility focus if this view or
8988        // any of its descendants had accessibility focus. This will NOT send
8989        // an event or update internal state if focus is cleared from a
8990        // descendant view, which may leave views in inconsistent states.
8991        final ViewRootImpl viewRootImpl = getViewRootImpl();
8992        if (viewRootImpl != null) {
8993            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8994            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8995                viewRootImpl.setAccessibilityFocus(null, null);
8996            }
8997        }
8998    }
8999
9000    private void sendAccessibilityHoverEvent(int eventType) {
9001        // Since we are not delivering to a client accessibility events from not
9002        // important views (unless the clinet request that) we need to fire the
9003        // event from the deepest view exposed to the client. As a consequence if
9004        // the user crosses a not exposed view the client will see enter and exit
9005        // of the exposed predecessor followed by and enter and exit of that same
9006        // predecessor when entering and exiting the not exposed descendant. This
9007        // is fine since the client has a clear idea which view is hovered at the
9008        // price of a couple more events being sent. This is a simple and
9009        // working solution.
9010        View source = this;
9011        while (true) {
9012            if (source.includeForAccessibility()) {
9013                source.sendAccessibilityEvent(eventType);
9014                return;
9015            }
9016            ViewParent parent = source.getParent();
9017            if (parent instanceof View) {
9018                source = (View) parent;
9019            } else {
9020                return;
9021            }
9022        }
9023    }
9024
9025    /**
9026     * Clears accessibility focus without calling any callback methods
9027     * normally invoked in {@link #clearAccessibilityFocus()}. This method
9028     * is used separately from that one for clearing accessibility focus when
9029     * giving this focus to another view.
9030     *
9031     * @param action The action, if any, that led to focus being cleared. Set to
9032     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
9033     * the window.
9034     */
9035    void clearAccessibilityFocusNoCallbacks(int action) {
9036        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
9037            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
9038            invalidate();
9039            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9040                AccessibilityEvent event = AccessibilityEvent.obtain(
9041                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
9042                event.setAction(action);
9043                if (mAccessibilityDelegate != null) {
9044                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
9045                } else {
9046                    sendAccessibilityEventUnchecked(event);
9047                }
9048            }
9049        }
9050    }
9051
9052    /**
9053     * Call this to try to give focus to a specific view or to one of its
9054     * descendants.
9055     *
9056     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9057     * false), or if it is focusable and it is not focusable in touch mode
9058     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9059     *
9060     * See also {@link #focusSearch(int)}, which is what you call to say that you
9061     * have focus, and you want your parent to look for the next one.
9062     *
9063     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
9064     * {@link #FOCUS_DOWN} and <code>null</code>.
9065     *
9066     * @return Whether this view or one of its descendants actually took focus.
9067     */
9068    public final boolean requestFocus() {
9069        return requestFocus(View.FOCUS_DOWN);
9070    }
9071
9072    /**
9073     * Call this to try to give focus to a specific view or to one of its
9074     * descendants and give it a hint about what direction focus is heading.
9075     *
9076     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9077     * false), or if it is focusable and it is not focusable in touch mode
9078     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9079     *
9080     * See also {@link #focusSearch(int)}, which is what you call to say that you
9081     * have focus, and you want your parent to look for the next one.
9082     *
9083     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
9084     * <code>null</code> set for the previously focused rectangle.
9085     *
9086     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9087     * @return Whether this view or one of its descendants actually took focus.
9088     */
9089    public final boolean requestFocus(int direction) {
9090        return requestFocus(direction, null);
9091    }
9092
9093    /**
9094     * Call this to try to give focus to a specific view or to one of its descendants
9095     * and give it hints about the direction and a specific rectangle that the focus
9096     * is coming from.  The rectangle can help give larger views a finer grained hint
9097     * about where focus is coming from, and therefore, where to show selection, or
9098     * forward focus change internally.
9099     *
9100     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9101     * false), or if it is focusable and it is not focusable in touch mode
9102     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9103     *
9104     * A View will not take focus if it is not visible.
9105     *
9106     * A View will not take focus if one of its parents has
9107     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
9108     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
9109     *
9110     * See also {@link #focusSearch(int)}, which is what you call to say that you
9111     * have focus, and you want your parent to look for the next one.
9112     *
9113     * You may wish to override this method if your custom {@link View} has an internal
9114     * {@link View} that it wishes to forward the request to.
9115     *
9116     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9117     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
9118     *        to give a finer grained hint about where focus is coming from.  May be null
9119     *        if there is no hint.
9120     * @return Whether this view or one of its descendants actually took focus.
9121     */
9122    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
9123        return requestFocusNoSearch(direction, previouslyFocusedRect);
9124    }
9125
9126    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
9127        // need to be focusable
9128        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
9129                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9130            return false;
9131        }
9132
9133        // need to be focusable in touch mode if in touch mode
9134        if (isInTouchMode() &&
9135            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
9136               return false;
9137        }
9138
9139        // need to not have any parents blocking us
9140        if (hasAncestorThatBlocksDescendantFocus()) {
9141            return false;
9142        }
9143
9144        handleFocusGainInternal(direction, previouslyFocusedRect);
9145        return true;
9146    }
9147
9148    /**
9149     * Call this to try to give focus to a specific view or to one of its descendants. This is a
9150     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
9151     * touch mode to request focus when they are touched.
9152     *
9153     * @return Whether this view or one of its descendants actually took focus.
9154     *
9155     * @see #isInTouchMode()
9156     *
9157     */
9158    public final boolean requestFocusFromTouch() {
9159        // Leave touch mode if we need to
9160        if (isInTouchMode()) {
9161            ViewRootImpl viewRoot = getViewRootImpl();
9162            if (viewRoot != null) {
9163                viewRoot.ensureTouchMode(false);
9164            }
9165        }
9166        return requestFocus(View.FOCUS_DOWN);
9167    }
9168
9169    /**
9170     * @return Whether any ancestor of this view blocks descendant focus.
9171     */
9172    private boolean hasAncestorThatBlocksDescendantFocus() {
9173        final boolean focusableInTouchMode = isFocusableInTouchMode();
9174        ViewParent ancestor = mParent;
9175        while (ancestor instanceof ViewGroup) {
9176            final ViewGroup vgAncestor = (ViewGroup) ancestor;
9177            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
9178                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
9179                return true;
9180            } else {
9181                ancestor = vgAncestor.getParent();
9182            }
9183        }
9184        return false;
9185    }
9186
9187    /**
9188     * Gets the mode for determining whether this View is important for accessibility
9189     * which is if it fires accessibility events and if it is reported to
9190     * accessibility services that query the screen.
9191     *
9192     * @return The mode for determining whether a View is important for accessibility.
9193     *
9194     * @attr ref android.R.styleable#View_importantForAccessibility
9195     *
9196     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9197     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9198     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9199     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9200     */
9201    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
9202            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
9203            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
9204            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
9205            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
9206                    to = "noHideDescendants")
9207        })
9208    public int getImportantForAccessibility() {
9209        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9210                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9211    }
9212
9213    /**
9214     * Sets the live region mode for this view. This indicates to accessibility
9215     * services whether they should automatically notify the user about changes
9216     * to the view's content description or text, or to the content descriptions
9217     * or text of the view's children (where applicable).
9218     * <p>
9219     * For example, in a login screen with a TextView that displays an "incorrect
9220     * password" notification, that view should be marked as a live region with
9221     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9222     * <p>
9223     * To disable change notifications for this view, use
9224     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
9225     * mode for most views.
9226     * <p>
9227     * To indicate that the user should be notified of changes, use
9228     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9229     * <p>
9230     * If the view's changes should interrupt ongoing speech and notify the user
9231     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
9232     *
9233     * @param mode The live region mode for this view, one of:
9234     *        <ul>
9235     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
9236     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
9237     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
9238     *        </ul>
9239     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9240     */
9241    public void setAccessibilityLiveRegion(int mode) {
9242        if (mode != getAccessibilityLiveRegion()) {
9243            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9244            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
9245                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9246            notifyViewAccessibilityStateChangedIfNeeded(
9247                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9248        }
9249    }
9250
9251    /**
9252     * Gets the live region mode for this View.
9253     *
9254     * @return The live region mode for the view.
9255     *
9256     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9257     *
9258     * @see #setAccessibilityLiveRegion(int)
9259     */
9260    public int getAccessibilityLiveRegion() {
9261        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
9262                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
9263    }
9264
9265    /**
9266     * Sets how to determine whether this view is important for accessibility
9267     * which is if it fires accessibility events and if it is reported to
9268     * accessibility services that query the screen.
9269     *
9270     * @param mode How to determine whether this view is important for accessibility.
9271     *
9272     * @attr ref android.R.styleable#View_importantForAccessibility
9273     *
9274     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9275     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9276     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9277     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9278     */
9279    public void setImportantForAccessibility(int mode) {
9280        final int oldMode = getImportantForAccessibility();
9281        if (mode != oldMode) {
9282            final boolean hideDescendants =
9283                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
9284
9285            // If this node or its descendants are no longer important, try to
9286            // clear accessibility focus.
9287            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
9288                final View focusHost = findAccessibilityFocusHost(hideDescendants);
9289                if (focusHost != null) {
9290                    focusHost.clearAccessibilityFocus();
9291                }
9292            }
9293
9294            // If we're moving between AUTO and another state, we might not need
9295            // to send a subtree changed notification. We'll store the computed
9296            // importance, since we'll need to check it later to make sure.
9297            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
9298                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
9299            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
9300            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9301            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
9302                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9303            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
9304                notifySubtreeAccessibilityStateChangedIfNeeded();
9305            } else {
9306                notifyViewAccessibilityStateChangedIfNeeded(
9307                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9308            }
9309        }
9310    }
9311
9312    /**
9313     * Returns the view within this view's hierarchy that is hosting
9314     * accessibility focus.
9315     *
9316     * @param searchDescendants whether to search for focus in descendant views
9317     * @return the view hosting accessibility focus, or {@code null}
9318     */
9319    private View findAccessibilityFocusHost(boolean searchDescendants) {
9320        if (isAccessibilityFocusedViewOrHost()) {
9321            return this;
9322        }
9323
9324        if (searchDescendants) {
9325            final ViewRootImpl viewRoot = getViewRootImpl();
9326            if (viewRoot != null) {
9327                final View focusHost = viewRoot.getAccessibilityFocusedHost();
9328                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9329                    return focusHost;
9330                }
9331            }
9332        }
9333
9334        return null;
9335    }
9336
9337    /**
9338     * Computes whether this view should be exposed for accessibility. In
9339     * general, views that are interactive or provide information are exposed
9340     * while views that serve only as containers are hidden.
9341     * <p>
9342     * If an ancestor of this view has importance
9343     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
9344     * returns <code>false</code>.
9345     * <p>
9346     * Otherwise, the value is computed according to the view's
9347     * {@link #getImportantForAccessibility()} value:
9348     * <ol>
9349     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
9350     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
9351     * </code>
9352     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
9353     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
9354     * view satisfies any of the following:
9355     * <ul>
9356     * <li>Is actionable, e.g. {@link #isClickable()},
9357     * {@link #isLongClickable()}, or {@link #isFocusable()}
9358     * <li>Has an {@link AccessibilityDelegate}
9359     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
9360     * {@link OnKeyListener}, etc.
9361     * <li>Is an accessibility live region, e.g.
9362     * {@link #getAccessibilityLiveRegion()} is not
9363     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
9364     * </ul>
9365     * </ol>
9366     *
9367     * @return Whether the view is exposed for accessibility.
9368     * @see #setImportantForAccessibility(int)
9369     * @see #getImportantForAccessibility()
9370     */
9371    public boolean isImportantForAccessibility() {
9372        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9373                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9374        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
9375                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9376            return false;
9377        }
9378
9379        // Check parent mode to ensure we're not hidden.
9380        ViewParent parent = mParent;
9381        while (parent instanceof View) {
9382            if (((View) parent).getImportantForAccessibility()
9383                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9384                return false;
9385            }
9386            parent = parent.getParent();
9387        }
9388
9389        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
9390                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
9391                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
9392    }
9393
9394    /**
9395     * Gets the parent for accessibility purposes. Note that the parent for
9396     * accessibility is not necessary the immediate parent. It is the first
9397     * predecessor that is important for accessibility.
9398     *
9399     * @return The parent for accessibility purposes.
9400     */
9401    public ViewParent getParentForAccessibility() {
9402        if (mParent instanceof View) {
9403            View parentView = (View) mParent;
9404            if (parentView.includeForAccessibility()) {
9405                return mParent;
9406            } else {
9407                return mParent.getParentForAccessibility();
9408            }
9409        }
9410        return null;
9411    }
9412
9413    /**
9414     * Adds the children of this View relevant for accessibility to the given list
9415     * as output. Since some Views are not important for accessibility the added
9416     * child views are not necessarily direct children of this view, rather they are
9417     * the first level of descendants important for accessibility.
9418     *
9419     * @param outChildren The output list that will receive children for accessibility.
9420     */
9421    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
9422
9423    }
9424
9425    /**
9426     * Whether to regard this view for accessibility. A view is regarded for
9427     * accessibility if it is important for accessibility or the querying
9428     * accessibility service has explicitly requested that view not
9429     * important for accessibility are regarded.
9430     *
9431     * @return Whether to regard the view for accessibility.
9432     *
9433     * @hide
9434     */
9435    public boolean includeForAccessibility() {
9436        if (mAttachInfo != null) {
9437            return (mAttachInfo.mAccessibilityFetchFlags
9438                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
9439                    || isImportantForAccessibility();
9440        }
9441        return false;
9442    }
9443
9444    /**
9445     * Returns whether the View is considered actionable from
9446     * accessibility perspective. Such view are important for
9447     * accessibility.
9448     *
9449     * @return True if the view is actionable for accessibility.
9450     *
9451     * @hide
9452     */
9453    public boolean isActionableForAccessibility() {
9454        return (isClickable() || isLongClickable() || isFocusable());
9455    }
9456
9457    /**
9458     * Returns whether the View has registered callbacks which makes it
9459     * important for accessibility.
9460     *
9461     * @return True if the view is actionable for accessibility.
9462     */
9463    private boolean hasListenersForAccessibility() {
9464        ListenerInfo info = getListenerInfo();
9465        return mTouchDelegate != null || info.mOnKeyListener != null
9466                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
9467                || info.mOnHoverListener != null || info.mOnDragListener != null;
9468    }
9469
9470    /**
9471     * Notifies that the accessibility state of this view changed. The change
9472     * is local to this view and does not represent structural changes such
9473     * as children and parent. For example, the view became focusable. The
9474     * notification is at at most once every
9475     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9476     * to avoid unnecessary load to the system. Also once a view has a pending
9477     * notification this method is a NOP until the notification has been sent.
9478     *
9479     * @hide
9480     */
9481    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
9482        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9483            return;
9484        }
9485        if (mSendViewStateChangedAccessibilityEvent == null) {
9486            mSendViewStateChangedAccessibilityEvent =
9487                    new SendViewStateChangedAccessibilityEvent();
9488        }
9489        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9490    }
9491
9492    /**
9493     * Notifies that the accessibility state of this view changed. The change
9494     * is *not* local to this view and does represent structural changes such
9495     * as children and parent. For example, the view size changed. The
9496     * notification is at at most once every
9497     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9498     * to avoid unnecessary load to the system. Also once a view has a pending
9499     * notification this method is a NOP until the notification has been sent.
9500     *
9501     * @hide
9502     */
9503    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9504        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9505            return;
9506        }
9507        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9508            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9509            if (mParent != null) {
9510                try {
9511                    mParent.notifySubtreeAccessibilityStateChanged(
9512                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9513                } catch (AbstractMethodError e) {
9514                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9515                            " does not fully implement ViewParent", e);
9516                }
9517            }
9518        }
9519    }
9520
9521    /**
9522     * Change the visibility of the View without triggering any other changes. This is
9523     * important for transitions, where visibility changes should not adjust focus or
9524     * trigger a new layout. This is only used when the visibility has already been changed
9525     * and we need a transient value during an animation. When the animation completes,
9526     * the original visibility value is always restored.
9527     *
9528     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9529     * @hide
9530     */
9531    public void setTransitionVisibility(@Visibility int visibility) {
9532        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9533    }
9534
9535    /**
9536     * Reset the flag indicating the accessibility state of the subtree rooted
9537     * at this view changed.
9538     */
9539    void resetSubtreeAccessibilityStateChanged() {
9540        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9541    }
9542
9543    /**
9544     * Report an accessibility action to this view's parents for delegated processing.
9545     *
9546     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9547     * call this method to delegate an accessibility action to a supporting parent. If the parent
9548     * returns true from its
9549     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9550     * method this method will return true to signify that the action was consumed.</p>
9551     *
9552     * <p>This method is useful for implementing nested scrolling child views. If
9553     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9554     * a custom view implementation may invoke this method to allow a parent to consume the
9555     * scroll first. If this method returns true the custom view should skip its own scrolling
9556     * behavior.</p>
9557     *
9558     * @param action Accessibility action to delegate
9559     * @param arguments Optional action arguments
9560     * @return true if the action was consumed by a parent
9561     */
9562    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9563        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9564            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9565                return true;
9566            }
9567        }
9568        return false;
9569    }
9570
9571    /**
9572     * Performs the specified accessibility action on the view. For
9573     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9574     * <p>
9575     * If an {@link AccessibilityDelegate} has been specified via calling
9576     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9577     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9578     * is responsible for handling this call.
9579     * </p>
9580     *
9581     * <p>The default implementation will delegate
9582     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9583     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9584     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9585     *
9586     * @param action The action to perform.
9587     * @param arguments Optional action arguments.
9588     * @return Whether the action was performed.
9589     */
9590    public boolean performAccessibilityAction(int action, Bundle arguments) {
9591      if (mAccessibilityDelegate != null) {
9592          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9593      } else {
9594          return performAccessibilityActionInternal(action, arguments);
9595      }
9596    }
9597
9598   /**
9599    * @see #performAccessibilityAction(int, Bundle)
9600    *
9601    * Note: Called from the default {@link AccessibilityDelegate}.
9602    *
9603    * @hide
9604    */
9605    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9606        if (isNestedScrollingEnabled()
9607                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9608                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9609                || action == R.id.accessibilityActionScrollUp
9610                || action == R.id.accessibilityActionScrollLeft
9611                || action == R.id.accessibilityActionScrollDown
9612                || action == R.id.accessibilityActionScrollRight)) {
9613            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9614                return true;
9615            }
9616        }
9617
9618        switch (action) {
9619            case AccessibilityNodeInfo.ACTION_CLICK: {
9620                if (isClickable()) {
9621                    performClick();
9622                    return true;
9623                }
9624            } break;
9625            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9626                if (isLongClickable()) {
9627                    performLongClick();
9628                    return true;
9629                }
9630            } break;
9631            case AccessibilityNodeInfo.ACTION_FOCUS: {
9632                if (!hasFocus()) {
9633                    // Get out of touch mode since accessibility
9634                    // wants to move focus around.
9635                    getViewRootImpl().ensureTouchMode(false);
9636                    return requestFocus();
9637                }
9638            } break;
9639            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9640                if (hasFocus()) {
9641                    clearFocus();
9642                    return !isFocused();
9643                }
9644            } break;
9645            case AccessibilityNodeInfo.ACTION_SELECT: {
9646                if (!isSelected()) {
9647                    setSelected(true);
9648                    return isSelected();
9649                }
9650            } break;
9651            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9652                if (isSelected()) {
9653                    setSelected(false);
9654                    return !isSelected();
9655                }
9656            } break;
9657            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9658                if (!isAccessibilityFocused()) {
9659                    return requestAccessibilityFocus();
9660                }
9661            } break;
9662            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9663                if (isAccessibilityFocused()) {
9664                    clearAccessibilityFocus();
9665                    return true;
9666                }
9667            } break;
9668            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9669                if (arguments != null) {
9670                    final int granularity = arguments.getInt(
9671                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9672                    final boolean extendSelection = arguments.getBoolean(
9673                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9674                    return traverseAtGranularity(granularity, true, extendSelection);
9675                }
9676            } break;
9677            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9678                if (arguments != null) {
9679                    final int granularity = arguments.getInt(
9680                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9681                    final boolean extendSelection = arguments.getBoolean(
9682                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9683                    return traverseAtGranularity(granularity, false, extendSelection);
9684                }
9685            } break;
9686            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9687                CharSequence text = getIterableTextForAccessibility();
9688                if (text == null) {
9689                    return false;
9690                }
9691                final int start = (arguments != null) ? arguments.getInt(
9692                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9693                final int end = (arguments != null) ? arguments.getInt(
9694                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9695                // Only cursor position can be specified (selection length == 0)
9696                if ((getAccessibilitySelectionStart() != start
9697                        || getAccessibilitySelectionEnd() != end)
9698                        && (start == end)) {
9699                    setAccessibilitySelection(start, end);
9700                    notifyViewAccessibilityStateChangedIfNeeded(
9701                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9702                    return true;
9703                }
9704            } break;
9705            case R.id.accessibilityActionShowOnScreen: {
9706                if (mAttachInfo != null) {
9707                    final Rect r = mAttachInfo.mTmpInvalRect;
9708                    getDrawingRect(r);
9709                    return requestRectangleOnScreen(r, true);
9710                }
9711            } break;
9712            case R.id.accessibilityActionContextClick: {
9713                if (isContextClickable()) {
9714                    performContextClick();
9715                    return true;
9716                }
9717            } break;
9718        }
9719        return false;
9720    }
9721
9722    private boolean traverseAtGranularity(int granularity, boolean forward,
9723            boolean extendSelection) {
9724        CharSequence text = getIterableTextForAccessibility();
9725        if (text == null || text.length() == 0) {
9726            return false;
9727        }
9728        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9729        if (iterator == null) {
9730            return false;
9731        }
9732        int current = getAccessibilitySelectionEnd();
9733        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9734            current = forward ? 0 : text.length();
9735        }
9736        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9737        if (range == null) {
9738            return false;
9739        }
9740        final int segmentStart = range[0];
9741        final int segmentEnd = range[1];
9742        int selectionStart;
9743        int selectionEnd;
9744        if (extendSelection && isAccessibilitySelectionExtendable()) {
9745            selectionStart = getAccessibilitySelectionStart();
9746            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9747                selectionStart = forward ? segmentStart : segmentEnd;
9748            }
9749            selectionEnd = forward ? segmentEnd : segmentStart;
9750        } else {
9751            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9752        }
9753        setAccessibilitySelection(selectionStart, selectionEnd);
9754        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9755                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9756        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9757        return true;
9758    }
9759
9760    /**
9761     * Gets the text reported for accessibility purposes.
9762     *
9763     * @return The accessibility text.
9764     *
9765     * @hide
9766     */
9767    public CharSequence getIterableTextForAccessibility() {
9768        return getContentDescription();
9769    }
9770
9771    /**
9772     * Gets whether accessibility selection can be extended.
9773     *
9774     * @return If selection is extensible.
9775     *
9776     * @hide
9777     */
9778    public boolean isAccessibilitySelectionExtendable() {
9779        return false;
9780    }
9781
9782    /**
9783     * @hide
9784     */
9785    public int getAccessibilitySelectionStart() {
9786        return mAccessibilityCursorPosition;
9787    }
9788
9789    /**
9790     * @hide
9791     */
9792    public int getAccessibilitySelectionEnd() {
9793        return getAccessibilitySelectionStart();
9794    }
9795
9796    /**
9797     * @hide
9798     */
9799    public void setAccessibilitySelection(int start, int end) {
9800        if (start ==  end && end == mAccessibilityCursorPosition) {
9801            return;
9802        }
9803        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9804            mAccessibilityCursorPosition = start;
9805        } else {
9806            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9807        }
9808        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9809    }
9810
9811    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9812            int fromIndex, int toIndex) {
9813        if (mParent == null) {
9814            return;
9815        }
9816        AccessibilityEvent event = AccessibilityEvent.obtain(
9817                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9818        onInitializeAccessibilityEvent(event);
9819        onPopulateAccessibilityEvent(event);
9820        event.setFromIndex(fromIndex);
9821        event.setToIndex(toIndex);
9822        event.setAction(action);
9823        event.setMovementGranularity(granularity);
9824        mParent.requestSendAccessibilityEvent(this, event);
9825    }
9826
9827    /**
9828     * @hide
9829     */
9830    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9831        switch (granularity) {
9832            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9833                CharSequence text = getIterableTextForAccessibility();
9834                if (text != null && text.length() > 0) {
9835                    CharacterTextSegmentIterator iterator =
9836                        CharacterTextSegmentIterator.getInstance(
9837                                mContext.getResources().getConfiguration().locale);
9838                    iterator.initialize(text.toString());
9839                    return iterator;
9840                }
9841            } break;
9842            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9843                CharSequence text = getIterableTextForAccessibility();
9844                if (text != null && text.length() > 0) {
9845                    WordTextSegmentIterator iterator =
9846                        WordTextSegmentIterator.getInstance(
9847                                mContext.getResources().getConfiguration().locale);
9848                    iterator.initialize(text.toString());
9849                    return iterator;
9850                }
9851            } break;
9852            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9853                CharSequence text = getIterableTextForAccessibility();
9854                if (text != null && text.length() > 0) {
9855                    ParagraphTextSegmentIterator iterator =
9856                        ParagraphTextSegmentIterator.getInstance();
9857                    iterator.initialize(text.toString());
9858                    return iterator;
9859                }
9860            } break;
9861        }
9862        return null;
9863    }
9864
9865    /**
9866     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
9867     * and {@link #onFinishTemporaryDetach()}.
9868     *
9869     * <p>This method always returns {@code true} when called directly or indirectly from
9870     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
9871     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
9872     * <ul>
9873     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
9874     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
9875     * </ul>
9876     * </p>
9877     *
9878     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
9879     * and {@link #onFinishTemporaryDetach()}.
9880     */
9881    public final boolean isTemporarilyDetached() {
9882        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
9883    }
9884
9885    /**
9886     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
9887     * a container View.
9888     */
9889    @CallSuper
9890    public void dispatchStartTemporaryDetach() {
9891        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
9892        onStartTemporaryDetach();
9893    }
9894
9895    /**
9896     * This is called when a container is going to temporarily detach a child, with
9897     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9898     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9899     * {@link #onDetachedFromWindow()} when the container is done.
9900     */
9901    public void onStartTemporaryDetach() {
9902        removeUnsetPressCallback();
9903        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9904    }
9905
9906    /**
9907     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
9908     * a container View.
9909     */
9910    @CallSuper
9911    public void dispatchFinishTemporaryDetach() {
9912        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
9913        onFinishTemporaryDetach();
9914        if (hasWindowFocus() && hasFocus()) {
9915            InputMethodManager.getInstance().focusIn(this);
9916        }
9917    }
9918
9919    /**
9920     * Called after {@link #onStartTemporaryDetach} when the container is done
9921     * changing the view.
9922     */
9923    public void onFinishTemporaryDetach() {
9924    }
9925
9926    /**
9927     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9928     * for this view's window.  Returns null if the view is not currently attached
9929     * to the window.  Normally you will not need to use this directly, but
9930     * just use the standard high-level event callbacks like
9931     * {@link #onKeyDown(int, KeyEvent)}.
9932     */
9933    public KeyEvent.DispatcherState getKeyDispatcherState() {
9934        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9935    }
9936
9937    /**
9938     * Dispatch a key event before it is processed by any input method
9939     * associated with the view hierarchy.  This can be used to intercept
9940     * key events in special situations before the IME consumes them; a
9941     * typical example would be handling the BACK key to update the application's
9942     * UI instead of allowing the IME to see it and close itself.
9943     *
9944     * @param event The key event to be dispatched.
9945     * @return True if the event was handled, false otherwise.
9946     */
9947    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9948        return onKeyPreIme(event.getKeyCode(), event);
9949    }
9950
9951    /**
9952     * Dispatch a key event to the next view on the focus path. This path runs
9953     * from the top of the view tree down to the currently focused view. If this
9954     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9955     * the next node down the focus path. This method also fires any key
9956     * listeners.
9957     *
9958     * @param event The key event to be dispatched.
9959     * @return True if the event was handled, false otherwise.
9960     */
9961    public boolean dispatchKeyEvent(KeyEvent event) {
9962        if (mInputEventConsistencyVerifier != null) {
9963            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9964        }
9965
9966        // Give any attached key listener a first crack at the event.
9967        //noinspection SimplifiableIfStatement
9968        ListenerInfo li = mListenerInfo;
9969        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9970                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9971            return true;
9972        }
9973
9974        if (event.dispatch(this, mAttachInfo != null
9975                ? mAttachInfo.mKeyDispatchState : null, this)) {
9976            return true;
9977        }
9978
9979        if (mInputEventConsistencyVerifier != null) {
9980            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9981        }
9982        return false;
9983    }
9984
9985    /**
9986     * Dispatches a key shortcut event.
9987     *
9988     * @param event The key event to be dispatched.
9989     * @return True if the event was handled by the view, false otherwise.
9990     */
9991    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9992        return onKeyShortcut(event.getKeyCode(), event);
9993    }
9994
9995    /**
9996     * Pass the touch screen motion event down to the target view, or this
9997     * view if it is the target.
9998     *
9999     * @param event The motion event to be dispatched.
10000     * @return True if the event was handled by the view, false otherwise.
10001     */
10002    public boolean dispatchTouchEvent(MotionEvent event) {
10003        // If the event should be handled by accessibility focus first.
10004        if (event.isTargetAccessibilityFocus()) {
10005            // We don't have focus or no virtual descendant has it, do not handle the event.
10006            if (!isAccessibilityFocusedViewOrHost()) {
10007                return false;
10008            }
10009            // We have focus and got the event, then use normal event dispatch.
10010            event.setTargetAccessibilityFocus(false);
10011        }
10012
10013        boolean result = false;
10014
10015        if (mInputEventConsistencyVerifier != null) {
10016            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
10017        }
10018
10019        final int actionMasked = event.getActionMasked();
10020        if (actionMasked == MotionEvent.ACTION_DOWN) {
10021            // Defensive cleanup for new gesture
10022            stopNestedScroll();
10023        }
10024
10025        if (onFilterTouchEventForSecurity(event)) {
10026            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
10027                result = true;
10028            }
10029            //noinspection SimplifiableIfStatement
10030            ListenerInfo li = mListenerInfo;
10031            if (li != null && li.mOnTouchListener != null
10032                    && (mViewFlags & ENABLED_MASK) == ENABLED
10033                    && li.mOnTouchListener.onTouch(this, event)) {
10034                result = true;
10035            }
10036
10037            if (!result && onTouchEvent(event)) {
10038                result = true;
10039            }
10040        }
10041
10042        if (!result && mInputEventConsistencyVerifier != null) {
10043            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10044        }
10045
10046        // Clean up after nested scrolls if this is the end of a gesture;
10047        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
10048        // of the gesture.
10049        if (actionMasked == MotionEvent.ACTION_UP ||
10050                actionMasked == MotionEvent.ACTION_CANCEL ||
10051                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
10052            stopNestedScroll();
10053        }
10054
10055        return result;
10056    }
10057
10058    boolean isAccessibilityFocusedViewOrHost() {
10059        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
10060                .getAccessibilityFocusedHost() == this);
10061    }
10062
10063    /**
10064     * Filter the touch event to apply security policies.
10065     *
10066     * @param event The motion event to be filtered.
10067     * @return True if the event should be dispatched, false if the event should be dropped.
10068     *
10069     * @see #getFilterTouchesWhenObscured
10070     */
10071    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
10072        //noinspection RedundantIfStatement
10073        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
10074                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
10075            // Window is obscured, drop this touch.
10076            return false;
10077        }
10078        return true;
10079    }
10080
10081    /**
10082     * Pass a trackball motion event down to the focused view.
10083     *
10084     * @param event The motion event to be dispatched.
10085     * @return True if the event was handled by the view, false otherwise.
10086     */
10087    public boolean dispatchTrackballEvent(MotionEvent event) {
10088        if (mInputEventConsistencyVerifier != null) {
10089            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
10090        }
10091
10092        return onTrackballEvent(event);
10093    }
10094
10095    /**
10096     * Dispatch a generic motion event.
10097     * <p>
10098     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10099     * are delivered to the view under the pointer.  All other generic motion events are
10100     * delivered to the focused view.  Hover events are handled specially and are delivered
10101     * to {@link #onHoverEvent(MotionEvent)}.
10102     * </p>
10103     *
10104     * @param event The motion event to be dispatched.
10105     * @return True if the event was handled by the view, false otherwise.
10106     */
10107    public boolean dispatchGenericMotionEvent(MotionEvent event) {
10108        if (mInputEventConsistencyVerifier != null) {
10109            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
10110        }
10111
10112        final int source = event.getSource();
10113        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
10114            final int action = event.getAction();
10115            if (action == MotionEvent.ACTION_HOVER_ENTER
10116                    || action == MotionEvent.ACTION_HOVER_MOVE
10117                    || action == MotionEvent.ACTION_HOVER_EXIT) {
10118                if (dispatchHoverEvent(event)) {
10119                    return true;
10120                }
10121            } else if (dispatchGenericPointerEvent(event)) {
10122                return true;
10123            }
10124        } else if (dispatchGenericFocusedEvent(event)) {
10125            return true;
10126        }
10127
10128        if (dispatchGenericMotionEventInternal(event)) {
10129            return true;
10130        }
10131
10132        if (mInputEventConsistencyVerifier != null) {
10133            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10134        }
10135        return false;
10136    }
10137
10138    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
10139        //noinspection SimplifiableIfStatement
10140        ListenerInfo li = mListenerInfo;
10141        if (li != null && li.mOnGenericMotionListener != null
10142                && (mViewFlags & ENABLED_MASK) == ENABLED
10143                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
10144            return true;
10145        }
10146
10147        if (onGenericMotionEvent(event)) {
10148            return true;
10149        }
10150
10151        final int actionButton = event.getActionButton();
10152        switch (event.getActionMasked()) {
10153            case MotionEvent.ACTION_BUTTON_PRESS:
10154                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
10155                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10156                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10157                    if (performContextClick(event.getX(), event.getY())) {
10158                        mInContextButtonPress = true;
10159                        setPressed(true, event.getX(), event.getY());
10160                        removeTapCallback();
10161                        removeLongPressCallback();
10162                        return true;
10163                    }
10164                }
10165                break;
10166
10167            case MotionEvent.ACTION_BUTTON_RELEASE:
10168                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10169                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10170                    mInContextButtonPress = false;
10171                    mIgnoreNextUpEvent = true;
10172                }
10173                break;
10174        }
10175
10176        if (mInputEventConsistencyVerifier != null) {
10177            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10178        }
10179        return false;
10180    }
10181
10182    /**
10183     * Dispatch a hover event.
10184     * <p>
10185     * Do not call this method directly.
10186     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10187     * </p>
10188     *
10189     * @param event The motion event to be dispatched.
10190     * @return True if the event was handled by the view, false otherwise.
10191     */
10192    protected boolean dispatchHoverEvent(MotionEvent event) {
10193        ListenerInfo li = mListenerInfo;
10194        //noinspection SimplifiableIfStatement
10195        if (li != null && li.mOnHoverListener != null
10196                && (mViewFlags & ENABLED_MASK) == ENABLED
10197                && li.mOnHoverListener.onHover(this, event)) {
10198            return true;
10199        }
10200
10201        return onHoverEvent(event);
10202    }
10203
10204    /**
10205     * Returns true if the view has a child to which it has recently sent
10206     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
10207     * it does not have a hovered child, then it must be the innermost hovered view.
10208     * @hide
10209     */
10210    protected boolean hasHoveredChild() {
10211        return false;
10212    }
10213
10214    /**
10215     * Dispatch a generic motion event to the view under the first pointer.
10216     * <p>
10217     * Do not call this method directly.
10218     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10219     * </p>
10220     *
10221     * @param event The motion event to be dispatched.
10222     * @return True if the event was handled by the view, false otherwise.
10223     */
10224    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
10225        return false;
10226    }
10227
10228    /**
10229     * Dispatch a generic motion event to the currently focused view.
10230     * <p>
10231     * Do not call this method directly.
10232     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10233     * </p>
10234     *
10235     * @param event The motion event to be dispatched.
10236     * @return True if the event was handled by the view, false otherwise.
10237     */
10238    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
10239        return false;
10240    }
10241
10242    /**
10243     * Dispatch a pointer event.
10244     * <p>
10245     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
10246     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
10247     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
10248     * and should not be expected to handle other pointing device features.
10249     * </p>
10250     *
10251     * @param event The motion event to be dispatched.
10252     * @return True if the event was handled by the view, false otherwise.
10253     * @hide
10254     */
10255    public final boolean dispatchPointerEvent(MotionEvent event) {
10256        if (event.isTouchEvent()) {
10257            return dispatchTouchEvent(event);
10258        } else {
10259            return dispatchGenericMotionEvent(event);
10260        }
10261    }
10262
10263    /**
10264     * Called when the window containing this view gains or loses window focus.
10265     * ViewGroups should override to route to their children.
10266     *
10267     * @param hasFocus True if the window containing this view now has focus,
10268     *        false otherwise.
10269     */
10270    public void dispatchWindowFocusChanged(boolean hasFocus) {
10271        onWindowFocusChanged(hasFocus);
10272    }
10273
10274    /**
10275     * Called when the window containing this view gains or loses focus.  Note
10276     * that this is separate from view focus: to receive key events, both
10277     * your view and its window must have focus.  If a window is displayed
10278     * on top of yours that takes input focus, then your own window will lose
10279     * focus but the view focus will remain unchanged.
10280     *
10281     * @param hasWindowFocus True if the window containing this view now has
10282     *        focus, false otherwise.
10283     */
10284    public void onWindowFocusChanged(boolean hasWindowFocus) {
10285        InputMethodManager imm = InputMethodManager.peekInstance();
10286        if (!hasWindowFocus) {
10287            if (isPressed()) {
10288                setPressed(false);
10289            }
10290            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10291                imm.focusOut(this);
10292            }
10293            removeLongPressCallback();
10294            removeTapCallback();
10295            onFocusLost();
10296        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10297            imm.focusIn(this);
10298        }
10299        refreshDrawableState();
10300    }
10301
10302    /**
10303     * Returns true if this view is in a window that currently has window focus.
10304     * Note that this is not the same as the view itself having focus.
10305     *
10306     * @return True if this view is in a window that currently has window focus.
10307     */
10308    public boolean hasWindowFocus() {
10309        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
10310    }
10311
10312    /**
10313     * Dispatch a view visibility change down the view hierarchy.
10314     * ViewGroups should override to route to their children.
10315     * @param changedView The view whose visibility changed. Could be 'this' or
10316     * an ancestor view.
10317     * @param visibility The new visibility of changedView: {@link #VISIBLE},
10318     * {@link #INVISIBLE} or {@link #GONE}.
10319     */
10320    protected void dispatchVisibilityChanged(@NonNull View changedView,
10321            @Visibility int visibility) {
10322        onVisibilityChanged(changedView, visibility);
10323    }
10324
10325    /**
10326     * Called when the visibility of the view or an ancestor of the view has
10327     * changed.
10328     *
10329     * @param changedView The view whose visibility changed. May be
10330     *                    {@code this} or an ancestor view.
10331     * @param visibility The new visibility, one of {@link #VISIBLE},
10332     *                   {@link #INVISIBLE} or {@link #GONE}.
10333     */
10334    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
10335    }
10336
10337    /**
10338     * Dispatch a hint about whether this view is displayed. For instance, when
10339     * a View moves out of the screen, it might receives a display hint indicating
10340     * the view is not displayed. Applications should not <em>rely</em> on this hint
10341     * as there is no guarantee that they will receive one.
10342     *
10343     * @param hint A hint about whether or not this view is displayed:
10344     * {@link #VISIBLE} or {@link #INVISIBLE}.
10345     */
10346    public void dispatchDisplayHint(@Visibility int hint) {
10347        onDisplayHint(hint);
10348    }
10349
10350    /**
10351     * Gives this view a hint about whether is displayed or not. For instance, when
10352     * a View moves out of the screen, it might receives a display hint indicating
10353     * the view is not displayed. Applications should not <em>rely</em> on this hint
10354     * as there is no guarantee that they will receive one.
10355     *
10356     * @param hint A hint about whether or not this view is displayed:
10357     * {@link #VISIBLE} or {@link #INVISIBLE}.
10358     */
10359    protected void onDisplayHint(@Visibility int hint) {
10360    }
10361
10362    /**
10363     * Dispatch a window visibility change down the view hierarchy.
10364     * ViewGroups should override to route to their children.
10365     *
10366     * @param visibility The new visibility of the window.
10367     *
10368     * @see #onWindowVisibilityChanged(int)
10369     */
10370    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
10371        onWindowVisibilityChanged(visibility);
10372    }
10373
10374    /**
10375     * Called when the window containing has change its visibility
10376     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
10377     * that this tells you whether or not your window is being made visible
10378     * to the window manager; this does <em>not</em> tell you whether or not
10379     * your window is obscured by other windows on the screen, even if it
10380     * is itself visible.
10381     *
10382     * @param visibility The new visibility of the window.
10383     */
10384    protected void onWindowVisibilityChanged(@Visibility int visibility) {
10385        if (visibility == VISIBLE) {
10386            initialAwakenScrollBars();
10387        }
10388    }
10389
10390    /**
10391     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
10392     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
10393     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
10394     *
10395     * @param isVisible true if this view's visibility to the user is uninterrupted by its
10396     *                  ancestors or by window visibility
10397     * @return true if this view is visible to the user, not counting clipping or overlapping
10398     */
10399    boolean dispatchVisibilityAggregated(boolean isVisible) {
10400        final boolean thisVisible = getVisibility() == VISIBLE;
10401        // If we're not visible but something is telling us we are, ignore it.
10402        if (thisVisible || !isVisible) {
10403            onVisibilityAggregated(isVisible);
10404        }
10405        return thisVisible && isVisible;
10406    }
10407
10408    /**
10409     * Called when the user-visibility of this View is potentially affected by a change
10410     * to this view itself, an ancestor view or the window this view is attached to.
10411     *
10412     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
10413     *                  and this view's window is also visible
10414     */
10415    @CallSuper
10416    public void onVisibilityAggregated(boolean isVisible) {
10417        if (isVisible && mAttachInfo != null) {
10418            initialAwakenScrollBars();
10419        }
10420
10421        final Drawable dr = mBackground;
10422        if (dr != null && isVisible != dr.isVisible()) {
10423            dr.setVisible(isVisible, false);
10424        }
10425        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
10426        if (fg != null && isVisible != fg.isVisible()) {
10427            fg.setVisible(isVisible, false);
10428        }
10429    }
10430
10431    /**
10432     * Returns the current visibility of the window this view is attached to
10433     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
10434     *
10435     * @return Returns the current visibility of the view's window.
10436     */
10437    @Visibility
10438    public int getWindowVisibility() {
10439        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
10440    }
10441
10442    /**
10443     * Retrieve the overall visible display size in which the window this view is
10444     * attached to has been positioned in.  This takes into account screen
10445     * decorations above the window, for both cases where the window itself
10446     * is being position inside of them or the window is being placed under
10447     * then and covered insets are used for the window to position its content
10448     * inside.  In effect, this tells you the available area where content can
10449     * be placed and remain visible to users.
10450     *
10451     * <p>This function requires an IPC back to the window manager to retrieve
10452     * the requested information, so should not be used in performance critical
10453     * code like drawing.
10454     *
10455     * @param outRect Filled in with the visible display frame.  If the view
10456     * is not attached to a window, this is simply the raw display size.
10457     */
10458    public void getWindowVisibleDisplayFrame(Rect outRect) {
10459        if (mAttachInfo != null) {
10460            try {
10461                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10462            } catch (RemoteException e) {
10463                return;
10464            }
10465            // XXX This is really broken, and probably all needs to be done
10466            // in the window manager, and we need to know more about whether
10467            // we want the area behind or in front of the IME.
10468            final Rect insets = mAttachInfo.mVisibleInsets;
10469            outRect.left += insets.left;
10470            outRect.top += insets.top;
10471            outRect.right -= insets.right;
10472            outRect.bottom -= insets.bottom;
10473            return;
10474        }
10475        // The view is not attached to a display so we don't have a context.
10476        // Make a best guess about the display size.
10477        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10478        d.getRectSize(outRect);
10479    }
10480
10481    /**
10482     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
10483     * is currently in without any insets.
10484     *
10485     * @hide
10486     */
10487    public void getWindowDisplayFrame(Rect outRect) {
10488        if (mAttachInfo != null) {
10489            try {
10490                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10491            } catch (RemoteException e) {
10492                return;
10493            }
10494            return;
10495        }
10496        // The view is not attached to a display so we don't have a context.
10497        // Make a best guess about the display size.
10498        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10499        d.getRectSize(outRect);
10500    }
10501
10502    /**
10503     * Dispatch a notification about a resource configuration change down
10504     * the view hierarchy.
10505     * ViewGroups should override to route to their children.
10506     *
10507     * @param newConfig The new resource configuration.
10508     *
10509     * @see #onConfigurationChanged(android.content.res.Configuration)
10510     */
10511    public void dispatchConfigurationChanged(Configuration newConfig) {
10512        onConfigurationChanged(newConfig);
10513    }
10514
10515    /**
10516     * Called when the current configuration of the resources being used
10517     * by the application have changed.  You can use this to decide when
10518     * to reload resources that can changed based on orientation and other
10519     * configuration characteristics.  You only need to use this if you are
10520     * not relying on the normal {@link android.app.Activity} mechanism of
10521     * recreating the activity instance upon a configuration change.
10522     *
10523     * @param newConfig The new resource configuration.
10524     */
10525    protected void onConfigurationChanged(Configuration newConfig) {
10526    }
10527
10528    /**
10529     * Private function to aggregate all per-view attributes in to the view
10530     * root.
10531     */
10532    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10533        performCollectViewAttributes(attachInfo, visibility);
10534    }
10535
10536    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10537        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
10538            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
10539                attachInfo.mKeepScreenOn = true;
10540            }
10541            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
10542            ListenerInfo li = mListenerInfo;
10543            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
10544                attachInfo.mHasSystemUiListeners = true;
10545            }
10546        }
10547    }
10548
10549    void needGlobalAttributesUpdate(boolean force) {
10550        final AttachInfo ai = mAttachInfo;
10551        if (ai != null && !ai.mRecomputeGlobalAttributes) {
10552            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
10553                    || ai.mHasSystemUiListeners) {
10554                ai.mRecomputeGlobalAttributes = true;
10555            }
10556        }
10557    }
10558
10559    /**
10560     * Returns whether the device is currently in touch mode.  Touch mode is entered
10561     * once the user begins interacting with the device by touch, and affects various
10562     * things like whether focus is always visible to the user.
10563     *
10564     * @return Whether the device is in touch mode.
10565     */
10566    @ViewDebug.ExportedProperty
10567    public boolean isInTouchMode() {
10568        if (mAttachInfo != null) {
10569            return mAttachInfo.mInTouchMode;
10570        } else {
10571            return ViewRootImpl.isInTouchMode();
10572        }
10573    }
10574
10575    /**
10576     * Returns the context the view is running in, through which it can
10577     * access the current theme, resources, etc.
10578     *
10579     * @return The view's Context.
10580     */
10581    @ViewDebug.CapturedViewProperty
10582    public final Context getContext() {
10583        return mContext;
10584    }
10585
10586    /**
10587     * Handle a key event before it is processed by any input method
10588     * associated with the view hierarchy.  This can be used to intercept
10589     * key events in special situations before the IME consumes them; a
10590     * typical example would be handling the BACK key to update the application's
10591     * UI instead of allowing the IME to see it and close itself.
10592     *
10593     * @param keyCode The value in event.getKeyCode().
10594     * @param event Description of the key event.
10595     * @return If you handled the event, return true. If you want to allow the
10596     *         event to be handled by the next receiver, return false.
10597     */
10598    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10599        return false;
10600    }
10601
10602    /**
10603     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10604     * KeyEvent.Callback.onKeyDown()}: perform press of the view
10605     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10606     * is released, if the view is enabled and clickable.
10607     * <p>
10608     * Key presses in software keyboards will generally NOT trigger this
10609     * listener, although some may elect to do so in some situations. Do not
10610     * rely on this to catch software key presses.
10611     *
10612     * @param keyCode a key code that represents the button pressed, from
10613     *                {@link android.view.KeyEvent}
10614     * @param event the KeyEvent object that defines the button action
10615     */
10616    public boolean onKeyDown(int keyCode, KeyEvent event) {
10617        if (KeyEvent.isConfirmKey(keyCode)) {
10618            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10619                return true;
10620            }
10621
10622            // Long clickable items don't necessarily have to be clickable.
10623            if (((mViewFlags & CLICKABLE) == CLICKABLE
10624                    || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10625                    && (event.getRepeatCount() == 0)) {
10626                // For the purposes of menu anchoring and drawable hotspots,
10627                // key events are considered to be at the center of the view.
10628                final float x = getWidth() / 2f;
10629                final float y = getHeight() / 2f;
10630                setPressed(true, x, y);
10631                checkForLongClick(0, x, y);
10632                return true;
10633            }
10634        }
10635
10636        return false;
10637    }
10638
10639    /**
10640     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
10641     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
10642     * the event).
10643     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10644     * although some may elect to do so in some situations. Do not rely on this to
10645     * catch software key presses.
10646     */
10647    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
10648        return false;
10649    }
10650
10651    /**
10652     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
10653     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
10654     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
10655     * or {@link KeyEvent#KEYCODE_SPACE} is released.
10656     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10657     * although some may elect to do so in some situations. Do not rely on this to
10658     * catch software key presses.
10659     *
10660     * @param keyCode A key code that represents the button pressed, from
10661     *                {@link android.view.KeyEvent}.
10662     * @param event   The KeyEvent object that defines the button action.
10663     */
10664    public boolean onKeyUp(int keyCode, KeyEvent event) {
10665        if (KeyEvent.isConfirmKey(keyCode)) {
10666            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10667                return true;
10668            }
10669            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
10670                setPressed(false);
10671
10672                if (!mHasPerformedLongPress) {
10673                    // This is a tap, so remove the longpress check
10674                    removeLongPressCallback();
10675                    return performClick();
10676                }
10677            }
10678        }
10679        return false;
10680    }
10681
10682    /**
10683     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10684     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
10685     * the event).
10686     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10687     * although some may elect to do so in some situations. Do not rely on this to
10688     * catch software key presses.
10689     *
10690     * @param keyCode     A key code that represents the button pressed, from
10691     *                    {@link android.view.KeyEvent}.
10692     * @param repeatCount The number of times the action was made.
10693     * @param event       The KeyEvent object that defines the button action.
10694     */
10695    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10696        return false;
10697    }
10698
10699    /**
10700     * Called on the focused view when a key shortcut event is not handled.
10701     * Override this method to implement local key shortcuts for the View.
10702     * Key shortcuts can also be implemented by setting the
10703     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10704     *
10705     * @param keyCode The value in event.getKeyCode().
10706     * @param event Description of the key event.
10707     * @return If you handled the event, return true. If you want to allow the
10708     *         event to be handled by the next receiver, return false.
10709     */
10710    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10711        return false;
10712    }
10713
10714    /**
10715     * Check whether the called view is a text editor, in which case it
10716     * would make sense to automatically display a soft input window for
10717     * it.  Subclasses should override this if they implement
10718     * {@link #onCreateInputConnection(EditorInfo)} to return true if
10719     * a call on that method would return a non-null InputConnection, and
10720     * they are really a first-class editor that the user would normally
10721     * start typing on when the go into a window containing your view.
10722     *
10723     * <p>The default implementation always returns false.  This does
10724     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10725     * will not be called or the user can not otherwise perform edits on your
10726     * view; it is just a hint to the system that this is not the primary
10727     * purpose of this view.
10728     *
10729     * @return Returns true if this view is a text editor, else false.
10730     */
10731    public boolean onCheckIsTextEditor() {
10732        return false;
10733    }
10734
10735    /**
10736     * Create a new InputConnection for an InputMethod to interact
10737     * with the view.  The default implementation returns null, since it doesn't
10738     * support input methods.  You can override this to implement such support.
10739     * This is only needed for views that take focus and text input.
10740     *
10741     * <p>When implementing this, you probably also want to implement
10742     * {@link #onCheckIsTextEditor()} to indicate you will return a
10743     * non-null InputConnection.</p>
10744     *
10745     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10746     * object correctly and in its entirety, so that the connected IME can rely
10747     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10748     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10749     * must be filled in with the correct cursor position for IMEs to work correctly
10750     * with your application.</p>
10751     *
10752     * @param outAttrs Fill in with attribute information about the connection.
10753     */
10754    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10755        return null;
10756    }
10757
10758    /**
10759     * Called by the {@link android.view.inputmethod.InputMethodManager}
10760     * when a view who is not the current
10761     * input connection target is trying to make a call on the manager.  The
10762     * default implementation returns false; you can override this to return
10763     * true for certain views if you are performing InputConnection proxying
10764     * to them.
10765     * @param view The View that is making the InputMethodManager call.
10766     * @return Return true to allow the call, false to reject.
10767     */
10768    public boolean checkInputConnectionProxy(View view) {
10769        return false;
10770    }
10771
10772    /**
10773     * Show the context menu for this view. It is not safe to hold on to the
10774     * menu after returning from this method.
10775     *
10776     * You should normally not overload this method. Overload
10777     * {@link #onCreateContextMenu(ContextMenu)} or define an
10778     * {@link OnCreateContextMenuListener} to add items to the context menu.
10779     *
10780     * @param menu The context menu to populate
10781     */
10782    public void createContextMenu(ContextMenu menu) {
10783        ContextMenuInfo menuInfo = getContextMenuInfo();
10784
10785        // Sets the current menu info so all items added to menu will have
10786        // my extra info set.
10787        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10788
10789        onCreateContextMenu(menu);
10790        ListenerInfo li = mListenerInfo;
10791        if (li != null && li.mOnCreateContextMenuListener != null) {
10792            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10793        }
10794
10795        // Clear the extra information so subsequent items that aren't mine don't
10796        // have my extra info.
10797        ((MenuBuilder)menu).setCurrentMenuInfo(null);
10798
10799        if (mParent != null) {
10800            mParent.createContextMenu(menu);
10801        }
10802    }
10803
10804    /**
10805     * Views should implement this if they have extra information to associate
10806     * with the context menu. The return result is supplied as a parameter to
10807     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10808     * callback.
10809     *
10810     * @return Extra information about the item for which the context menu
10811     *         should be shown. This information will vary across different
10812     *         subclasses of View.
10813     */
10814    protected ContextMenuInfo getContextMenuInfo() {
10815        return null;
10816    }
10817
10818    /**
10819     * Views should implement this if the view itself is going to add items to
10820     * the context menu.
10821     *
10822     * @param menu the context menu to populate
10823     */
10824    protected void onCreateContextMenu(ContextMenu menu) {
10825    }
10826
10827    /**
10828     * Implement this method to handle trackball motion events.  The
10829     * <em>relative</em> movement of the trackball since the last event
10830     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10831     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10832     * that a movement of 1 corresponds to the user pressing one DPAD key (so
10833     * they will often be fractional values, representing the more fine-grained
10834     * movement information available from a trackball).
10835     *
10836     * @param event The motion event.
10837     * @return True if the event was handled, false otherwise.
10838     */
10839    public boolean onTrackballEvent(MotionEvent event) {
10840        return false;
10841    }
10842
10843    /**
10844     * Implement this method to handle generic motion events.
10845     * <p>
10846     * Generic motion events describe joystick movements, mouse hovers, track pad
10847     * touches, scroll wheel movements and other input events.  The
10848     * {@link MotionEvent#getSource() source} of the motion event specifies
10849     * the class of input that was received.  Implementations of this method
10850     * must examine the bits in the source before processing the event.
10851     * The following code example shows how this is done.
10852     * </p><p>
10853     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10854     * are delivered to the view under the pointer.  All other generic motion events are
10855     * delivered to the focused view.
10856     * </p>
10857     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10858     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10859     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10860     *             // process the joystick movement...
10861     *             return true;
10862     *         }
10863     *     }
10864     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10865     *         switch (event.getAction()) {
10866     *             case MotionEvent.ACTION_HOVER_MOVE:
10867     *                 // process the mouse hover movement...
10868     *                 return true;
10869     *             case MotionEvent.ACTION_SCROLL:
10870     *                 // process the scroll wheel movement...
10871     *                 return true;
10872     *         }
10873     *     }
10874     *     return super.onGenericMotionEvent(event);
10875     * }</pre>
10876     *
10877     * @param event The generic motion event being processed.
10878     * @return True if the event was handled, false otherwise.
10879     */
10880    public boolean onGenericMotionEvent(MotionEvent event) {
10881        return false;
10882    }
10883
10884    /**
10885     * Implement this method to handle hover events.
10886     * <p>
10887     * This method is called whenever a pointer is hovering into, over, or out of the
10888     * bounds of a view and the view is not currently being touched.
10889     * Hover events are represented as pointer events with action
10890     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10891     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10892     * </p>
10893     * <ul>
10894     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10895     * when the pointer enters the bounds of the view.</li>
10896     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10897     * when the pointer has already entered the bounds of the view and has moved.</li>
10898     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10899     * when the pointer has exited the bounds of the view or when the pointer is
10900     * about to go down due to a button click, tap, or similar user action that
10901     * causes the view to be touched.</li>
10902     * </ul>
10903     * <p>
10904     * The view should implement this method to return true to indicate that it is
10905     * handling the hover event, such as by changing its drawable state.
10906     * </p><p>
10907     * The default implementation calls {@link #setHovered} to update the hovered state
10908     * of the view when a hover enter or hover exit event is received, if the view
10909     * is enabled and is clickable.  The default implementation also sends hover
10910     * accessibility events.
10911     * </p>
10912     *
10913     * @param event The motion event that describes the hover.
10914     * @return True if the view handled the hover event.
10915     *
10916     * @see #isHovered
10917     * @see #setHovered
10918     * @see #onHoverChanged
10919     */
10920    public boolean onHoverEvent(MotionEvent event) {
10921        // The root view may receive hover (or touch) events that are outside the bounds of
10922        // the window.  This code ensures that we only send accessibility events for
10923        // hovers that are actually within the bounds of the root view.
10924        final int action = event.getActionMasked();
10925        if (!mSendingHoverAccessibilityEvents) {
10926            if ((action == MotionEvent.ACTION_HOVER_ENTER
10927                    || action == MotionEvent.ACTION_HOVER_MOVE)
10928                    && !hasHoveredChild()
10929                    && pointInView(event.getX(), event.getY())) {
10930                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10931                mSendingHoverAccessibilityEvents = true;
10932            }
10933        } else {
10934            if (action == MotionEvent.ACTION_HOVER_EXIT
10935                    || (action == MotionEvent.ACTION_MOVE
10936                            && !pointInView(event.getX(), event.getY()))) {
10937                mSendingHoverAccessibilityEvents = false;
10938                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10939            }
10940        }
10941
10942        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
10943                && event.isFromSource(InputDevice.SOURCE_MOUSE)
10944                && isOnScrollbar(event.getX(), event.getY())) {
10945            awakenScrollBars();
10946        }
10947        if (isHoverable()) {
10948            switch (action) {
10949                case MotionEvent.ACTION_HOVER_ENTER:
10950                    setHovered(true);
10951                    break;
10952                case MotionEvent.ACTION_HOVER_EXIT:
10953                    setHovered(false);
10954                    break;
10955            }
10956
10957            // Dispatch the event to onGenericMotionEvent before returning true.
10958            // This is to provide compatibility with existing applications that
10959            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10960            // break because of the new default handling for hoverable views
10961            // in onHoverEvent.
10962            // Note that onGenericMotionEvent will be called by default when
10963            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10964            dispatchGenericMotionEventInternal(event);
10965            // The event was already handled by calling setHovered(), so always
10966            // return true.
10967            return true;
10968        }
10969
10970        return false;
10971    }
10972
10973    /**
10974     * Returns true if the view should handle {@link #onHoverEvent}
10975     * by calling {@link #setHovered} to change its hovered state.
10976     *
10977     * @return True if the view is hoverable.
10978     */
10979    private boolean isHoverable() {
10980        final int viewFlags = mViewFlags;
10981        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10982            return false;
10983        }
10984
10985        return (viewFlags & CLICKABLE) == CLICKABLE
10986                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10987                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10988    }
10989
10990    /**
10991     * Returns true if the view is currently hovered.
10992     *
10993     * @return True if the view is currently hovered.
10994     *
10995     * @see #setHovered
10996     * @see #onHoverChanged
10997     */
10998    @ViewDebug.ExportedProperty
10999    public boolean isHovered() {
11000        return (mPrivateFlags & PFLAG_HOVERED) != 0;
11001    }
11002
11003    /**
11004     * Sets whether the view is currently hovered.
11005     * <p>
11006     * Calling this method also changes the drawable state of the view.  This
11007     * enables the view to react to hover by using different drawable resources
11008     * to change its appearance.
11009     * </p><p>
11010     * The {@link #onHoverChanged} method is called when the hovered state changes.
11011     * </p>
11012     *
11013     * @param hovered True if the view is hovered.
11014     *
11015     * @see #isHovered
11016     * @see #onHoverChanged
11017     */
11018    public void setHovered(boolean hovered) {
11019        if (hovered) {
11020            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
11021                mPrivateFlags |= PFLAG_HOVERED;
11022                refreshDrawableState();
11023                onHoverChanged(true);
11024            }
11025        } else {
11026            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
11027                mPrivateFlags &= ~PFLAG_HOVERED;
11028                refreshDrawableState();
11029                onHoverChanged(false);
11030            }
11031        }
11032    }
11033
11034    /**
11035     * Implement this method to handle hover state changes.
11036     * <p>
11037     * This method is called whenever the hover state changes as a result of a
11038     * call to {@link #setHovered}.
11039     * </p>
11040     *
11041     * @param hovered The current hover state, as returned by {@link #isHovered}.
11042     *
11043     * @see #isHovered
11044     * @see #setHovered
11045     */
11046    public void onHoverChanged(boolean hovered) {
11047    }
11048
11049    /**
11050     * Handles scroll bar dragging by mouse input.
11051     *
11052     * @hide
11053     * @param event The motion event.
11054     *
11055     * @return true if the event was handled as a scroll bar dragging, false otherwise.
11056     */
11057    protected boolean handleScrollBarDragging(MotionEvent event) {
11058        if (mScrollCache == null) {
11059            return false;
11060        }
11061        final float x = event.getX();
11062        final float y = event.getY();
11063        final int action = event.getAction();
11064        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
11065                && action != MotionEvent.ACTION_DOWN)
11066                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
11067                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
11068            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11069            return false;
11070        }
11071
11072        switch (action) {
11073            case MotionEvent.ACTION_MOVE:
11074                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
11075                    return false;
11076                }
11077                if (mScrollCache.mScrollBarDraggingState
11078                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
11079                    final Rect bounds = mScrollCache.mScrollBarBounds;
11080                    getVerticalScrollBarBounds(bounds);
11081                    final int range = computeVerticalScrollRange();
11082                    final int offset = computeVerticalScrollOffset();
11083                    final int extent = computeVerticalScrollExtent();
11084
11085                    final int thumbLength = ScrollBarUtils.getThumbLength(
11086                            bounds.height(), bounds.width(), extent, range);
11087                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11088                            bounds.height(), thumbLength, extent, range, offset);
11089
11090                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
11091                    final float maxThumbOffset = bounds.height() - thumbLength;
11092                    final float newThumbOffset =
11093                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11094                    final int height = getHeight();
11095                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11096                            && height > 0 && extent > 0) {
11097                        final int newY = Math.round((range - extent)
11098                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
11099                        if (newY != getScrollY()) {
11100                            mScrollCache.mScrollBarDraggingPos = y;
11101                            setScrollY(newY);
11102                        }
11103                    }
11104                    return true;
11105                }
11106                if (mScrollCache.mScrollBarDraggingState
11107                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
11108                    final Rect bounds = mScrollCache.mScrollBarBounds;
11109                    getHorizontalScrollBarBounds(bounds);
11110                    final int range = computeHorizontalScrollRange();
11111                    final int offset = computeHorizontalScrollOffset();
11112                    final int extent = computeHorizontalScrollExtent();
11113
11114                    final int thumbLength = ScrollBarUtils.getThumbLength(
11115                            bounds.width(), bounds.height(), extent, range);
11116                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11117                            bounds.width(), thumbLength, extent, range, offset);
11118
11119                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
11120                    final float maxThumbOffset = bounds.width() - thumbLength;
11121                    final float newThumbOffset =
11122                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11123                    final int width = getWidth();
11124                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11125                            && width > 0 && extent > 0) {
11126                        final int newX = Math.round((range - extent)
11127                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
11128                        if (newX != getScrollX()) {
11129                            mScrollCache.mScrollBarDraggingPos = x;
11130                            setScrollX(newX);
11131                        }
11132                    }
11133                    return true;
11134                }
11135            case MotionEvent.ACTION_DOWN:
11136                if (mScrollCache.state == ScrollabilityCache.OFF) {
11137                    return false;
11138                }
11139                if (isOnVerticalScrollbarThumb(x, y)) {
11140                    mScrollCache.mScrollBarDraggingState =
11141                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
11142                    mScrollCache.mScrollBarDraggingPos = y;
11143                    return true;
11144                }
11145                if (isOnHorizontalScrollbarThumb(x, y)) {
11146                    mScrollCache.mScrollBarDraggingState =
11147                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
11148                    mScrollCache.mScrollBarDraggingPos = x;
11149                    return true;
11150                }
11151        }
11152        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11153        return false;
11154    }
11155
11156    /**
11157     * Implement this method to handle touch screen motion events.
11158     * <p>
11159     * If this method is used to detect click actions, it is recommended that
11160     * the actions be performed by implementing and calling
11161     * {@link #performClick()}. This will ensure consistent system behavior,
11162     * including:
11163     * <ul>
11164     * <li>obeying click sound preferences
11165     * <li>dispatching OnClickListener calls
11166     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
11167     * accessibility features are enabled
11168     * </ul>
11169     *
11170     * @param event The motion event.
11171     * @return True if the event was handled, false otherwise.
11172     */
11173    public boolean onTouchEvent(MotionEvent event) {
11174        final float x = event.getX();
11175        final float y = event.getY();
11176        final int viewFlags = mViewFlags;
11177        final int action = event.getAction();
11178
11179        if ((viewFlags & ENABLED_MASK) == DISABLED) {
11180            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
11181                setPressed(false);
11182            }
11183            // A disabled view that is clickable still consumes the touch
11184            // events, it just doesn't respond to them.
11185            return (((viewFlags & CLICKABLE) == CLICKABLE
11186                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
11187                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
11188        }
11189        if (mTouchDelegate != null) {
11190            if (mTouchDelegate.onTouchEvent(event)) {
11191                return true;
11192            }
11193        }
11194
11195        if (((viewFlags & CLICKABLE) == CLICKABLE ||
11196                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
11197                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
11198            switch (action) {
11199                case MotionEvent.ACTION_UP:
11200                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
11201                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
11202                        // take focus if we don't have it already and we should in
11203                        // touch mode.
11204                        boolean focusTaken = false;
11205                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
11206                            focusTaken = requestFocus();
11207                        }
11208
11209                        if (prepressed) {
11210                            // The button is being released before we actually
11211                            // showed it as pressed.  Make it show the pressed
11212                            // state now (before scheduling the click) to ensure
11213                            // the user sees it.
11214                            setPressed(true, x, y);
11215                       }
11216
11217                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
11218                            // This is a tap, so remove the longpress check
11219                            removeLongPressCallback();
11220
11221                            // Only perform take click actions if we were in the pressed state
11222                            if (!focusTaken) {
11223                                // Use a Runnable and post this rather than calling
11224                                // performClick directly. This lets other visual state
11225                                // of the view update before click actions start.
11226                                if (mPerformClick == null) {
11227                                    mPerformClick = new PerformClick();
11228                                }
11229                                if (!post(mPerformClick)) {
11230                                    performClick();
11231                                }
11232                            }
11233                        }
11234
11235                        if (mUnsetPressedState == null) {
11236                            mUnsetPressedState = new UnsetPressedState();
11237                        }
11238
11239                        if (prepressed) {
11240                            postDelayed(mUnsetPressedState,
11241                                    ViewConfiguration.getPressedStateDuration());
11242                        } else if (!post(mUnsetPressedState)) {
11243                            // If the post failed, unpress right now
11244                            mUnsetPressedState.run();
11245                        }
11246
11247                        removeTapCallback();
11248                    }
11249                    mIgnoreNextUpEvent = false;
11250                    break;
11251
11252                case MotionEvent.ACTION_DOWN:
11253                    mHasPerformedLongPress = false;
11254
11255                    if (performButtonActionOnTouchDown(event)) {
11256                        break;
11257                    }
11258
11259                    // Walk up the hierarchy to determine if we're inside a scrolling container.
11260                    boolean isInScrollingContainer = isInScrollingContainer();
11261
11262                    // For views inside a scrolling container, delay the pressed feedback for
11263                    // a short period in case this is a scroll.
11264                    if (isInScrollingContainer) {
11265                        mPrivateFlags |= PFLAG_PREPRESSED;
11266                        if (mPendingCheckForTap == null) {
11267                            mPendingCheckForTap = new CheckForTap();
11268                        }
11269                        mPendingCheckForTap.x = event.getX();
11270                        mPendingCheckForTap.y = event.getY();
11271                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
11272                    } else {
11273                        // Not inside a scrolling container, so show the feedback right away
11274                        setPressed(true, x, y);
11275                        checkForLongClick(0, x, y);
11276                    }
11277                    break;
11278
11279                case MotionEvent.ACTION_CANCEL:
11280                    setPressed(false);
11281                    removeTapCallback();
11282                    removeLongPressCallback();
11283                    mInContextButtonPress = false;
11284                    mHasPerformedLongPress = false;
11285                    mIgnoreNextUpEvent = false;
11286                    break;
11287
11288                case MotionEvent.ACTION_MOVE:
11289                    drawableHotspotChanged(x, y);
11290
11291                    // Be lenient about moving outside of buttons
11292                    if (!pointInView(x, y, mTouchSlop)) {
11293                        // Outside button
11294                        removeTapCallback();
11295                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
11296                            // Remove any future long press/tap checks
11297                            removeLongPressCallback();
11298
11299                            setPressed(false);
11300                        }
11301                    }
11302                    break;
11303            }
11304
11305            return true;
11306        }
11307
11308        return false;
11309    }
11310
11311    /**
11312     * @hide
11313     */
11314    public boolean isInScrollingContainer() {
11315        ViewParent p = getParent();
11316        while (p != null && p instanceof ViewGroup) {
11317            if (((ViewGroup) p).shouldDelayChildPressedState()) {
11318                return true;
11319            }
11320            p = p.getParent();
11321        }
11322        return false;
11323    }
11324
11325    /**
11326     * Remove the longpress detection timer.
11327     */
11328    private void removeLongPressCallback() {
11329        if (mPendingCheckForLongPress != null) {
11330          removeCallbacks(mPendingCheckForLongPress);
11331        }
11332    }
11333
11334    /**
11335     * Remove the pending click action
11336     */
11337    private void removePerformClickCallback() {
11338        if (mPerformClick != null) {
11339            removeCallbacks(mPerformClick);
11340        }
11341    }
11342
11343    /**
11344     * Remove the prepress detection timer.
11345     */
11346    private void removeUnsetPressCallback() {
11347        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
11348            setPressed(false);
11349            removeCallbacks(mUnsetPressedState);
11350        }
11351    }
11352
11353    /**
11354     * Remove the tap detection timer.
11355     */
11356    private void removeTapCallback() {
11357        if (mPendingCheckForTap != null) {
11358            mPrivateFlags &= ~PFLAG_PREPRESSED;
11359            removeCallbacks(mPendingCheckForTap);
11360        }
11361    }
11362
11363    /**
11364     * Cancels a pending long press.  Your subclass can use this if you
11365     * want the context menu to come up if the user presses and holds
11366     * at the same place, but you don't want it to come up if they press
11367     * and then move around enough to cause scrolling.
11368     */
11369    public void cancelLongPress() {
11370        removeLongPressCallback();
11371
11372        /*
11373         * The prepressed state handled by the tap callback is a display
11374         * construct, but the tap callback will post a long press callback
11375         * less its own timeout. Remove it here.
11376         */
11377        removeTapCallback();
11378    }
11379
11380    /**
11381     * Remove the pending callback for sending a
11382     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
11383     */
11384    private void removeSendViewScrolledAccessibilityEventCallback() {
11385        if (mSendViewScrolledAccessibilityEvent != null) {
11386            removeCallbacks(mSendViewScrolledAccessibilityEvent);
11387            mSendViewScrolledAccessibilityEvent.mIsPending = false;
11388        }
11389    }
11390
11391    /**
11392     * Sets the TouchDelegate for this View.
11393     */
11394    public void setTouchDelegate(TouchDelegate delegate) {
11395        mTouchDelegate = delegate;
11396    }
11397
11398    /**
11399     * Gets the TouchDelegate for this View.
11400     */
11401    public TouchDelegate getTouchDelegate() {
11402        return mTouchDelegate;
11403    }
11404
11405    /**
11406     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
11407     *
11408     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
11409     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
11410     * available. This method should only be called for touch events.
11411     *
11412     * <p class="note">This api is not intended for most applications. Buffered dispatch
11413     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
11414     * streams will not improve your input latency. Side effects include: increased latency,
11415     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
11416     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
11417     * you.</p>
11418     */
11419    public final void requestUnbufferedDispatch(MotionEvent event) {
11420        final int action = event.getAction();
11421        if (mAttachInfo == null
11422                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
11423                || !event.isTouchEvent()) {
11424            return;
11425        }
11426        mAttachInfo.mUnbufferedDispatchRequested = true;
11427    }
11428
11429    /**
11430     * Set flags controlling behavior of this view.
11431     *
11432     * @param flags Constant indicating the value which should be set
11433     * @param mask Constant indicating the bit range that should be changed
11434     */
11435    void setFlags(int flags, int mask) {
11436        final boolean accessibilityEnabled =
11437                AccessibilityManager.getInstance(mContext).isEnabled();
11438        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
11439
11440        int old = mViewFlags;
11441        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
11442
11443        int changed = mViewFlags ^ old;
11444        if (changed == 0) {
11445            return;
11446        }
11447        int privateFlags = mPrivateFlags;
11448
11449        /* Check if the FOCUSABLE bit has changed */
11450        if (((changed & FOCUSABLE_MASK) != 0) &&
11451                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
11452            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
11453                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
11454                /* Give up focus if we are no longer focusable */
11455                clearFocus();
11456            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
11457                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
11458                /*
11459                 * Tell the view system that we are now available to take focus
11460                 * if no one else already has it.
11461                 */
11462                if (mParent != null) mParent.focusableViewAvailable(this);
11463            }
11464        }
11465
11466        final int newVisibility = flags & VISIBILITY_MASK;
11467        if (newVisibility == VISIBLE) {
11468            if ((changed & VISIBILITY_MASK) != 0) {
11469                /*
11470                 * If this view is becoming visible, invalidate it in case it changed while
11471                 * it was not visible. Marking it drawn ensures that the invalidation will
11472                 * go through.
11473                 */
11474                mPrivateFlags |= PFLAG_DRAWN;
11475                invalidate(true);
11476
11477                needGlobalAttributesUpdate(true);
11478
11479                // a view becoming visible is worth notifying the parent
11480                // about in case nothing has focus.  even if this specific view
11481                // isn't focusable, it may contain something that is, so let
11482                // the root view try to give this focus if nothing else does.
11483                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
11484                    mParent.focusableViewAvailable(this);
11485                }
11486            }
11487        }
11488
11489        /* Check if the GONE bit has changed */
11490        if ((changed & GONE) != 0) {
11491            needGlobalAttributesUpdate(false);
11492            requestLayout();
11493
11494            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
11495                if (hasFocus()) clearFocus();
11496                clearAccessibilityFocus();
11497                destroyDrawingCache();
11498                if (mParent instanceof View) {
11499                    // GONE views noop invalidation, so invalidate the parent
11500                    ((View) mParent).invalidate(true);
11501                }
11502                // Mark the view drawn to ensure that it gets invalidated properly the next
11503                // time it is visible and gets invalidated
11504                mPrivateFlags |= PFLAG_DRAWN;
11505            }
11506            if (mAttachInfo != null) {
11507                mAttachInfo.mViewVisibilityChanged = true;
11508            }
11509        }
11510
11511        /* Check if the VISIBLE bit has changed */
11512        if ((changed & INVISIBLE) != 0) {
11513            needGlobalAttributesUpdate(false);
11514            /*
11515             * If this view is becoming invisible, set the DRAWN flag so that
11516             * the next invalidate() will not be skipped.
11517             */
11518            mPrivateFlags |= PFLAG_DRAWN;
11519
11520            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
11521                // root view becoming invisible shouldn't clear focus and accessibility focus
11522                if (getRootView() != this) {
11523                    if (hasFocus()) clearFocus();
11524                    clearAccessibilityFocus();
11525                }
11526            }
11527            if (mAttachInfo != null) {
11528                mAttachInfo.mViewVisibilityChanged = true;
11529            }
11530        }
11531
11532        if ((changed & VISIBILITY_MASK) != 0) {
11533            // If the view is invisible, cleanup its display list to free up resources
11534            if (newVisibility != VISIBLE && mAttachInfo != null) {
11535                cleanupDraw();
11536            }
11537
11538            if (mParent instanceof ViewGroup) {
11539                ((ViewGroup) mParent).onChildVisibilityChanged(this,
11540                        (changed & VISIBILITY_MASK), newVisibility);
11541                ((View) mParent).invalidate(true);
11542            } else if (mParent != null) {
11543                mParent.invalidateChild(this, null);
11544            }
11545
11546            if (mAttachInfo != null) {
11547                dispatchVisibilityChanged(this, newVisibility);
11548
11549                // Aggregated visibility changes are dispatched to attached views
11550                // in visible windows where the parent is currently shown/drawn
11551                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
11552                // discounting clipping or overlapping. This makes it a good place
11553                // to change animation states.
11554                if (mParent != null && getWindowVisibility() == VISIBLE &&
11555                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
11556                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
11557                }
11558                notifySubtreeAccessibilityStateChangedIfNeeded();
11559            }
11560        }
11561
11562        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
11563            destroyDrawingCache();
11564        }
11565
11566        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
11567            destroyDrawingCache();
11568            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11569            invalidateParentCaches();
11570        }
11571
11572        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
11573            destroyDrawingCache();
11574            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11575        }
11576
11577        if ((changed & DRAW_MASK) != 0) {
11578            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
11579                if (mBackground != null
11580                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
11581                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11582                } else {
11583                    mPrivateFlags |= PFLAG_SKIP_DRAW;
11584                }
11585            } else {
11586                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11587            }
11588            requestLayout();
11589            invalidate(true);
11590        }
11591
11592        if ((changed & KEEP_SCREEN_ON) != 0) {
11593            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
11594                mParent.recomputeViewAttributes(this);
11595            }
11596        }
11597
11598        if (accessibilityEnabled) {
11599            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
11600                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
11601                    || (changed & CONTEXT_CLICKABLE) != 0) {
11602                if (oldIncludeForAccessibility != includeForAccessibility()) {
11603                    notifySubtreeAccessibilityStateChangedIfNeeded();
11604                } else {
11605                    notifyViewAccessibilityStateChangedIfNeeded(
11606                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11607                }
11608            } else if ((changed & ENABLED_MASK) != 0) {
11609                notifyViewAccessibilityStateChangedIfNeeded(
11610                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11611            }
11612        }
11613    }
11614
11615    /**
11616     * Change the view's z order in the tree, so it's on top of other sibling
11617     * views. This ordering change may affect layout, if the parent container
11618     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
11619     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
11620     * method should be followed by calls to {@link #requestLayout()} and
11621     * {@link View#invalidate()} on the view's parent to force the parent to redraw
11622     * with the new child ordering.
11623     *
11624     * @see ViewGroup#bringChildToFront(View)
11625     */
11626    public void bringToFront() {
11627        if (mParent != null) {
11628            mParent.bringChildToFront(this);
11629        }
11630    }
11631
11632    /**
11633     * This is called in response to an internal scroll in this view (i.e., the
11634     * view scrolled its own contents). This is typically as a result of
11635     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
11636     * called.
11637     *
11638     * @param l Current horizontal scroll origin.
11639     * @param t Current vertical scroll origin.
11640     * @param oldl Previous horizontal scroll origin.
11641     * @param oldt Previous vertical scroll origin.
11642     */
11643    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
11644        notifySubtreeAccessibilityStateChangedIfNeeded();
11645
11646        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11647            postSendViewScrolledAccessibilityEventCallback();
11648        }
11649
11650        mBackgroundSizeChanged = true;
11651        if (mForegroundInfo != null) {
11652            mForegroundInfo.mBoundsChanged = true;
11653        }
11654
11655        final AttachInfo ai = mAttachInfo;
11656        if (ai != null) {
11657            ai.mViewScrollChanged = true;
11658        }
11659
11660        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
11661            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
11662        }
11663    }
11664
11665    /**
11666     * Interface definition for a callback to be invoked when the scroll
11667     * X or Y positions of a view change.
11668     * <p>
11669     * <b>Note:</b> Some views handle scrolling independently from View and may
11670     * have their own separate listeners for scroll-type events. For example,
11671     * {@link android.widget.ListView ListView} allows clients to register an
11672     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
11673     * to listen for changes in list scroll position.
11674     *
11675     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
11676     */
11677    public interface OnScrollChangeListener {
11678        /**
11679         * Called when the scroll position of a view changes.
11680         *
11681         * @param v The view whose scroll position has changed.
11682         * @param scrollX Current horizontal scroll origin.
11683         * @param scrollY Current vertical scroll origin.
11684         * @param oldScrollX Previous horizontal scroll origin.
11685         * @param oldScrollY Previous vertical scroll origin.
11686         */
11687        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
11688    }
11689
11690    /**
11691     * Interface definition for a callback to be invoked when the layout bounds of a view
11692     * changes due to layout processing.
11693     */
11694    public interface OnLayoutChangeListener {
11695        /**
11696         * Called when the layout bounds of a view changes due to layout processing.
11697         *
11698         * @param v The view whose bounds have changed.
11699         * @param left The new value of the view's left property.
11700         * @param top The new value of the view's top property.
11701         * @param right The new value of the view's right property.
11702         * @param bottom The new value of the view's bottom property.
11703         * @param oldLeft The previous value of the view's left property.
11704         * @param oldTop The previous value of the view's top property.
11705         * @param oldRight The previous value of the view's right property.
11706         * @param oldBottom The previous value of the view's bottom property.
11707         */
11708        void onLayoutChange(View v, int left, int top, int right, int bottom,
11709            int oldLeft, int oldTop, int oldRight, int oldBottom);
11710    }
11711
11712    /**
11713     * This is called during layout when the size of this view has changed. If
11714     * you were just added to the view hierarchy, you're called with the old
11715     * values of 0.
11716     *
11717     * @param w Current width of this view.
11718     * @param h Current height of this view.
11719     * @param oldw Old width of this view.
11720     * @param oldh Old height of this view.
11721     */
11722    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
11723    }
11724
11725    /**
11726     * Called by draw to draw the child views. This may be overridden
11727     * by derived classes to gain control just before its children are drawn
11728     * (but after its own view has been drawn).
11729     * @param canvas the canvas on which to draw the view
11730     */
11731    protected void dispatchDraw(Canvas canvas) {
11732
11733    }
11734
11735    /**
11736     * Gets the parent of this view. Note that the parent is a
11737     * ViewParent and not necessarily a View.
11738     *
11739     * @return Parent of this view.
11740     */
11741    public final ViewParent getParent() {
11742        return mParent;
11743    }
11744
11745    /**
11746     * Set the horizontal scrolled position of your view. This will cause a call to
11747     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11748     * invalidated.
11749     * @param value the x position to scroll to
11750     */
11751    public void setScrollX(int value) {
11752        scrollTo(value, mScrollY);
11753    }
11754
11755    /**
11756     * Set the vertical scrolled position of your view. This will cause a call to
11757     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11758     * invalidated.
11759     * @param value the y position to scroll to
11760     */
11761    public void setScrollY(int value) {
11762        scrollTo(mScrollX, value);
11763    }
11764
11765    /**
11766     * Return the scrolled left position of this view. This is the left edge of
11767     * the displayed part of your view. You do not need to draw any pixels
11768     * farther left, since those are outside of the frame of your view on
11769     * screen.
11770     *
11771     * @return The left edge of the displayed part of your view, in pixels.
11772     */
11773    public final int getScrollX() {
11774        return mScrollX;
11775    }
11776
11777    /**
11778     * Return the scrolled top position of this view. This is the top edge of
11779     * the displayed part of your view. You do not need to draw any pixels above
11780     * it, since those are outside of the frame of your view on screen.
11781     *
11782     * @return The top edge of the displayed part of your view, in pixels.
11783     */
11784    public final int getScrollY() {
11785        return mScrollY;
11786    }
11787
11788    /**
11789     * Return the width of the your view.
11790     *
11791     * @return The width of your view, in pixels.
11792     */
11793    @ViewDebug.ExportedProperty(category = "layout")
11794    public final int getWidth() {
11795        return mRight - mLeft;
11796    }
11797
11798    /**
11799     * Return the height of your view.
11800     *
11801     * @return The height of your view, in pixels.
11802     */
11803    @ViewDebug.ExportedProperty(category = "layout")
11804    public final int getHeight() {
11805        return mBottom - mTop;
11806    }
11807
11808    /**
11809     * Return the visible drawing bounds of your view. Fills in the output
11810     * rectangle with the values from getScrollX(), getScrollY(),
11811     * getWidth(), and getHeight(). These bounds do not account for any
11812     * transformation properties currently set on the view, such as
11813     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11814     *
11815     * @param outRect The (scrolled) drawing bounds of the view.
11816     */
11817    public void getDrawingRect(Rect outRect) {
11818        outRect.left = mScrollX;
11819        outRect.top = mScrollY;
11820        outRect.right = mScrollX + (mRight - mLeft);
11821        outRect.bottom = mScrollY + (mBottom - mTop);
11822    }
11823
11824    /**
11825     * Like {@link #getMeasuredWidthAndState()}, but only returns the
11826     * raw width component (that is the result is masked by
11827     * {@link #MEASURED_SIZE_MASK}).
11828     *
11829     * @return The raw measured width of this view.
11830     */
11831    public final int getMeasuredWidth() {
11832        return mMeasuredWidth & MEASURED_SIZE_MASK;
11833    }
11834
11835    /**
11836     * Return the full width measurement information for this view as computed
11837     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11838     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11839     * This should be used during measurement and layout calculations only. Use
11840     * {@link #getWidth()} to see how wide a view is after layout.
11841     *
11842     * @return The measured width of this view as a bit mask.
11843     */
11844    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11845            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11846                    name = "MEASURED_STATE_TOO_SMALL"),
11847    })
11848    public final int getMeasuredWidthAndState() {
11849        return mMeasuredWidth;
11850    }
11851
11852    /**
11853     * Like {@link #getMeasuredHeightAndState()}, but only returns the
11854     * raw height component (that is the result is masked by
11855     * {@link #MEASURED_SIZE_MASK}).
11856     *
11857     * @return The raw measured height of this view.
11858     */
11859    public final int getMeasuredHeight() {
11860        return mMeasuredHeight & MEASURED_SIZE_MASK;
11861    }
11862
11863    /**
11864     * Return the full height measurement information for this view as computed
11865     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11866     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11867     * This should be used during measurement and layout calculations only. Use
11868     * {@link #getHeight()} to see how wide a view is after layout.
11869     *
11870     * @return The measured height of this view as a bit mask.
11871     */
11872    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11873            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11874                    name = "MEASURED_STATE_TOO_SMALL"),
11875    })
11876    public final int getMeasuredHeightAndState() {
11877        return mMeasuredHeight;
11878    }
11879
11880    /**
11881     * Return only the state bits of {@link #getMeasuredWidthAndState()}
11882     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11883     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11884     * and the height component is at the shifted bits
11885     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11886     */
11887    public final int getMeasuredState() {
11888        return (mMeasuredWidth&MEASURED_STATE_MASK)
11889                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11890                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11891    }
11892
11893    /**
11894     * The transform matrix of this view, which is calculated based on the current
11895     * rotation, scale, and pivot properties.
11896     *
11897     * @see #getRotation()
11898     * @see #getScaleX()
11899     * @see #getScaleY()
11900     * @see #getPivotX()
11901     * @see #getPivotY()
11902     * @return The current transform matrix for the view
11903     */
11904    public Matrix getMatrix() {
11905        ensureTransformationInfo();
11906        final Matrix matrix = mTransformationInfo.mMatrix;
11907        mRenderNode.getMatrix(matrix);
11908        return matrix;
11909    }
11910
11911    /**
11912     * Returns true if the transform matrix is the identity matrix.
11913     * Recomputes the matrix if necessary.
11914     *
11915     * @return True if the transform matrix is the identity matrix, false otherwise.
11916     */
11917    final boolean hasIdentityMatrix() {
11918        return mRenderNode.hasIdentityMatrix();
11919    }
11920
11921    void ensureTransformationInfo() {
11922        if (mTransformationInfo == null) {
11923            mTransformationInfo = new TransformationInfo();
11924        }
11925    }
11926
11927    /**
11928     * Utility method to retrieve the inverse of the current mMatrix property.
11929     * We cache the matrix to avoid recalculating it when transform properties
11930     * have not changed.
11931     *
11932     * @return The inverse of the current matrix of this view.
11933     * @hide
11934     */
11935    public final Matrix getInverseMatrix() {
11936        ensureTransformationInfo();
11937        if (mTransformationInfo.mInverseMatrix == null) {
11938            mTransformationInfo.mInverseMatrix = new Matrix();
11939        }
11940        final Matrix matrix = mTransformationInfo.mInverseMatrix;
11941        mRenderNode.getInverseMatrix(matrix);
11942        return matrix;
11943    }
11944
11945    /**
11946     * Gets the distance along the Z axis from the camera to this view.
11947     *
11948     * @see #setCameraDistance(float)
11949     *
11950     * @return The distance along the Z axis.
11951     */
11952    public float getCameraDistance() {
11953        final float dpi = mResources.getDisplayMetrics().densityDpi;
11954        return -(mRenderNode.getCameraDistance() * dpi);
11955    }
11956
11957    /**
11958     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11959     * views are drawn) from the camera to this view. The camera's distance
11960     * affects 3D transformations, for instance rotations around the X and Y
11961     * axis. If the rotationX or rotationY properties are changed and this view is
11962     * large (more than half the size of the screen), it is recommended to always
11963     * use a camera distance that's greater than the height (X axis rotation) or
11964     * the width (Y axis rotation) of this view.</p>
11965     *
11966     * <p>The distance of the camera from the view plane can have an affect on the
11967     * perspective distortion of the view when it is rotated around the x or y axis.
11968     * For example, a large distance will result in a large viewing angle, and there
11969     * will not be much perspective distortion of the view as it rotates. A short
11970     * distance may cause much more perspective distortion upon rotation, and can
11971     * also result in some drawing artifacts if the rotated view ends up partially
11972     * behind the camera (which is why the recommendation is to use a distance at
11973     * least as far as the size of the view, if the view is to be rotated.)</p>
11974     *
11975     * <p>The distance is expressed in "depth pixels." The default distance depends
11976     * on the screen density. For instance, on a medium density display, the
11977     * default distance is 1280. On a high density display, the default distance
11978     * is 1920.</p>
11979     *
11980     * <p>If you want to specify a distance that leads to visually consistent
11981     * results across various densities, use the following formula:</p>
11982     * <pre>
11983     * float scale = context.getResources().getDisplayMetrics().density;
11984     * view.setCameraDistance(distance * scale);
11985     * </pre>
11986     *
11987     * <p>The density scale factor of a high density display is 1.5,
11988     * and 1920 = 1280 * 1.5.</p>
11989     *
11990     * @param distance The distance in "depth pixels", if negative the opposite
11991     *        value is used
11992     *
11993     * @see #setRotationX(float)
11994     * @see #setRotationY(float)
11995     */
11996    public void setCameraDistance(float distance) {
11997        final float dpi = mResources.getDisplayMetrics().densityDpi;
11998
11999        invalidateViewProperty(true, false);
12000        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
12001        invalidateViewProperty(false, false);
12002
12003        invalidateParentIfNeededAndWasQuickRejected();
12004    }
12005
12006    /**
12007     * The degrees that the view is rotated around the pivot point.
12008     *
12009     * @see #setRotation(float)
12010     * @see #getPivotX()
12011     * @see #getPivotY()
12012     *
12013     * @return The degrees of rotation.
12014     */
12015    @ViewDebug.ExportedProperty(category = "drawing")
12016    public float getRotation() {
12017        return mRenderNode.getRotation();
12018    }
12019
12020    /**
12021     * Sets the degrees that the view is rotated around the pivot point. Increasing values
12022     * result in clockwise rotation.
12023     *
12024     * @param rotation The degrees of rotation.
12025     *
12026     * @see #getRotation()
12027     * @see #getPivotX()
12028     * @see #getPivotY()
12029     * @see #setRotationX(float)
12030     * @see #setRotationY(float)
12031     *
12032     * @attr ref android.R.styleable#View_rotation
12033     */
12034    public void setRotation(float rotation) {
12035        if (rotation != getRotation()) {
12036            // Double-invalidation is necessary to capture view's old and new areas
12037            invalidateViewProperty(true, false);
12038            mRenderNode.setRotation(rotation);
12039            invalidateViewProperty(false, true);
12040
12041            invalidateParentIfNeededAndWasQuickRejected();
12042            notifySubtreeAccessibilityStateChangedIfNeeded();
12043        }
12044    }
12045
12046    /**
12047     * The degrees that the view is rotated around the vertical axis through the pivot point.
12048     *
12049     * @see #getPivotX()
12050     * @see #getPivotY()
12051     * @see #setRotationY(float)
12052     *
12053     * @return The degrees of Y rotation.
12054     */
12055    @ViewDebug.ExportedProperty(category = "drawing")
12056    public float getRotationY() {
12057        return mRenderNode.getRotationY();
12058    }
12059
12060    /**
12061     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
12062     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
12063     * down the y axis.
12064     *
12065     * When rotating large views, it is recommended to adjust the camera distance
12066     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12067     *
12068     * @param rotationY The degrees of Y rotation.
12069     *
12070     * @see #getRotationY()
12071     * @see #getPivotX()
12072     * @see #getPivotY()
12073     * @see #setRotation(float)
12074     * @see #setRotationX(float)
12075     * @see #setCameraDistance(float)
12076     *
12077     * @attr ref android.R.styleable#View_rotationY
12078     */
12079    public void setRotationY(float rotationY) {
12080        if (rotationY != getRotationY()) {
12081            invalidateViewProperty(true, false);
12082            mRenderNode.setRotationY(rotationY);
12083            invalidateViewProperty(false, true);
12084
12085            invalidateParentIfNeededAndWasQuickRejected();
12086            notifySubtreeAccessibilityStateChangedIfNeeded();
12087        }
12088    }
12089
12090    /**
12091     * The degrees that the view is rotated around the horizontal axis through the pivot point.
12092     *
12093     * @see #getPivotX()
12094     * @see #getPivotY()
12095     * @see #setRotationX(float)
12096     *
12097     * @return The degrees of X rotation.
12098     */
12099    @ViewDebug.ExportedProperty(category = "drawing")
12100    public float getRotationX() {
12101        return mRenderNode.getRotationX();
12102    }
12103
12104    /**
12105     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
12106     * Increasing values result in clockwise rotation from the viewpoint of looking down the
12107     * x axis.
12108     *
12109     * When rotating large views, it is recommended to adjust the camera distance
12110     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12111     *
12112     * @param rotationX The degrees of X rotation.
12113     *
12114     * @see #getRotationX()
12115     * @see #getPivotX()
12116     * @see #getPivotY()
12117     * @see #setRotation(float)
12118     * @see #setRotationY(float)
12119     * @see #setCameraDistance(float)
12120     *
12121     * @attr ref android.R.styleable#View_rotationX
12122     */
12123    public void setRotationX(float rotationX) {
12124        if (rotationX != getRotationX()) {
12125            invalidateViewProperty(true, false);
12126            mRenderNode.setRotationX(rotationX);
12127            invalidateViewProperty(false, true);
12128
12129            invalidateParentIfNeededAndWasQuickRejected();
12130            notifySubtreeAccessibilityStateChangedIfNeeded();
12131        }
12132    }
12133
12134    /**
12135     * The amount that the view is scaled in x around the pivot point, as a proportion of
12136     * the view's unscaled width. 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 getScaleX() {
12146        return mRenderNode.getScaleX();
12147    }
12148
12149    /**
12150     * Sets the amount that the view is scaled in x 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 scaleX The scaling factor.
12154     * @see #getPivotX()
12155     * @see #getPivotY()
12156     *
12157     * @attr ref android.R.styleable#View_scaleX
12158     */
12159    public void setScaleX(float scaleX) {
12160        if (scaleX != getScaleX()) {
12161            invalidateViewProperty(true, false);
12162            mRenderNode.setScaleX(scaleX);
12163            invalidateViewProperty(false, true);
12164
12165            invalidateParentIfNeededAndWasQuickRejected();
12166            notifySubtreeAccessibilityStateChangedIfNeeded();
12167        }
12168    }
12169
12170    /**
12171     * The amount that the view is scaled in y around the pivot point, as a proportion of
12172     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
12173     *
12174     * <p>By default, this is 1.0f.
12175     *
12176     * @see #getPivotX()
12177     * @see #getPivotY()
12178     * @return The scaling factor.
12179     */
12180    @ViewDebug.ExportedProperty(category = "drawing")
12181    public float getScaleY() {
12182        return mRenderNode.getScaleY();
12183    }
12184
12185    /**
12186     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
12187     * the view's unscaled width. A value of 1 means that no scaling is applied.
12188     *
12189     * @param scaleY The scaling factor.
12190     * @see #getPivotX()
12191     * @see #getPivotY()
12192     *
12193     * @attr ref android.R.styleable#View_scaleY
12194     */
12195    public void setScaleY(float scaleY) {
12196        if (scaleY != getScaleY()) {
12197            invalidateViewProperty(true, false);
12198            mRenderNode.setScaleY(scaleY);
12199            invalidateViewProperty(false, true);
12200
12201            invalidateParentIfNeededAndWasQuickRejected();
12202            notifySubtreeAccessibilityStateChangedIfNeeded();
12203        }
12204    }
12205
12206    /**
12207     * The x location of the point around which the view is {@link #setRotation(float) rotated}
12208     * and {@link #setScaleX(float) scaled}.
12209     *
12210     * @see #getRotation()
12211     * @see #getScaleX()
12212     * @see #getScaleY()
12213     * @see #getPivotY()
12214     * @return The x location of the pivot point.
12215     *
12216     * @attr ref android.R.styleable#View_transformPivotX
12217     */
12218    @ViewDebug.ExportedProperty(category = "drawing")
12219    public float getPivotX() {
12220        return mRenderNode.getPivotX();
12221    }
12222
12223    /**
12224     * Sets the x location of the point around which the view is
12225     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
12226     * By default, the pivot point is centered on the object.
12227     * Setting this property disables this behavior and causes the view to use only the
12228     * explicitly set pivotX and pivotY values.
12229     *
12230     * @param pivotX The x location of the pivot point.
12231     * @see #getRotation()
12232     * @see #getScaleX()
12233     * @see #getScaleY()
12234     * @see #getPivotY()
12235     *
12236     * @attr ref android.R.styleable#View_transformPivotX
12237     */
12238    public void setPivotX(float pivotX) {
12239        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
12240            invalidateViewProperty(true, false);
12241            mRenderNode.setPivotX(pivotX);
12242            invalidateViewProperty(false, true);
12243
12244            invalidateParentIfNeededAndWasQuickRejected();
12245        }
12246    }
12247
12248    /**
12249     * The y location of the point around which the view is {@link #setRotation(float) rotated}
12250     * and {@link #setScaleY(float) scaled}.
12251     *
12252     * @see #getRotation()
12253     * @see #getScaleX()
12254     * @see #getScaleY()
12255     * @see #getPivotY()
12256     * @return The y location of the pivot point.
12257     *
12258     * @attr ref android.R.styleable#View_transformPivotY
12259     */
12260    @ViewDebug.ExportedProperty(category = "drawing")
12261    public float getPivotY() {
12262        return mRenderNode.getPivotY();
12263    }
12264
12265    /**
12266     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
12267     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
12268     * Setting this property disables this behavior and causes the view to use only the
12269     * explicitly set pivotX and pivotY values.
12270     *
12271     * @param pivotY The y location of the pivot point.
12272     * @see #getRotation()
12273     * @see #getScaleX()
12274     * @see #getScaleY()
12275     * @see #getPivotY()
12276     *
12277     * @attr ref android.R.styleable#View_transformPivotY
12278     */
12279    public void setPivotY(float pivotY) {
12280        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
12281            invalidateViewProperty(true, false);
12282            mRenderNode.setPivotY(pivotY);
12283            invalidateViewProperty(false, true);
12284
12285            invalidateParentIfNeededAndWasQuickRejected();
12286        }
12287    }
12288
12289    /**
12290     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
12291     * completely transparent and 1 means the view is completely opaque.
12292     *
12293     * <p>By default this is 1.0f.
12294     * @return The opacity of the view.
12295     */
12296    @ViewDebug.ExportedProperty(category = "drawing")
12297    public float getAlpha() {
12298        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
12299    }
12300
12301    /**
12302     * Sets the behavior for overlapping rendering for this view (see {@link
12303     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
12304     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
12305     * providing the value which is then used internally. That is, when {@link
12306     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
12307     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
12308     * instead.
12309     *
12310     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
12311     * instead of that returned by {@link #hasOverlappingRendering()}.
12312     *
12313     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
12314     */
12315    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
12316        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
12317        if (hasOverlappingRendering) {
12318            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12319        } else {
12320            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12321        }
12322    }
12323
12324    /**
12325     * Returns the value for overlapping rendering that is used internally. This is either
12326     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
12327     * the return value of {@link #hasOverlappingRendering()}, otherwise.
12328     *
12329     * @return The value for overlapping rendering being used internally.
12330     */
12331    public final boolean getHasOverlappingRendering() {
12332        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
12333                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
12334                hasOverlappingRendering();
12335    }
12336
12337    /**
12338     * Returns whether this View has content which overlaps.
12339     *
12340     * <p>This function, intended to be overridden by specific View types, is an optimization when
12341     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
12342     * an offscreen buffer and then composited into place, which can be expensive. If the view has
12343     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
12344     * directly. An example of overlapping rendering is a TextView with a background image, such as
12345     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
12346     * ImageView with only the foreground image. The default implementation returns true; subclasses
12347     * should override if they have cases which can be optimized.</p>
12348     *
12349     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
12350     * necessitates that a View return true if it uses the methods internally without passing the
12351     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
12352     *
12353     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
12354     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
12355     *
12356     * @return true if the content in this view might overlap, false otherwise.
12357     */
12358    @ViewDebug.ExportedProperty(category = "drawing")
12359    public boolean hasOverlappingRendering() {
12360        return true;
12361    }
12362
12363    /**
12364     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
12365     * completely transparent and 1 means the view is completely opaque.
12366     *
12367     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
12368     * can have significant performance implications, especially for large views. It is best to use
12369     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
12370     *
12371     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
12372     * strongly recommended for performance reasons to either override
12373     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
12374     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
12375     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
12376     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
12377     * of rendering cost, even for simple or small views. Starting with
12378     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
12379     * applied to the view at the rendering level.</p>
12380     *
12381     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
12382     * responsible for applying the opacity itself.</p>
12383     *
12384     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
12385     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
12386     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
12387     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
12388     *
12389     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
12390     * value will clip a View to its bounds, unless the View returns <code>false</code> from
12391     * {@link #hasOverlappingRendering}.</p>
12392     *
12393     * @param alpha The opacity of the view.
12394     *
12395     * @see #hasOverlappingRendering()
12396     * @see #setLayerType(int, android.graphics.Paint)
12397     *
12398     * @attr ref android.R.styleable#View_alpha
12399     */
12400    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
12401        ensureTransformationInfo();
12402        if (mTransformationInfo.mAlpha != alpha) {
12403            // Report visibility changes, which can affect children, to accessibility
12404            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
12405                notifySubtreeAccessibilityStateChangedIfNeeded();
12406            }
12407            mTransformationInfo.mAlpha = alpha;
12408            if (onSetAlpha((int) (alpha * 255))) {
12409                mPrivateFlags |= PFLAG_ALPHA_SET;
12410                // subclass is handling alpha - don't optimize rendering cache invalidation
12411                invalidateParentCaches();
12412                invalidate(true);
12413            } else {
12414                mPrivateFlags &= ~PFLAG_ALPHA_SET;
12415                invalidateViewProperty(true, false);
12416                mRenderNode.setAlpha(getFinalAlpha());
12417            }
12418        }
12419    }
12420
12421    /**
12422     * Faster version of setAlpha() which performs the same steps except there are
12423     * no calls to invalidate(). The caller of this function should perform proper invalidation
12424     * on the parent and this object. The return value indicates whether the subclass handles
12425     * alpha (the return value for onSetAlpha()).
12426     *
12427     * @param alpha The new value for the alpha property
12428     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
12429     *         the new value for the alpha property is different from the old value
12430     */
12431    boolean setAlphaNoInvalidation(float alpha) {
12432        ensureTransformationInfo();
12433        if (mTransformationInfo.mAlpha != alpha) {
12434            mTransformationInfo.mAlpha = alpha;
12435            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
12436            if (subclassHandlesAlpha) {
12437                mPrivateFlags |= PFLAG_ALPHA_SET;
12438                return true;
12439            } else {
12440                mPrivateFlags &= ~PFLAG_ALPHA_SET;
12441                mRenderNode.setAlpha(getFinalAlpha());
12442            }
12443        }
12444        return false;
12445    }
12446
12447    /**
12448     * This property is hidden and intended only for use by the Fade transition, which
12449     * animates it to produce a visual translucency that does not side-effect (or get
12450     * affected by) the real alpha property. This value is composited with the other
12451     * alpha value (and the AlphaAnimation value, when that is present) to produce
12452     * a final visual translucency result, which is what is passed into the DisplayList.
12453     *
12454     * @hide
12455     */
12456    public void setTransitionAlpha(float alpha) {
12457        ensureTransformationInfo();
12458        if (mTransformationInfo.mTransitionAlpha != alpha) {
12459            mTransformationInfo.mTransitionAlpha = alpha;
12460            mPrivateFlags &= ~PFLAG_ALPHA_SET;
12461            invalidateViewProperty(true, false);
12462            mRenderNode.setAlpha(getFinalAlpha());
12463        }
12464    }
12465
12466    /**
12467     * Calculates the visual alpha of this view, which is a combination of the actual
12468     * alpha value and the transitionAlpha value (if set).
12469     */
12470    private float getFinalAlpha() {
12471        if (mTransformationInfo != null) {
12472            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
12473        }
12474        return 1;
12475    }
12476
12477    /**
12478     * This property is hidden and intended only for use by the Fade transition, which
12479     * animates it to produce a visual translucency that does not side-effect (or get
12480     * affected by) the real alpha property. This value is composited with the other
12481     * alpha value (and the AlphaAnimation value, when that is present) to produce
12482     * a final visual translucency result, which is what is passed into the DisplayList.
12483     *
12484     * @hide
12485     */
12486    @ViewDebug.ExportedProperty(category = "drawing")
12487    public float getTransitionAlpha() {
12488        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
12489    }
12490
12491    /**
12492     * Top position of this view relative to its parent.
12493     *
12494     * @return The top of this view, in pixels.
12495     */
12496    @ViewDebug.CapturedViewProperty
12497    public final int getTop() {
12498        return mTop;
12499    }
12500
12501    /**
12502     * Sets the top position of this view relative to its parent. This method is meant to be called
12503     * by the layout system and should not generally be called otherwise, because the property
12504     * may be changed at any time by the layout.
12505     *
12506     * @param top The top of this view, in pixels.
12507     */
12508    public final void setTop(int top) {
12509        if (top != mTop) {
12510            final boolean matrixIsIdentity = hasIdentityMatrix();
12511            if (matrixIsIdentity) {
12512                if (mAttachInfo != null) {
12513                    int minTop;
12514                    int yLoc;
12515                    if (top < mTop) {
12516                        minTop = top;
12517                        yLoc = top - mTop;
12518                    } else {
12519                        minTop = mTop;
12520                        yLoc = 0;
12521                    }
12522                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
12523                }
12524            } else {
12525                // Double-invalidation is necessary to capture view's old and new areas
12526                invalidate(true);
12527            }
12528
12529            int width = mRight - mLeft;
12530            int oldHeight = mBottom - mTop;
12531
12532            mTop = top;
12533            mRenderNode.setTop(mTop);
12534
12535            sizeChange(width, mBottom - mTop, width, oldHeight);
12536
12537            if (!matrixIsIdentity) {
12538                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12539                invalidate(true);
12540            }
12541            mBackgroundSizeChanged = true;
12542            if (mForegroundInfo != null) {
12543                mForegroundInfo.mBoundsChanged = true;
12544            }
12545            invalidateParentIfNeeded();
12546            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12547                // View was rejected last time it was drawn by its parent; this may have changed
12548                invalidateParentIfNeeded();
12549            }
12550        }
12551    }
12552
12553    /**
12554     * Bottom position of this view relative to its parent.
12555     *
12556     * @return The bottom of this view, in pixels.
12557     */
12558    @ViewDebug.CapturedViewProperty
12559    public final int getBottom() {
12560        return mBottom;
12561    }
12562
12563    /**
12564     * True if this view has changed since the last time being drawn.
12565     *
12566     * @return The dirty state of this view.
12567     */
12568    public boolean isDirty() {
12569        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
12570    }
12571
12572    /**
12573     * Sets the bottom position of this view relative to its parent. This method is meant to be
12574     * called by the layout system and should not generally be called otherwise, because the
12575     * property may be changed at any time by the layout.
12576     *
12577     * @param bottom The bottom of this view, in pixels.
12578     */
12579    public final void setBottom(int bottom) {
12580        if (bottom != mBottom) {
12581            final boolean matrixIsIdentity = hasIdentityMatrix();
12582            if (matrixIsIdentity) {
12583                if (mAttachInfo != null) {
12584                    int maxBottom;
12585                    if (bottom < mBottom) {
12586                        maxBottom = mBottom;
12587                    } else {
12588                        maxBottom = bottom;
12589                    }
12590                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
12591                }
12592            } else {
12593                // Double-invalidation is necessary to capture view's old and new areas
12594                invalidate(true);
12595            }
12596
12597            int width = mRight - mLeft;
12598            int oldHeight = mBottom - mTop;
12599
12600            mBottom = bottom;
12601            mRenderNode.setBottom(mBottom);
12602
12603            sizeChange(width, mBottom - mTop, width, oldHeight);
12604
12605            if (!matrixIsIdentity) {
12606                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12607                invalidate(true);
12608            }
12609            mBackgroundSizeChanged = true;
12610            if (mForegroundInfo != null) {
12611                mForegroundInfo.mBoundsChanged = true;
12612            }
12613            invalidateParentIfNeeded();
12614            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12615                // View was rejected last time it was drawn by its parent; this may have changed
12616                invalidateParentIfNeeded();
12617            }
12618        }
12619    }
12620
12621    /**
12622     * Left position of this view relative to its parent.
12623     *
12624     * @return The left edge of this view, in pixels.
12625     */
12626    @ViewDebug.CapturedViewProperty
12627    public final int getLeft() {
12628        return mLeft;
12629    }
12630
12631    /**
12632     * Sets the left position of this view relative to its parent. This method is meant to be called
12633     * by the layout system and should not generally be called otherwise, because the property
12634     * may be changed at any time by the layout.
12635     *
12636     * @param left The left of this view, in pixels.
12637     */
12638    public final void setLeft(int left) {
12639        if (left != mLeft) {
12640            final boolean matrixIsIdentity = hasIdentityMatrix();
12641            if (matrixIsIdentity) {
12642                if (mAttachInfo != null) {
12643                    int minLeft;
12644                    int xLoc;
12645                    if (left < mLeft) {
12646                        minLeft = left;
12647                        xLoc = left - mLeft;
12648                    } else {
12649                        minLeft = mLeft;
12650                        xLoc = 0;
12651                    }
12652                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
12653                }
12654            } else {
12655                // Double-invalidation is necessary to capture view's old and new areas
12656                invalidate(true);
12657            }
12658
12659            int oldWidth = mRight - mLeft;
12660            int height = mBottom - mTop;
12661
12662            mLeft = left;
12663            mRenderNode.setLeft(left);
12664
12665            sizeChange(mRight - mLeft, height, oldWidth, height);
12666
12667            if (!matrixIsIdentity) {
12668                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12669                invalidate(true);
12670            }
12671            mBackgroundSizeChanged = true;
12672            if (mForegroundInfo != null) {
12673                mForegroundInfo.mBoundsChanged = true;
12674            }
12675            invalidateParentIfNeeded();
12676            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12677                // View was rejected last time it was drawn by its parent; this may have changed
12678                invalidateParentIfNeeded();
12679            }
12680        }
12681    }
12682
12683    /**
12684     * Right position of this view relative to its parent.
12685     *
12686     * @return The right edge of this view, in pixels.
12687     */
12688    @ViewDebug.CapturedViewProperty
12689    public final int getRight() {
12690        return mRight;
12691    }
12692
12693    /**
12694     * Sets the right position of this view relative to its parent. This method is meant to be called
12695     * by the layout system and should not generally be called otherwise, because the property
12696     * may be changed at any time by the layout.
12697     *
12698     * @param right The right of this view, in pixels.
12699     */
12700    public final void setRight(int right) {
12701        if (right != mRight) {
12702            final boolean matrixIsIdentity = hasIdentityMatrix();
12703            if (matrixIsIdentity) {
12704                if (mAttachInfo != null) {
12705                    int maxRight;
12706                    if (right < mRight) {
12707                        maxRight = mRight;
12708                    } else {
12709                        maxRight = right;
12710                    }
12711                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
12712                }
12713            } else {
12714                // Double-invalidation is necessary to capture view's old and new areas
12715                invalidate(true);
12716            }
12717
12718            int oldWidth = mRight - mLeft;
12719            int height = mBottom - mTop;
12720
12721            mRight = right;
12722            mRenderNode.setRight(mRight);
12723
12724            sizeChange(mRight - mLeft, height, oldWidth, height);
12725
12726            if (!matrixIsIdentity) {
12727                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12728                invalidate(true);
12729            }
12730            mBackgroundSizeChanged = true;
12731            if (mForegroundInfo != null) {
12732                mForegroundInfo.mBoundsChanged = true;
12733            }
12734            invalidateParentIfNeeded();
12735            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12736                // View was rejected last time it was drawn by its parent; this may have changed
12737                invalidateParentIfNeeded();
12738            }
12739        }
12740    }
12741
12742    /**
12743     * The visual x position of this view, in pixels. This is equivalent to the
12744     * {@link #setTranslationX(float) translationX} property plus the current
12745     * {@link #getLeft() left} property.
12746     *
12747     * @return The visual x position of this view, in pixels.
12748     */
12749    @ViewDebug.ExportedProperty(category = "drawing")
12750    public float getX() {
12751        return mLeft + getTranslationX();
12752    }
12753
12754    /**
12755     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
12756     * {@link #setTranslationX(float) translationX} property to be the difference between
12757     * the x value passed in and the current {@link #getLeft() left} property.
12758     *
12759     * @param x The visual x position of this view, in pixels.
12760     */
12761    public void setX(float x) {
12762        setTranslationX(x - mLeft);
12763    }
12764
12765    /**
12766     * The visual y position of this view, in pixels. This is equivalent to the
12767     * {@link #setTranslationY(float) translationY} property plus the current
12768     * {@link #getTop() top} property.
12769     *
12770     * @return The visual y position of this view, in pixels.
12771     */
12772    @ViewDebug.ExportedProperty(category = "drawing")
12773    public float getY() {
12774        return mTop + getTranslationY();
12775    }
12776
12777    /**
12778     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
12779     * {@link #setTranslationY(float) translationY} property to be the difference between
12780     * the y value passed in and the current {@link #getTop() top} property.
12781     *
12782     * @param y The visual y position of this view, in pixels.
12783     */
12784    public void setY(float y) {
12785        setTranslationY(y - mTop);
12786    }
12787
12788    /**
12789     * The visual z position of this view, in pixels. This is equivalent to the
12790     * {@link #setTranslationZ(float) translationZ} property plus the current
12791     * {@link #getElevation() elevation} property.
12792     *
12793     * @return The visual z position of this view, in pixels.
12794     */
12795    @ViewDebug.ExportedProperty(category = "drawing")
12796    public float getZ() {
12797        return getElevation() + getTranslationZ();
12798    }
12799
12800    /**
12801     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
12802     * {@link #setTranslationZ(float) translationZ} property to be the difference between
12803     * the x value passed in and the current {@link #getElevation() elevation} property.
12804     *
12805     * @param z The visual z position of this view, in pixels.
12806     */
12807    public void setZ(float z) {
12808        setTranslationZ(z - getElevation());
12809    }
12810
12811    /**
12812     * The base elevation of this view relative to its parent, in pixels.
12813     *
12814     * @return The base depth position of the view, in pixels.
12815     */
12816    @ViewDebug.ExportedProperty(category = "drawing")
12817    public float getElevation() {
12818        return mRenderNode.getElevation();
12819    }
12820
12821    /**
12822     * Sets the base elevation of this view, in pixels.
12823     *
12824     * @attr ref android.R.styleable#View_elevation
12825     */
12826    public void setElevation(float elevation) {
12827        if (elevation != getElevation()) {
12828            invalidateViewProperty(true, false);
12829            mRenderNode.setElevation(elevation);
12830            invalidateViewProperty(false, true);
12831
12832            invalidateParentIfNeededAndWasQuickRejected();
12833        }
12834    }
12835
12836    /**
12837     * The horizontal location of this view relative to its {@link #getLeft() left} position.
12838     * This position is post-layout, in addition to wherever the object's
12839     * layout placed it.
12840     *
12841     * @return The horizontal position of this view relative to its left position, in pixels.
12842     */
12843    @ViewDebug.ExportedProperty(category = "drawing")
12844    public float getTranslationX() {
12845        return mRenderNode.getTranslationX();
12846    }
12847
12848    /**
12849     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12850     * This effectively positions the object post-layout, in addition to wherever the object's
12851     * layout placed it.
12852     *
12853     * @param translationX The horizontal position of this view relative to its left position,
12854     * in pixels.
12855     *
12856     * @attr ref android.R.styleable#View_translationX
12857     */
12858    public void setTranslationX(float translationX) {
12859        if (translationX != getTranslationX()) {
12860            invalidateViewProperty(true, false);
12861            mRenderNode.setTranslationX(translationX);
12862            invalidateViewProperty(false, true);
12863
12864            invalidateParentIfNeededAndWasQuickRejected();
12865            notifySubtreeAccessibilityStateChangedIfNeeded();
12866        }
12867    }
12868
12869    /**
12870     * The vertical location of this view relative to its {@link #getTop() top} position.
12871     * This position is post-layout, in addition to wherever the object's
12872     * layout placed it.
12873     *
12874     * @return The vertical position of this view relative to its top position,
12875     * in pixels.
12876     */
12877    @ViewDebug.ExportedProperty(category = "drawing")
12878    public float getTranslationY() {
12879        return mRenderNode.getTranslationY();
12880    }
12881
12882    /**
12883     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12884     * This effectively positions the object post-layout, in addition to wherever the object's
12885     * layout placed it.
12886     *
12887     * @param translationY The vertical position of this view relative to its top position,
12888     * in pixels.
12889     *
12890     * @attr ref android.R.styleable#View_translationY
12891     */
12892    public void setTranslationY(float translationY) {
12893        if (translationY != getTranslationY()) {
12894            invalidateViewProperty(true, false);
12895            mRenderNode.setTranslationY(translationY);
12896            invalidateViewProperty(false, true);
12897
12898            invalidateParentIfNeededAndWasQuickRejected();
12899            notifySubtreeAccessibilityStateChangedIfNeeded();
12900        }
12901    }
12902
12903    /**
12904     * The depth location of this view relative to its {@link #getElevation() elevation}.
12905     *
12906     * @return The depth of this view relative to its elevation.
12907     */
12908    @ViewDebug.ExportedProperty(category = "drawing")
12909    public float getTranslationZ() {
12910        return mRenderNode.getTranslationZ();
12911    }
12912
12913    /**
12914     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12915     *
12916     * @attr ref android.R.styleable#View_translationZ
12917     */
12918    public void setTranslationZ(float translationZ) {
12919        if (translationZ != getTranslationZ()) {
12920            invalidateViewProperty(true, false);
12921            mRenderNode.setTranslationZ(translationZ);
12922            invalidateViewProperty(false, true);
12923
12924            invalidateParentIfNeededAndWasQuickRejected();
12925        }
12926    }
12927
12928    /** @hide */
12929    public void setAnimationMatrix(Matrix matrix) {
12930        invalidateViewProperty(true, false);
12931        mRenderNode.setAnimationMatrix(matrix);
12932        invalidateViewProperty(false, true);
12933
12934        invalidateParentIfNeededAndWasQuickRejected();
12935    }
12936
12937    /**
12938     * Returns the current StateListAnimator if exists.
12939     *
12940     * @return StateListAnimator or null if it does not exists
12941     * @see    #setStateListAnimator(android.animation.StateListAnimator)
12942     */
12943    public StateListAnimator getStateListAnimator() {
12944        return mStateListAnimator;
12945    }
12946
12947    /**
12948     * Attaches the provided StateListAnimator to this View.
12949     * <p>
12950     * Any previously attached StateListAnimator will be detached.
12951     *
12952     * @param stateListAnimator The StateListAnimator to update the view
12953     * @see {@link android.animation.StateListAnimator}
12954     */
12955    public void setStateListAnimator(StateListAnimator stateListAnimator) {
12956        if (mStateListAnimator == stateListAnimator) {
12957            return;
12958        }
12959        if (mStateListAnimator != null) {
12960            mStateListAnimator.setTarget(null);
12961        }
12962        mStateListAnimator = stateListAnimator;
12963        if (stateListAnimator != null) {
12964            stateListAnimator.setTarget(this);
12965            if (isAttachedToWindow()) {
12966                stateListAnimator.setState(getDrawableState());
12967            }
12968        }
12969    }
12970
12971    /**
12972     * Returns whether the Outline should be used to clip the contents of the View.
12973     * <p>
12974     * Note that this flag will only be respected if the View's Outline returns true from
12975     * {@link Outline#canClip()}.
12976     *
12977     * @see #setOutlineProvider(ViewOutlineProvider)
12978     * @see #setClipToOutline(boolean)
12979     */
12980    public final boolean getClipToOutline() {
12981        return mRenderNode.getClipToOutline();
12982    }
12983
12984    /**
12985     * Sets whether the View's Outline should be used to clip the contents of the View.
12986     * <p>
12987     * Only a single non-rectangular clip can be applied on a View at any time.
12988     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12989     * circular reveal} animation take priority over Outline clipping, and
12990     * child Outline clipping takes priority over Outline clipping done by a
12991     * parent.
12992     * <p>
12993     * Note that this flag will only be respected if the View's Outline returns true from
12994     * {@link Outline#canClip()}.
12995     *
12996     * @see #setOutlineProvider(ViewOutlineProvider)
12997     * @see #getClipToOutline()
12998     */
12999    public void setClipToOutline(boolean clipToOutline) {
13000        damageInParent();
13001        if (getClipToOutline() != clipToOutline) {
13002            mRenderNode.setClipToOutline(clipToOutline);
13003        }
13004    }
13005
13006    // correspond to the enum values of View_outlineProvider
13007    private static final int PROVIDER_BACKGROUND = 0;
13008    private static final int PROVIDER_NONE = 1;
13009    private static final int PROVIDER_BOUNDS = 2;
13010    private static final int PROVIDER_PADDED_BOUNDS = 3;
13011    private void setOutlineProviderFromAttribute(int providerInt) {
13012        switch (providerInt) {
13013            case PROVIDER_BACKGROUND:
13014                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
13015                break;
13016            case PROVIDER_NONE:
13017                setOutlineProvider(null);
13018                break;
13019            case PROVIDER_BOUNDS:
13020                setOutlineProvider(ViewOutlineProvider.BOUNDS);
13021                break;
13022            case PROVIDER_PADDED_BOUNDS:
13023                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
13024                break;
13025        }
13026    }
13027
13028    /**
13029     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
13030     * the shape of the shadow it casts, and enables outline clipping.
13031     * <p>
13032     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
13033     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
13034     * outline provider with this method allows this behavior to be overridden.
13035     * <p>
13036     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
13037     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
13038     * <p>
13039     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
13040     *
13041     * @see #setClipToOutline(boolean)
13042     * @see #getClipToOutline()
13043     * @see #getOutlineProvider()
13044     */
13045    public void setOutlineProvider(ViewOutlineProvider provider) {
13046        mOutlineProvider = provider;
13047        invalidateOutline();
13048    }
13049
13050    /**
13051     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
13052     * that defines the shape of the shadow it casts, and enables outline clipping.
13053     *
13054     * @see #setOutlineProvider(ViewOutlineProvider)
13055     */
13056    public ViewOutlineProvider getOutlineProvider() {
13057        return mOutlineProvider;
13058    }
13059
13060    /**
13061     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
13062     *
13063     * @see #setOutlineProvider(ViewOutlineProvider)
13064     */
13065    public void invalidateOutline() {
13066        rebuildOutline();
13067
13068        notifySubtreeAccessibilityStateChangedIfNeeded();
13069        invalidateViewProperty(false, false);
13070    }
13071
13072    /**
13073     * Internal version of {@link #invalidateOutline()} which invalidates the
13074     * outline without invalidating the view itself. This is intended to be called from
13075     * within methods in the View class itself which are the result of the view being
13076     * invalidated already. For example, when we are drawing the background of a View,
13077     * we invalidate the outline in case it changed in the meantime, but we do not
13078     * need to invalidate the view because we're already drawing the background as part
13079     * of drawing the view in response to an earlier invalidation of the view.
13080     */
13081    private void rebuildOutline() {
13082        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
13083        if (mAttachInfo == null) return;
13084
13085        if (mOutlineProvider == null) {
13086            // no provider, remove outline
13087            mRenderNode.setOutline(null);
13088        } else {
13089            final Outline outline = mAttachInfo.mTmpOutline;
13090            outline.setEmpty();
13091            outline.setAlpha(1.0f);
13092
13093            mOutlineProvider.getOutline(this, outline);
13094            mRenderNode.setOutline(outline);
13095        }
13096    }
13097
13098    /**
13099     * HierarchyViewer only
13100     *
13101     * @hide
13102     */
13103    @ViewDebug.ExportedProperty(category = "drawing")
13104    public boolean hasShadow() {
13105        return mRenderNode.hasShadow();
13106    }
13107
13108
13109    /** @hide */
13110    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
13111        mRenderNode.setRevealClip(shouldClip, x, y, radius);
13112        invalidateViewProperty(false, false);
13113    }
13114
13115    /**
13116     * Hit rectangle in parent's coordinates
13117     *
13118     * @param outRect The hit rectangle of the view.
13119     */
13120    public void getHitRect(Rect outRect) {
13121        if (hasIdentityMatrix() || mAttachInfo == null) {
13122            outRect.set(mLeft, mTop, mRight, mBottom);
13123        } else {
13124            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
13125            tmpRect.set(0, 0, getWidth(), getHeight());
13126            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
13127            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
13128                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
13129        }
13130    }
13131
13132    /**
13133     * Determines whether the given point, in local coordinates is inside the view.
13134     */
13135    /*package*/ final boolean pointInView(float localX, float localY) {
13136        return pointInView(localX, localY, 0);
13137    }
13138
13139    /**
13140     * Utility method to determine whether the given point, in local coordinates,
13141     * is inside the view, where the area of the view is expanded by the slop factor.
13142     * This method is called while processing touch-move events to determine if the event
13143     * is still within the view.
13144     *
13145     * @hide
13146     */
13147    public boolean pointInView(float localX, float localY, float slop) {
13148        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
13149                localY < ((mBottom - mTop) + slop);
13150    }
13151
13152    /**
13153     * When a view has focus and the user navigates away from it, the next view is searched for
13154     * starting from the rectangle filled in by this method.
13155     *
13156     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
13157     * of the view.  However, if your view maintains some idea of internal selection,
13158     * such as a cursor, or a selected row or column, you should override this method and
13159     * fill in a more specific rectangle.
13160     *
13161     * @param r The rectangle to fill in, in this view's coordinates.
13162     */
13163    public void getFocusedRect(Rect r) {
13164        getDrawingRect(r);
13165    }
13166
13167    /**
13168     * If some part of this view is not clipped by any of its parents, then
13169     * return that area in r in global (root) coordinates. To convert r to local
13170     * coordinates (without taking possible View rotations into account), offset
13171     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
13172     * If the view is completely clipped or translated out, return false.
13173     *
13174     * @param r If true is returned, r holds the global coordinates of the
13175     *        visible portion of this view.
13176     * @param globalOffset If true is returned, globalOffset holds the dx,dy
13177     *        between this view and its root. globalOffet may be null.
13178     * @return true if r is non-empty (i.e. part of the view is visible at the
13179     *         root level.
13180     */
13181    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
13182        int width = mRight - mLeft;
13183        int height = mBottom - mTop;
13184        if (width > 0 && height > 0) {
13185            r.set(0, 0, width, height);
13186            if (globalOffset != null) {
13187                globalOffset.set(-mScrollX, -mScrollY);
13188            }
13189            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
13190        }
13191        return false;
13192    }
13193
13194    public final boolean getGlobalVisibleRect(Rect r) {
13195        return getGlobalVisibleRect(r, null);
13196    }
13197
13198    public final boolean getLocalVisibleRect(Rect r) {
13199        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
13200        if (getGlobalVisibleRect(r, offset)) {
13201            r.offset(-offset.x, -offset.y); // make r local
13202            return true;
13203        }
13204        return false;
13205    }
13206
13207    /**
13208     * Offset this view's vertical location by the specified number of pixels.
13209     *
13210     * @param offset the number of pixels to offset the view by
13211     */
13212    public void offsetTopAndBottom(int offset) {
13213        if (offset != 0) {
13214            final boolean matrixIsIdentity = hasIdentityMatrix();
13215            if (matrixIsIdentity) {
13216                if (isHardwareAccelerated()) {
13217                    invalidateViewProperty(false, false);
13218                } else {
13219                    final ViewParent p = mParent;
13220                    if (p != null && mAttachInfo != null) {
13221                        final Rect r = mAttachInfo.mTmpInvalRect;
13222                        int minTop;
13223                        int maxBottom;
13224                        int yLoc;
13225                        if (offset < 0) {
13226                            minTop = mTop + offset;
13227                            maxBottom = mBottom;
13228                            yLoc = offset;
13229                        } else {
13230                            minTop = mTop;
13231                            maxBottom = mBottom + offset;
13232                            yLoc = 0;
13233                        }
13234                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
13235                        p.invalidateChild(this, r);
13236                    }
13237                }
13238            } else {
13239                invalidateViewProperty(false, false);
13240            }
13241
13242            mTop += offset;
13243            mBottom += offset;
13244            mRenderNode.offsetTopAndBottom(offset);
13245            if (isHardwareAccelerated()) {
13246                invalidateViewProperty(false, false);
13247                invalidateParentIfNeededAndWasQuickRejected();
13248            } else {
13249                if (!matrixIsIdentity) {
13250                    invalidateViewProperty(false, true);
13251                }
13252                invalidateParentIfNeeded();
13253            }
13254            notifySubtreeAccessibilityStateChangedIfNeeded();
13255        }
13256    }
13257
13258    /**
13259     * Offset this view's horizontal location by the specified amount of pixels.
13260     *
13261     * @param offset the number of pixels to offset the view by
13262     */
13263    public void offsetLeftAndRight(int offset) {
13264        if (offset != 0) {
13265            final boolean matrixIsIdentity = hasIdentityMatrix();
13266            if (matrixIsIdentity) {
13267                if (isHardwareAccelerated()) {
13268                    invalidateViewProperty(false, false);
13269                } else {
13270                    final ViewParent p = mParent;
13271                    if (p != null && mAttachInfo != null) {
13272                        final Rect r = mAttachInfo.mTmpInvalRect;
13273                        int minLeft;
13274                        int maxRight;
13275                        if (offset < 0) {
13276                            minLeft = mLeft + offset;
13277                            maxRight = mRight;
13278                        } else {
13279                            minLeft = mLeft;
13280                            maxRight = mRight + offset;
13281                        }
13282                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
13283                        p.invalidateChild(this, r);
13284                    }
13285                }
13286            } else {
13287                invalidateViewProperty(false, false);
13288            }
13289
13290            mLeft += offset;
13291            mRight += offset;
13292            mRenderNode.offsetLeftAndRight(offset);
13293            if (isHardwareAccelerated()) {
13294                invalidateViewProperty(false, false);
13295                invalidateParentIfNeededAndWasQuickRejected();
13296            } else {
13297                if (!matrixIsIdentity) {
13298                    invalidateViewProperty(false, true);
13299                }
13300                invalidateParentIfNeeded();
13301            }
13302            notifySubtreeAccessibilityStateChangedIfNeeded();
13303        }
13304    }
13305
13306    /**
13307     * Get the LayoutParams associated with this view. All views should have
13308     * layout parameters. These supply parameters to the <i>parent</i> of this
13309     * view specifying how it should be arranged. There are many subclasses of
13310     * ViewGroup.LayoutParams, and these correspond to the different subclasses
13311     * of ViewGroup that are responsible for arranging their children.
13312     *
13313     * This method may return null if this View is not attached to a parent
13314     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
13315     * was not invoked successfully. When a View is attached to a parent
13316     * ViewGroup, this method must not return null.
13317     *
13318     * @return The LayoutParams associated with this view, or null if no
13319     *         parameters have been set yet
13320     */
13321    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
13322    public ViewGroup.LayoutParams getLayoutParams() {
13323        return mLayoutParams;
13324    }
13325
13326    /**
13327     * Set the layout parameters associated with this view. These supply
13328     * parameters to the <i>parent</i> of this view specifying how it should be
13329     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
13330     * correspond to the different subclasses of ViewGroup that are responsible
13331     * for arranging their children.
13332     *
13333     * @param params The layout parameters for this view, cannot be null
13334     */
13335    public void setLayoutParams(ViewGroup.LayoutParams params) {
13336        if (params == null) {
13337            throw new NullPointerException("Layout parameters cannot be null");
13338        }
13339        mLayoutParams = params;
13340        resolveLayoutParams();
13341        if (mParent instanceof ViewGroup) {
13342            ((ViewGroup) mParent).onSetLayoutParams(this, params);
13343        }
13344        requestLayout();
13345    }
13346
13347    /**
13348     * Resolve the layout parameters depending on the resolved layout direction
13349     *
13350     * @hide
13351     */
13352    public void resolveLayoutParams() {
13353        if (mLayoutParams != null) {
13354            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
13355        }
13356    }
13357
13358    /**
13359     * Set the scrolled position of your view. This will cause a call to
13360     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13361     * invalidated.
13362     * @param x the x position to scroll to
13363     * @param y the y position to scroll to
13364     */
13365    public void scrollTo(int x, int y) {
13366        if (mScrollX != x || mScrollY != y) {
13367            int oldX = mScrollX;
13368            int oldY = mScrollY;
13369            mScrollX = x;
13370            mScrollY = y;
13371            invalidateParentCaches();
13372            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
13373            if (!awakenScrollBars()) {
13374                postInvalidateOnAnimation();
13375            }
13376        }
13377    }
13378
13379    /**
13380     * Move the scrolled position of your view. This will cause a call to
13381     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13382     * invalidated.
13383     * @param x the amount of pixels to scroll by horizontally
13384     * @param y the amount of pixels to scroll by vertically
13385     */
13386    public void scrollBy(int x, int y) {
13387        scrollTo(mScrollX + x, mScrollY + y);
13388    }
13389
13390    /**
13391     * <p>Trigger the scrollbars to draw. When invoked this method starts an
13392     * animation to fade the scrollbars out after a default delay. If a subclass
13393     * provides animated scrolling, the start delay should equal the duration
13394     * of the scrolling animation.</p>
13395     *
13396     * <p>The animation starts only if at least one of the scrollbars is
13397     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
13398     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13399     * this method returns true, and false otherwise. If the animation is
13400     * started, this method calls {@link #invalidate()}; in that case the
13401     * caller should not call {@link #invalidate()}.</p>
13402     *
13403     * <p>This method should be invoked every time a subclass directly updates
13404     * the scroll parameters.</p>
13405     *
13406     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
13407     * and {@link #scrollTo(int, int)}.</p>
13408     *
13409     * @return true if the animation is played, false otherwise
13410     *
13411     * @see #awakenScrollBars(int)
13412     * @see #scrollBy(int, int)
13413     * @see #scrollTo(int, int)
13414     * @see #isHorizontalScrollBarEnabled()
13415     * @see #isVerticalScrollBarEnabled()
13416     * @see #setHorizontalScrollBarEnabled(boolean)
13417     * @see #setVerticalScrollBarEnabled(boolean)
13418     */
13419    protected boolean awakenScrollBars() {
13420        return mScrollCache != null &&
13421                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
13422    }
13423
13424    /**
13425     * Trigger the scrollbars to draw.
13426     * This method differs from awakenScrollBars() only in its default duration.
13427     * initialAwakenScrollBars() will show the scroll bars for longer than
13428     * usual to give the user more of a chance to notice them.
13429     *
13430     * @return true if the animation is played, false otherwise.
13431     */
13432    private boolean initialAwakenScrollBars() {
13433        return mScrollCache != null &&
13434                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
13435    }
13436
13437    /**
13438     * <p>
13439     * Trigger the scrollbars to draw. When invoked this method starts an
13440     * animation to fade the scrollbars out after a fixed delay. If a subclass
13441     * provides animated scrolling, the start delay should equal the duration of
13442     * the scrolling animation.
13443     * </p>
13444     *
13445     * <p>
13446     * The animation starts only if at least one of the scrollbars is enabled,
13447     * as specified by {@link #isHorizontalScrollBarEnabled()} and
13448     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13449     * this method returns true, and false otherwise. If the animation is
13450     * started, this method calls {@link #invalidate()}; in that case the caller
13451     * should not call {@link #invalidate()}.
13452     * </p>
13453     *
13454     * <p>
13455     * This method should be invoked every time a subclass directly updates the
13456     * scroll parameters.
13457     * </p>
13458     *
13459     * @param startDelay the delay, in milliseconds, after which the animation
13460     *        should start; when the delay is 0, the animation starts
13461     *        immediately
13462     * @return true if the animation is played, false otherwise
13463     *
13464     * @see #scrollBy(int, int)
13465     * @see #scrollTo(int, int)
13466     * @see #isHorizontalScrollBarEnabled()
13467     * @see #isVerticalScrollBarEnabled()
13468     * @see #setHorizontalScrollBarEnabled(boolean)
13469     * @see #setVerticalScrollBarEnabled(boolean)
13470     */
13471    protected boolean awakenScrollBars(int startDelay) {
13472        return awakenScrollBars(startDelay, true);
13473    }
13474
13475    /**
13476     * <p>
13477     * Trigger the scrollbars to draw. When invoked this method starts an
13478     * animation to fade the scrollbars out after a fixed delay. If a subclass
13479     * provides animated scrolling, the start delay should equal the duration of
13480     * the scrolling animation.
13481     * </p>
13482     *
13483     * <p>
13484     * The animation starts only if at least one of the scrollbars is enabled,
13485     * as specified by {@link #isHorizontalScrollBarEnabled()} and
13486     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13487     * this method returns true, and false otherwise. If the animation is
13488     * started, this method calls {@link #invalidate()} if the invalidate parameter
13489     * is set to true; in that case the caller
13490     * should not call {@link #invalidate()}.
13491     * </p>
13492     *
13493     * <p>
13494     * This method should be invoked every time a subclass directly updates the
13495     * scroll parameters.
13496     * </p>
13497     *
13498     * @param startDelay the delay, in milliseconds, after which the animation
13499     *        should start; when the delay is 0, the animation starts
13500     *        immediately
13501     *
13502     * @param invalidate Whether this method should call invalidate
13503     *
13504     * @return true if the animation is played, false otherwise
13505     *
13506     * @see #scrollBy(int, int)
13507     * @see #scrollTo(int, int)
13508     * @see #isHorizontalScrollBarEnabled()
13509     * @see #isVerticalScrollBarEnabled()
13510     * @see #setHorizontalScrollBarEnabled(boolean)
13511     * @see #setVerticalScrollBarEnabled(boolean)
13512     */
13513    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
13514        final ScrollabilityCache scrollCache = mScrollCache;
13515
13516        if (scrollCache == null || !scrollCache.fadeScrollBars) {
13517            return false;
13518        }
13519
13520        if (scrollCache.scrollBar == null) {
13521            scrollCache.scrollBar = new ScrollBarDrawable();
13522            scrollCache.scrollBar.setState(getDrawableState());
13523            scrollCache.scrollBar.setCallback(this);
13524        }
13525
13526        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
13527
13528            if (invalidate) {
13529                // Invalidate to show the scrollbars
13530                postInvalidateOnAnimation();
13531            }
13532
13533            if (scrollCache.state == ScrollabilityCache.OFF) {
13534                // FIXME: this is copied from WindowManagerService.
13535                // We should get this value from the system when it
13536                // is possible to do so.
13537                final int KEY_REPEAT_FIRST_DELAY = 750;
13538                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
13539            }
13540
13541            // Tell mScrollCache when we should start fading. This may
13542            // extend the fade start time if one was already scheduled
13543            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
13544            scrollCache.fadeStartTime = fadeStartTime;
13545            scrollCache.state = ScrollabilityCache.ON;
13546
13547            // Schedule our fader to run, unscheduling any old ones first
13548            if (mAttachInfo != null) {
13549                mAttachInfo.mHandler.removeCallbacks(scrollCache);
13550                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
13551            }
13552
13553            return true;
13554        }
13555
13556        return false;
13557    }
13558
13559    /**
13560     * Do not invalidate views which are not visible and which are not running an animation. They
13561     * will not get drawn and they should not set dirty flags as if they will be drawn
13562     */
13563    private boolean skipInvalidate() {
13564        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
13565                (!(mParent instanceof ViewGroup) ||
13566                        !((ViewGroup) mParent).isViewTransitioning(this));
13567    }
13568
13569    /**
13570     * Mark the area defined by dirty as needing to be drawn. If the view is
13571     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13572     * point in the future.
13573     * <p>
13574     * This must be called from a UI thread. To call from a non-UI thread, call
13575     * {@link #postInvalidate()}.
13576     * <p>
13577     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
13578     * {@code dirty}.
13579     *
13580     * @param dirty the rectangle representing the bounds of the dirty region
13581     */
13582    public void invalidate(Rect dirty) {
13583        final int scrollX = mScrollX;
13584        final int scrollY = mScrollY;
13585        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
13586                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
13587    }
13588
13589    /**
13590     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
13591     * coordinates of the dirty rect are relative to the view. If the view is
13592     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13593     * point in the future.
13594     * <p>
13595     * This must be called from a UI thread. To call from a non-UI thread, call
13596     * {@link #postInvalidate()}.
13597     *
13598     * @param l the left position of the dirty region
13599     * @param t the top position of the dirty region
13600     * @param r the right position of the dirty region
13601     * @param b the bottom position of the dirty region
13602     */
13603    public void invalidate(int l, int t, int r, int b) {
13604        final int scrollX = mScrollX;
13605        final int scrollY = mScrollY;
13606        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
13607    }
13608
13609    /**
13610     * Invalidate the whole view. If the view is visible,
13611     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
13612     * the future.
13613     * <p>
13614     * This must be called from a UI thread. To call from a non-UI thread, call
13615     * {@link #postInvalidate()}.
13616     */
13617    public void invalidate() {
13618        invalidate(true);
13619    }
13620
13621    /**
13622     * This is where the invalidate() work actually happens. A full invalidate()
13623     * causes the drawing cache to be invalidated, but this function can be
13624     * called with invalidateCache set to false to skip that invalidation step
13625     * for cases that do not need it (for example, a component that remains at
13626     * the same dimensions with the same content).
13627     *
13628     * @param invalidateCache Whether the drawing cache for this view should be
13629     *            invalidated as well. This is usually true for a full
13630     *            invalidate, but may be set to false if the View's contents or
13631     *            dimensions have not changed.
13632     */
13633    void invalidate(boolean invalidateCache) {
13634        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
13635    }
13636
13637    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
13638            boolean fullInvalidate) {
13639        if (mGhostView != null) {
13640            mGhostView.invalidate(true);
13641            return;
13642        }
13643
13644        if (skipInvalidate()) {
13645            return;
13646        }
13647
13648        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
13649                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
13650                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
13651                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
13652            if (fullInvalidate) {
13653                mLastIsOpaque = isOpaque();
13654                mPrivateFlags &= ~PFLAG_DRAWN;
13655            }
13656
13657            mPrivateFlags |= PFLAG_DIRTY;
13658
13659            if (invalidateCache) {
13660                mPrivateFlags |= PFLAG_INVALIDATED;
13661                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13662            }
13663
13664            // Propagate the damage rectangle to the parent view.
13665            final AttachInfo ai = mAttachInfo;
13666            final ViewParent p = mParent;
13667            if (p != null && ai != null && l < r && t < b) {
13668                final Rect damage = ai.mTmpInvalRect;
13669                damage.set(l, t, r, b);
13670                p.invalidateChild(this, damage);
13671            }
13672
13673            // Damage the entire projection receiver, if necessary.
13674            if (mBackground != null && mBackground.isProjected()) {
13675                final View receiver = getProjectionReceiver();
13676                if (receiver != null) {
13677                    receiver.damageInParent();
13678                }
13679            }
13680
13681            // Damage the entire IsolatedZVolume receiving this view's shadow.
13682            if (isHardwareAccelerated() && getZ() != 0) {
13683                damageShadowReceiver();
13684            }
13685        }
13686    }
13687
13688    /**
13689     * @return this view's projection receiver, or {@code null} if none exists
13690     */
13691    private View getProjectionReceiver() {
13692        ViewParent p = getParent();
13693        while (p != null && p instanceof View) {
13694            final View v = (View) p;
13695            if (v.isProjectionReceiver()) {
13696                return v;
13697            }
13698            p = p.getParent();
13699        }
13700
13701        return null;
13702    }
13703
13704    /**
13705     * @return whether the view is a projection receiver
13706     */
13707    private boolean isProjectionReceiver() {
13708        return mBackground != null;
13709    }
13710
13711    /**
13712     * Damage area of the screen that can be covered by this View's shadow.
13713     *
13714     * This method will guarantee that any changes to shadows cast by a View
13715     * are damaged on the screen for future redraw.
13716     */
13717    private void damageShadowReceiver() {
13718        final AttachInfo ai = mAttachInfo;
13719        if (ai != null) {
13720            ViewParent p = getParent();
13721            if (p != null && p instanceof ViewGroup) {
13722                final ViewGroup vg = (ViewGroup) p;
13723                vg.damageInParent();
13724            }
13725        }
13726    }
13727
13728    /**
13729     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
13730     * set any flags or handle all of the cases handled by the default invalidation methods.
13731     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
13732     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
13733     * walk up the hierarchy, transforming the dirty rect as necessary.
13734     *
13735     * The method also handles normal invalidation logic if display list properties are not
13736     * being used in this view. The invalidateParent and forceRedraw flags are used by that
13737     * backup approach, to handle these cases used in the various property-setting methods.
13738     *
13739     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
13740     * are not being used in this view
13741     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
13742     * list properties are not being used in this view
13743     */
13744    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
13745        if (!isHardwareAccelerated()
13746                || !mRenderNode.isValid()
13747                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
13748            if (invalidateParent) {
13749                invalidateParentCaches();
13750            }
13751            if (forceRedraw) {
13752                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13753            }
13754            invalidate(false);
13755        } else {
13756            damageInParent();
13757        }
13758        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
13759            damageShadowReceiver();
13760        }
13761    }
13762
13763    /**
13764     * Tells the parent view to damage this view's bounds.
13765     *
13766     * @hide
13767     */
13768    protected void damageInParent() {
13769        final AttachInfo ai = mAttachInfo;
13770        final ViewParent p = mParent;
13771        if (p != null && ai != null) {
13772            final Rect r = ai.mTmpInvalRect;
13773            r.set(0, 0, mRight - mLeft, mBottom - mTop);
13774            if (mParent instanceof ViewGroup) {
13775                ((ViewGroup) mParent).damageChild(this, r);
13776            } else {
13777                mParent.invalidateChild(this, r);
13778            }
13779        }
13780    }
13781
13782    /**
13783     * Utility method to transform a given Rect by the current matrix of this view.
13784     */
13785    void transformRect(final Rect rect) {
13786        if (!getMatrix().isIdentity()) {
13787            RectF boundingRect = mAttachInfo.mTmpTransformRect;
13788            boundingRect.set(rect);
13789            getMatrix().mapRect(boundingRect);
13790            rect.set((int) Math.floor(boundingRect.left),
13791                    (int) Math.floor(boundingRect.top),
13792                    (int) Math.ceil(boundingRect.right),
13793                    (int) Math.ceil(boundingRect.bottom));
13794        }
13795    }
13796
13797    /**
13798     * Used to indicate that the parent of this view should clear its caches. This functionality
13799     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13800     * which is necessary when various parent-managed properties of the view change, such as
13801     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
13802     * clears the parent caches and does not causes an invalidate event.
13803     *
13804     * @hide
13805     */
13806    protected void invalidateParentCaches() {
13807        if (mParent instanceof View) {
13808            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
13809        }
13810    }
13811
13812    /**
13813     * Used to indicate that the parent of this view should be invalidated. This functionality
13814     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13815     * which is necessary when various parent-managed properties of the view change, such as
13816     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
13817     * an invalidation event to the parent.
13818     *
13819     * @hide
13820     */
13821    protected void invalidateParentIfNeeded() {
13822        if (isHardwareAccelerated() && mParent instanceof View) {
13823            ((View) mParent).invalidate(true);
13824        }
13825    }
13826
13827    /**
13828     * @hide
13829     */
13830    protected void invalidateParentIfNeededAndWasQuickRejected() {
13831        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
13832            // View was rejected last time it was drawn by its parent; this may have changed
13833            invalidateParentIfNeeded();
13834        }
13835    }
13836
13837    /**
13838     * Indicates whether this View is opaque. An opaque View guarantees that it will
13839     * draw all the pixels overlapping its bounds using a fully opaque color.
13840     *
13841     * Subclasses of View should override this method whenever possible to indicate
13842     * whether an instance is opaque. Opaque Views are treated in a special way by
13843     * the View hierarchy, possibly allowing it to perform optimizations during
13844     * invalidate/draw passes.
13845     *
13846     * @return True if this View is guaranteed to be fully opaque, false otherwise.
13847     */
13848    @ViewDebug.ExportedProperty(category = "drawing")
13849    public boolean isOpaque() {
13850        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13851                getFinalAlpha() >= 1.0f;
13852    }
13853
13854    /**
13855     * @hide
13856     */
13857    protected void computeOpaqueFlags() {
13858        // Opaque if:
13859        //   - Has a background
13860        //   - Background is opaque
13861        //   - Doesn't have scrollbars or scrollbars overlay
13862
13863        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13864            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13865        } else {
13866            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13867        }
13868
13869        final int flags = mViewFlags;
13870        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13871                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13872                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13873            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13874        } else {
13875            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13876        }
13877    }
13878
13879    /**
13880     * @hide
13881     */
13882    protected boolean hasOpaqueScrollbars() {
13883        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13884    }
13885
13886    /**
13887     * @return A handler associated with the thread running the View. This
13888     * handler can be used to pump events in the UI events queue.
13889     */
13890    public Handler getHandler() {
13891        final AttachInfo attachInfo = mAttachInfo;
13892        if (attachInfo != null) {
13893            return attachInfo.mHandler;
13894        }
13895        return null;
13896    }
13897
13898    /**
13899     * Returns the queue of runnable for this view.
13900     *
13901     * @return the queue of runnables for this view
13902     */
13903    private HandlerActionQueue getRunQueue() {
13904        if (mRunQueue == null) {
13905            mRunQueue = new HandlerActionQueue();
13906        }
13907        return mRunQueue;
13908    }
13909
13910    /**
13911     * Gets the view root associated with the View.
13912     * @return The view root, or null if none.
13913     * @hide
13914     */
13915    public ViewRootImpl getViewRootImpl() {
13916        if (mAttachInfo != null) {
13917            return mAttachInfo.mViewRootImpl;
13918        }
13919        return null;
13920    }
13921
13922    /**
13923     * @hide
13924     */
13925    public ThreadedRenderer getHardwareRenderer() {
13926        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
13927    }
13928
13929    /**
13930     * <p>Causes the Runnable to be added to the message queue.
13931     * The runnable will be run on the user interface thread.</p>
13932     *
13933     * @param action The Runnable that will be executed.
13934     *
13935     * @return Returns true if the Runnable was successfully placed in to the
13936     *         message queue.  Returns false on failure, usually because the
13937     *         looper processing the message queue is exiting.
13938     *
13939     * @see #postDelayed
13940     * @see #removeCallbacks
13941     */
13942    public boolean post(Runnable action) {
13943        final AttachInfo attachInfo = mAttachInfo;
13944        if (attachInfo != null) {
13945            return attachInfo.mHandler.post(action);
13946        }
13947
13948        // Postpone the runnable until we know on which thread it needs to run.
13949        // Assume that the runnable will be successfully placed after attach.
13950        getRunQueue().post(action);
13951        return true;
13952    }
13953
13954    /**
13955     * <p>Causes the Runnable to be added to the message queue, to be run
13956     * after the specified amount of time elapses.
13957     * The runnable will be run on the user interface thread.</p>
13958     *
13959     * @param action The Runnable that will be executed.
13960     * @param delayMillis The delay (in milliseconds) until the Runnable
13961     *        will be executed.
13962     *
13963     * @return true if the Runnable was successfully placed in to the
13964     *         message queue.  Returns false on failure, usually because the
13965     *         looper processing the message queue is exiting.  Note that a
13966     *         result of true does not mean the Runnable will be processed --
13967     *         if the looper is quit before the delivery time of the message
13968     *         occurs then the message will be dropped.
13969     *
13970     * @see #post
13971     * @see #removeCallbacks
13972     */
13973    public boolean postDelayed(Runnable action, long delayMillis) {
13974        final AttachInfo attachInfo = mAttachInfo;
13975        if (attachInfo != null) {
13976            return attachInfo.mHandler.postDelayed(action, delayMillis);
13977        }
13978
13979        // Postpone the runnable until we know on which thread it needs to run.
13980        // Assume that the runnable will be successfully placed after attach.
13981        getRunQueue().postDelayed(action, delayMillis);
13982        return true;
13983    }
13984
13985    /**
13986     * <p>Causes the Runnable to execute on the next animation time step.
13987     * The runnable will be run on the user interface thread.</p>
13988     *
13989     * @param action The Runnable that will be executed.
13990     *
13991     * @see #postOnAnimationDelayed
13992     * @see #removeCallbacks
13993     */
13994    public void postOnAnimation(Runnable action) {
13995        final AttachInfo attachInfo = mAttachInfo;
13996        if (attachInfo != null) {
13997            attachInfo.mViewRootImpl.mChoreographer.postCallback(
13998                    Choreographer.CALLBACK_ANIMATION, action, null);
13999        } else {
14000            // Postpone the runnable until we know
14001            // on which thread it needs to run.
14002            getRunQueue().post(action);
14003        }
14004    }
14005
14006    /**
14007     * <p>Causes the Runnable to execute on the next animation time step,
14008     * after the specified amount of time elapses.
14009     * The runnable will be run on the user interface thread.</p>
14010     *
14011     * @param action The Runnable that will be executed.
14012     * @param delayMillis The delay (in milliseconds) until the Runnable
14013     *        will be executed.
14014     *
14015     * @see #postOnAnimation
14016     * @see #removeCallbacks
14017     */
14018    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
14019        final AttachInfo attachInfo = mAttachInfo;
14020        if (attachInfo != null) {
14021            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
14022                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
14023        } else {
14024            // Postpone the runnable until we know
14025            // on which thread it needs to run.
14026            getRunQueue().postDelayed(action, delayMillis);
14027        }
14028    }
14029
14030    /**
14031     * <p>Removes the specified Runnable from the message queue.</p>
14032     *
14033     * @param action The Runnable to remove from the message handling queue
14034     *
14035     * @return true if this view could ask the Handler to remove the Runnable,
14036     *         false otherwise. When the returned value is true, the Runnable
14037     *         may or may not have been actually removed from the message queue
14038     *         (for instance, if the Runnable was not in the queue already.)
14039     *
14040     * @see #post
14041     * @see #postDelayed
14042     * @see #postOnAnimation
14043     * @see #postOnAnimationDelayed
14044     */
14045    public boolean removeCallbacks(Runnable action) {
14046        if (action != null) {
14047            final AttachInfo attachInfo = mAttachInfo;
14048            if (attachInfo != null) {
14049                attachInfo.mHandler.removeCallbacks(action);
14050                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14051                        Choreographer.CALLBACK_ANIMATION, action, null);
14052            }
14053            getRunQueue().removeCallbacks(action);
14054        }
14055        return true;
14056    }
14057
14058    /**
14059     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
14060     * Use this to invalidate the View from a non-UI thread.</p>
14061     *
14062     * <p>This method can be invoked from outside of the UI thread
14063     * only when this View is attached to a window.</p>
14064     *
14065     * @see #invalidate()
14066     * @see #postInvalidateDelayed(long)
14067     */
14068    public void postInvalidate() {
14069        postInvalidateDelayed(0);
14070    }
14071
14072    /**
14073     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14074     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
14075     *
14076     * <p>This method can be invoked from outside of the UI thread
14077     * only when this View is attached to a window.</p>
14078     *
14079     * @param left The left coordinate of the rectangle to invalidate.
14080     * @param top The top coordinate of the rectangle to invalidate.
14081     * @param right The right coordinate of the rectangle to invalidate.
14082     * @param bottom The bottom coordinate of the rectangle to invalidate.
14083     *
14084     * @see #invalidate(int, int, int, int)
14085     * @see #invalidate(Rect)
14086     * @see #postInvalidateDelayed(long, int, int, int, int)
14087     */
14088    public void postInvalidate(int left, int top, int right, int bottom) {
14089        postInvalidateDelayed(0, left, top, right, bottom);
14090    }
14091
14092    /**
14093     * <p>Cause an invalidate to happen on a subsequent cycle through the event
14094     * loop. Waits for the specified amount of time.</p>
14095     *
14096     * <p>This method can be invoked from outside of the UI thread
14097     * only when this View is attached to a window.</p>
14098     *
14099     * @param delayMilliseconds the duration in milliseconds to delay the
14100     *         invalidation by
14101     *
14102     * @see #invalidate()
14103     * @see #postInvalidate()
14104     */
14105    public void postInvalidateDelayed(long delayMilliseconds) {
14106        // We try only with the AttachInfo because there's no point in invalidating
14107        // if we are not attached to our window
14108        final AttachInfo attachInfo = mAttachInfo;
14109        if (attachInfo != null) {
14110            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
14111        }
14112    }
14113
14114    /**
14115     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14116     * through the event loop. Waits for the specified amount of time.</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     * @param delayMilliseconds the duration in milliseconds to delay the
14122     *         invalidation by
14123     * @param left The left coordinate of the rectangle to invalidate.
14124     * @param top The top coordinate of the rectangle to invalidate.
14125     * @param right The right coordinate of the rectangle to invalidate.
14126     * @param bottom The bottom coordinate of the rectangle to invalidate.
14127     *
14128     * @see #invalidate(int, int, int, int)
14129     * @see #invalidate(Rect)
14130     * @see #postInvalidate(int, int, int, int)
14131     */
14132    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
14133            int right, int bottom) {
14134
14135        // We try only with the AttachInfo because there's no point in invalidating
14136        // if we are not attached to our window
14137        final AttachInfo attachInfo = mAttachInfo;
14138        if (attachInfo != null) {
14139            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14140            info.target = this;
14141            info.left = left;
14142            info.top = top;
14143            info.right = right;
14144            info.bottom = bottom;
14145
14146            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
14147        }
14148    }
14149
14150    /**
14151     * <p>Cause an invalidate to happen on the next animation time step, typically the
14152     * next display frame.</p>
14153     *
14154     * <p>This method can be invoked from outside of the UI thread
14155     * only when this View is attached to a window.</p>
14156     *
14157     * @see #invalidate()
14158     */
14159    public void postInvalidateOnAnimation() {
14160        // We try only with the AttachInfo because there's no point in invalidating
14161        // if we are not attached to our window
14162        final AttachInfo attachInfo = mAttachInfo;
14163        if (attachInfo != null) {
14164            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
14165        }
14166    }
14167
14168    /**
14169     * <p>Cause an invalidate of the specified area to happen on the next animation
14170     * time step, typically the next display frame.</p>
14171     *
14172     * <p>This method can be invoked from outside of the UI thread
14173     * only when this View is attached to a window.</p>
14174     *
14175     * @param left The left coordinate of the rectangle to invalidate.
14176     * @param top The top coordinate of the rectangle to invalidate.
14177     * @param right The right coordinate of the rectangle to invalidate.
14178     * @param bottom The bottom coordinate of the rectangle to invalidate.
14179     *
14180     * @see #invalidate(int, int, int, int)
14181     * @see #invalidate(Rect)
14182     */
14183    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
14184        // We try only with the AttachInfo because there's no point in invalidating
14185        // if we are not attached to our window
14186        final AttachInfo attachInfo = mAttachInfo;
14187        if (attachInfo != null) {
14188            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14189            info.target = this;
14190            info.left = left;
14191            info.top = top;
14192            info.right = right;
14193            info.bottom = bottom;
14194
14195            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
14196        }
14197    }
14198
14199    /**
14200     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
14201     * This event is sent at most once every
14202     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
14203     */
14204    private void postSendViewScrolledAccessibilityEventCallback() {
14205        if (mSendViewScrolledAccessibilityEvent == null) {
14206            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
14207        }
14208        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
14209            mSendViewScrolledAccessibilityEvent.mIsPending = true;
14210            postDelayed(mSendViewScrolledAccessibilityEvent,
14211                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
14212        }
14213    }
14214
14215    /**
14216     * Called by a parent to request that a child update its values for mScrollX
14217     * and mScrollY if necessary. This will typically be done if the child is
14218     * animating a scroll using a {@link android.widget.Scroller Scroller}
14219     * object.
14220     */
14221    public void computeScroll() {
14222    }
14223
14224    /**
14225     * <p>Indicate whether the horizontal edges are faded when the view is
14226     * scrolled horizontally.</p>
14227     *
14228     * @return true if the horizontal edges should are faded on scroll, false
14229     *         otherwise
14230     *
14231     * @see #setHorizontalFadingEdgeEnabled(boolean)
14232     *
14233     * @attr ref android.R.styleable#View_requiresFadingEdge
14234     */
14235    public boolean isHorizontalFadingEdgeEnabled() {
14236        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
14237    }
14238
14239    /**
14240     * <p>Define whether the horizontal edges should be faded when this view
14241     * is scrolled horizontally.</p>
14242     *
14243     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
14244     *                                    be faded when the view is scrolled
14245     *                                    horizontally
14246     *
14247     * @see #isHorizontalFadingEdgeEnabled()
14248     *
14249     * @attr ref android.R.styleable#View_requiresFadingEdge
14250     */
14251    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
14252        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
14253            if (horizontalFadingEdgeEnabled) {
14254                initScrollCache();
14255            }
14256
14257            mViewFlags ^= FADING_EDGE_HORIZONTAL;
14258        }
14259    }
14260
14261    /**
14262     * <p>Indicate whether the vertical edges are faded when the view is
14263     * scrolled horizontally.</p>
14264     *
14265     * @return true if the vertical edges should are faded on scroll, false
14266     *         otherwise
14267     *
14268     * @see #setVerticalFadingEdgeEnabled(boolean)
14269     *
14270     * @attr ref android.R.styleable#View_requiresFadingEdge
14271     */
14272    public boolean isVerticalFadingEdgeEnabled() {
14273        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
14274    }
14275
14276    /**
14277     * <p>Define whether the vertical edges should be faded when this view
14278     * is scrolled vertically.</p>
14279     *
14280     * @param verticalFadingEdgeEnabled true if the vertical edges should
14281     *                                  be faded when the view is scrolled
14282     *                                  vertically
14283     *
14284     * @see #isVerticalFadingEdgeEnabled()
14285     *
14286     * @attr ref android.R.styleable#View_requiresFadingEdge
14287     */
14288    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
14289        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
14290            if (verticalFadingEdgeEnabled) {
14291                initScrollCache();
14292            }
14293
14294            mViewFlags ^= FADING_EDGE_VERTICAL;
14295        }
14296    }
14297
14298    /**
14299     * Returns the strength, or intensity, of the top faded edge. The strength is
14300     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14301     * returns 0.0 or 1.0 but no value in between.
14302     *
14303     * Subclasses should override this method to provide a smoother fade transition
14304     * when scrolling occurs.
14305     *
14306     * @return the intensity of the top fade as a float between 0.0f and 1.0f
14307     */
14308    protected float getTopFadingEdgeStrength() {
14309        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
14310    }
14311
14312    /**
14313     * Returns the strength, or intensity, of the bottom faded edge. The strength is
14314     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14315     * returns 0.0 or 1.0 but no value in between.
14316     *
14317     * Subclasses should override this method to provide a smoother fade transition
14318     * when scrolling occurs.
14319     *
14320     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
14321     */
14322    protected float getBottomFadingEdgeStrength() {
14323        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
14324                computeVerticalScrollRange() ? 1.0f : 0.0f;
14325    }
14326
14327    /**
14328     * Returns the strength, or intensity, of the left faded edge. The strength is
14329     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14330     * returns 0.0 or 1.0 but no value in between.
14331     *
14332     * Subclasses should override this method to provide a smoother fade transition
14333     * when scrolling occurs.
14334     *
14335     * @return the intensity of the left fade as a float between 0.0f and 1.0f
14336     */
14337    protected float getLeftFadingEdgeStrength() {
14338        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
14339    }
14340
14341    /**
14342     * Returns the strength, or intensity, of the right faded edge. The strength is
14343     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14344     * returns 0.0 or 1.0 but no value in between.
14345     *
14346     * Subclasses should override this method to provide a smoother fade transition
14347     * when scrolling occurs.
14348     *
14349     * @return the intensity of the right fade as a float between 0.0f and 1.0f
14350     */
14351    protected float getRightFadingEdgeStrength() {
14352        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
14353                computeHorizontalScrollRange() ? 1.0f : 0.0f;
14354    }
14355
14356    /**
14357     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
14358     * scrollbar is not drawn by default.</p>
14359     *
14360     * @return true if the horizontal scrollbar should be painted, false
14361     *         otherwise
14362     *
14363     * @see #setHorizontalScrollBarEnabled(boolean)
14364     */
14365    public boolean isHorizontalScrollBarEnabled() {
14366        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14367    }
14368
14369    /**
14370     * <p>Define whether the horizontal scrollbar should be drawn or not. The
14371     * scrollbar is not drawn by default.</p>
14372     *
14373     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
14374     *                                   be painted
14375     *
14376     * @see #isHorizontalScrollBarEnabled()
14377     */
14378    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
14379        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
14380            mViewFlags ^= SCROLLBARS_HORIZONTAL;
14381            computeOpaqueFlags();
14382            resolvePadding();
14383        }
14384    }
14385
14386    /**
14387     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
14388     * scrollbar is not drawn by default.</p>
14389     *
14390     * @return true if the vertical scrollbar should be painted, false
14391     *         otherwise
14392     *
14393     * @see #setVerticalScrollBarEnabled(boolean)
14394     */
14395    public boolean isVerticalScrollBarEnabled() {
14396        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
14397    }
14398
14399    /**
14400     * <p>Define whether the vertical scrollbar should be drawn or not. The
14401     * scrollbar is not drawn by default.</p>
14402     *
14403     * @param verticalScrollBarEnabled true if the vertical scrollbar should
14404     *                                 be painted
14405     *
14406     * @see #isVerticalScrollBarEnabled()
14407     */
14408    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
14409        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
14410            mViewFlags ^= SCROLLBARS_VERTICAL;
14411            computeOpaqueFlags();
14412            resolvePadding();
14413        }
14414    }
14415
14416    /**
14417     * @hide
14418     */
14419    protected void recomputePadding() {
14420        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14421    }
14422
14423    /**
14424     * Define whether scrollbars will fade when the view is not scrolling.
14425     *
14426     * @param fadeScrollbars whether to enable fading
14427     *
14428     * @attr ref android.R.styleable#View_fadeScrollbars
14429     */
14430    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
14431        initScrollCache();
14432        final ScrollabilityCache scrollabilityCache = mScrollCache;
14433        scrollabilityCache.fadeScrollBars = fadeScrollbars;
14434        if (fadeScrollbars) {
14435            scrollabilityCache.state = ScrollabilityCache.OFF;
14436        } else {
14437            scrollabilityCache.state = ScrollabilityCache.ON;
14438        }
14439    }
14440
14441    /**
14442     *
14443     * Returns true if scrollbars will fade when this view is not scrolling
14444     *
14445     * @return true if scrollbar fading is enabled
14446     *
14447     * @attr ref android.R.styleable#View_fadeScrollbars
14448     */
14449    public boolean isScrollbarFadingEnabled() {
14450        return mScrollCache != null && mScrollCache.fadeScrollBars;
14451    }
14452
14453    /**
14454     *
14455     * Returns the delay before scrollbars fade.
14456     *
14457     * @return the delay before scrollbars fade
14458     *
14459     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14460     */
14461    public int getScrollBarDefaultDelayBeforeFade() {
14462        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
14463                mScrollCache.scrollBarDefaultDelayBeforeFade;
14464    }
14465
14466    /**
14467     * Define the delay before scrollbars fade.
14468     *
14469     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
14470     *
14471     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14472     */
14473    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
14474        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
14475    }
14476
14477    /**
14478     *
14479     * Returns the scrollbar fade duration.
14480     *
14481     * @return the scrollbar fade duration
14482     *
14483     * @attr ref android.R.styleable#View_scrollbarFadeDuration
14484     */
14485    public int getScrollBarFadeDuration() {
14486        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
14487                mScrollCache.scrollBarFadeDuration;
14488    }
14489
14490    /**
14491     * Define the scrollbar fade duration.
14492     *
14493     * @param scrollBarFadeDuration - the scrollbar fade duration
14494     *
14495     * @attr ref android.R.styleable#View_scrollbarFadeDuration
14496     */
14497    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
14498        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
14499    }
14500
14501    /**
14502     *
14503     * Returns the scrollbar size.
14504     *
14505     * @return the scrollbar size
14506     *
14507     * @attr ref android.R.styleable#View_scrollbarSize
14508     */
14509    public int getScrollBarSize() {
14510        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
14511                mScrollCache.scrollBarSize;
14512    }
14513
14514    /**
14515     * Define the scrollbar size.
14516     *
14517     * @param scrollBarSize - the scrollbar size
14518     *
14519     * @attr ref android.R.styleable#View_scrollbarSize
14520     */
14521    public void setScrollBarSize(int scrollBarSize) {
14522        getScrollCache().scrollBarSize = scrollBarSize;
14523    }
14524
14525    /**
14526     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
14527     * inset. When inset, they add to the padding of the view. And the scrollbars
14528     * can be drawn inside the padding area or on the edge of the view. For example,
14529     * if a view has a background drawable and you want to draw the scrollbars
14530     * inside the padding specified by the drawable, you can use
14531     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
14532     * appear at the edge of the view, ignoring the padding, then you can use
14533     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
14534     * @param style the style of the scrollbars. Should be one of
14535     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
14536     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
14537     * @see #SCROLLBARS_INSIDE_OVERLAY
14538     * @see #SCROLLBARS_INSIDE_INSET
14539     * @see #SCROLLBARS_OUTSIDE_OVERLAY
14540     * @see #SCROLLBARS_OUTSIDE_INSET
14541     *
14542     * @attr ref android.R.styleable#View_scrollbarStyle
14543     */
14544    public void setScrollBarStyle(@ScrollBarStyle int style) {
14545        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
14546            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
14547            computeOpaqueFlags();
14548            resolvePadding();
14549        }
14550    }
14551
14552    /**
14553     * <p>Returns the current scrollbar style.</p>
14554     * @return the current scrollbar style
14555     * @see #SCROLLBARS_INSIDE_OVERLAY
14556     * @see #SCROLLBARS_INSIDE_INSET
14557     * @see #SCROLLBARS_OUTSIDE_OVERLAY
14558     * @see #SCROLLBARS_OUTSIDE_INSET
14559     *
14560     * @attr ref android.R.styleable#View_scrollbarStyle
14561     */
14562    @ViewDebug.ExportedProperty(mapping = {
14563            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
14564            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
14565            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
14566            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
14567    })
14568    @ScrollBarStyle
14569    public int getScrollBarStyle() {
14570        return mViewFlags & SCROLLBARS_STYLE_MASK;
14571    }
14572
14573    /**
14574     * <p>Compute the horizontal range that the horizontal scrollbar
14575     * represents.</p>
14576     *
14577     * <p>The range is expressed in arbitrary units that must be the same as the
14578     * units used by {@link #computeHorizontalScrollExtent()} and
14579     * {@link #computeHorizontalScrollOffset()}.</p>
14580     *
14581     * <p>The default range is the drawing width of this view.</p>
14582     *
14583     * @return the total horizontal range represented by the horizontal
14584     *         scrollbar
14585     *
14586     * @see #computeHorizontalScrollExtent()
14587     * @see #computeHorizontalScrollOffset()
14588     * @see android.widget.ScrollBarDrawable
14589     */
14590    protected int computeHorizontalScrollRange() {
14591        return getWidth();
14592    }
14593
14594    /**
14595     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
14596     * within the horizontal range. This value is used to compute the position
14597     * of the thumb within the scrollbar's track.</p>
14598     *
14599     * <p>The range is expressed in arbitrary units that must be the same as the
14600     * units used by {@link #computeHorizontalScrollRange()} and
14601     * {@link #computeHorizontalScrollExtent()}.</p>
14602     *
14603     * <p>The default offset is the scroll offset of this view.</p>
14604     *
14605     * @return the horizontal offset of the scrollbar's thumb
14606     *
14607     * @see #computeHorizontalScrollRange()
14608     * @see #computeHorizontalScrollExtent()
14609     * @see android.widget.ScrollBarDrawable
14610     */
14611    protected int computeHorizontalScrollOffset() {
14612        return mScrollX;
14613    }
14614
14615    /**
14616     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
14617     * within the horizontal range. This value is used to compute the length
14618     * of the thumb within the scrollbar's track.</p>
14619     *
14620     * <p>The range is expressed in arbitrary units that must be the same as the
14621     * units used by {@link #computeHorizontalScrollRange()} and
14622     * {@link #computeHorizontalScrollOffset()}.</p>
14623     *
14624     * <p>The default extent is the drawing width of this view.</p>
14625     *
14626     * @return the horizontal extent of the scrollbar's thumb
14627     *
14628     * @see #computeHorizontalScrollRange()
14629     * @see #computeHorizontalScrollOffset()
14630     * @see android.widget.ScrollBarDrawable
14631     */
14632    protected int computeHorizontalScrollExtent() {
14633        return getWidth();
14634    }
14635
14636    /**
14637     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
14638     *
14639     * <p>The range is expressed in arbitrary units that must be the same as the
14640     * units used by {@link #computeVerticalScrollExtent()} and
14641     * {@link #computeVerticalScrollOffset()}.</p>
14642     *
14643     * @return the total vertical range represented by the vertical scrollbar
14644     *
14645     * <p>The default range is the drawing height of this view.</p>
14646     *
14647     * @see #computeVerticalScrollExtent()
14648     * @see #computeVerticalScrollOffset()
14649     * @see android.widget.ScrollBarDrawable
14650     */
14651    protected int computeVerticalScrollRange() {
14652        return getHeight();
14653    }
14654
14655    /**
14656     * <p>Compute the vertical offset of the vertical scrollbar's thumb
14657     * within the horizontal range. This value is used to compute the position
14658     * of the thumb within the scrollbar's track.</p>
14659     *
14660     * <p>The range is expressed in arbitrary units that must be the same as the
14661     * units used by {@link #computeVerticalScrollRange()} and
14662     * {@link #computeVerticalScrollExtent()}.</p>
14663     *
14664     * <p>The default offset is the scroll offset of this view.</p>
14665     *
14666     * @return the vertical offset of the scrollbar's thumb
14667     *
14668     * @see #computeVerticalScrollRange()
14669     * @see #computeVerticalScrollExtent()
14670     * @see android.widget.ScrollBarDrawable
14671     */
14672    protected int computeVerticalScrollOffset() {
14673        return mScrollY;
14674    }
14675
14676    /**
14677     * <p>Compute the vertical extent of the vertical scrollbar's thumb
14678     * within the vertical range. This value is used to compute the length
14679     * of the thumb within the scrollbar's track.</p>
14680     *
14681     * <p>The range is expressed in arbitrary units that must be the same as the
14682     * units used by {@link #computeVerticalScrollRange()} and
14683     * {@link #computeVerticalScrollOffset()}.</p>
14684     *
14685     * <p>The default extent is the drawing height of this view.</p>
14686     *
14687     * @return the vertical extent of the scrollbar's thumb
14688     *
14689     * @see #computeVerticalScrollRange()
14690     * @see #computeVerticalScrollOffset()
14691     * @see android.widget.ScrollBarDrawable
14692     */
14693    protected int computeVerticalScrollExtent() {
14694        return getHeight();
14695    }
14696
14697    /**
14698     * Check if this view can be scrolled horizontally in a certain direction.
14699     *
14700     * @param direction Negative to check scrolling left, positive to check scrolling right.
14701     * @return true if this view can be scrolled in the specified direction, false otherwise.
14702     */
14703    public boolean canScrollHorizontally(int direction) {
14704        final int offset = computeHorizontalScrollOffset();
14705        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
14706        if (range == 0) return false;
14707        if (direction < 0) {
14708            return offset > 0;
14709        } else {
14710            return offset < range - 1;
14711        }
14712    }
14713
14714    /**
14715     * Check if this view can be scrolled vertically in a certain direction.
14716     *
14717     * @param direction Negative to check scrolling up, positive to check scrolling down.
14718     * @return true if this view can be scrolled in the specified direction, false otherwise.
14719     */
14720    public boolean canScrollVertically(int direction) {
14721        final int offset = computeVerticalScrollOffset();
14722        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
14723        if (range == 0) return false;
14724        if (direction < 0) {
14725            return offset > 0;
14726        } else {
14727            return offset < range - 1;
14728        }
14729    }
14730
14731    void getScrollIndicatorBounds(@NonNull Rect out) {
14732        out.left = mScrollX;
14733        out.right = mScrollX + mRight - mLeft;
14734        out.top = mScrollY;
14735        out.bottom = mScrollY + mBottom - mTop;
14736    }
14737
14738    private void onDrawScrollIndicators(Canvas c) {
14739        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
14740            // No scroll indicators enabled.
14741            return;
14742        }
14743
14744        final Drawable dr = mScrollIndicatorDrawable;
14745        if (dr == null) {
14746            // Scroll indicators aren't supported here.
14747            return;
14748        }
14749
14750        final int h = dr.getIntrinsicHeight();
14751        final int w = dr.getIntrinsicWidth();
14752        final Rect rect = mAttachInfo.mTmpInvalRect;
14753        getScrollIndicatorBounds(rect);
14754
14755        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
14756            final boolean canScrollUp = canScrollVertically(-1);
14757            if (canScrollUp) {
14758                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
14759                dr.draw(c);
14760            }
14761        }
14762
14763        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
14764            final boolean canScrollDown = canScrollVertically(1);
14765            if (canScrollDown) {
14766                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
14767                dr.draw(c);
14768            }
14769        }
14770
14771        final int leftRtl;
14772        final int rightRtl;
14773        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14774            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
14775            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
14776        } else {
14777            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
14778            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
14779        }
14780
14781        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
14782        if ((mPrivateFlags3 & leftMask) != 0) {
14783            final boolean canScrollLeft = canScrollHorizontally(-1);
14784            if (canScrollLeft) {
14785                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
14786                dr.draw(c);
14787            }
14788        }
14789
14790        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
14791        if ((mPrivateFlags3 & rightMask) != 0) {
14792            final boolean canScrollRight = canScrollHorizontally(1);
14793            if (canScrollRight) {
14794                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
14795                dr.draw(c);
14796            }
14797        }
14798    }
14799
14800    private void getHorizontalScrollBarBounds(Rect bounds) {
14801        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14802        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14803                && !isVerticalScrollBarHidden();
14804        final int size = getHorizontalScrollbarHeight();
14805        final int verticalScrollBarGap = drawVerticalScrollBar ?
14806                getVerticalScrollbarWidth() : 0;
14807        final int width = mRight - mLeft;
14808        final int height = mBottom - mTop;
14809        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
14810        bounds.left = mScrollX + (mPaddingLeft & inside);
14811        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14812        bounds.bottom = bounds.top + size;
14813    }
14814
14815    private void getVerticalScrollBarBounds(Rect bounds) {
14816        if (mRoundScrollbarRenderer == null) {
14817            getStraightVerticalScrollBarBounds(bounds);
14818        } else {
14819            getRoundVerticalScrollBarBounds(bounds);
14820        }
14821    }
14822
14823    private void getRoundVerticalScrollBarBounds(Rect bounds) {
14824        final int width = mRight - mLeft;
14825        final int height = mBottom - mTop;
14826        // Do not take padding into account as we always want the scrollbars
14827        // to hug the screen for round wearable devices.
14828        bounds.left = mScrollX;
14829        bounds.top = mScrollY;
14830        bounds.right = bounds.left + width;
14831        bounds.bottom = mScrollY + height;
14832    }
14833
14834    private void getStraightVerticalScrollBarBounds(Rect bounds) {
14835        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14836        final int size = getVerticalScrollbarWidth();
14837        int verticalScrollbarPosition = mVerticalScrollbarPosition;
14838        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14839            verticalScrollbarPosition = isLayoutRtl() ?
14840                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14841        }
14842        final int width = mRight - mLeft;
14843        final int height = mBottom - mTop;
14844        switch (verticalScrollbarPosition) {
14845            default:
14846            case SCROLLBAR_POSITION_RIGHT:
14847                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
14848                break;
14849            case SCROLLBAR_POSITION_LEFT:
14850                bounds.left = mScrollX + (mUserPaddingLeft & inside);
14851                break;
14852        }
14853        bounds.top = mScrollY + (mPaddingTop & inside);
14854        bounds.right = bounds.left + size;
14855        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
14856    }
14857
14858    /**
14859     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
14860     * scrollbars are painted only if they have been awakened first.</p>
14861     *
14862     * @param canvas the canvas on which to draw the scrollbars
14863     *
14864     * @see #awakenScrollBars(int)
14865     */
14866    protected final void onDrawScrollBars(Canvas canvas) {
14867        // scrollbars are drawn only when the animation is running
14868        final ScrollabilityCache cache = mScrollCache;
14869
14870        if (cache != null) {
14871
14872            int state = cache.state;
14873
14874            if (state == ScrollabilityCache.OFF) {
14875                return;
14876            }
14877
14878            boolean invalidate = false;
14879
14880            if (state == ScrollabilityCache.FADING) {
14881                // We're fading -- get our fade interpolation
14882                if (cache.interpolatorValues == null) {
14883                    cache.interpolatorValues = new float[1];
14884                }
14885
14886                float[] values = cache.interpolatorValues;
14887
14888                // Stops the animation if we're done
14889                if (cache.scrollBarInterpolator.timeToValues(values) ==
14890                        Interpolator.Result.FREEZE_END) {
14891                    cache.state = ScrollabilityCache.OFF;
14892                } else {
14893                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14894                }
14895
14896                // This will make the scroll bars inval themselves after
14897                // drawing. We only want this when we're fading so that
14898                // we prevent excessive redraws
14899                invalidate = true;
14900            } else {
14901                // We're just on -- but we may have been fading before so
14902                // reset alpha
14903                cache.scrollBar.mutate().setAlpha(255);
14904            }
14905
14906            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
14907            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14908                    && !isVerticalScrollBarHidden();
14909
14910            // Fork out the scroll bar drawing for round wearable devices.
14911            if (mRoundScrollbarRenderer != null) {
14912                if (drawVerticalScrollBar) {
14913                    final Rect bounds = cache.mScrollBarBounds;
14914                    getVerticalScrollBarBounds(bounds);
14915                    mRoundScrollbarRenderer.drawRoundScrollbars(
14916                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
14917                    if (invalidate) {
14918                        invalidate();
14919                    }
14920                }
14921                // Do not draw horizontal scroll bars for round wearable devices.
14922            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14923                final ScrollBarDrawable scrollBar = cache.scrollBar;
14924
14925                if (drawHorizontalScrollBar) {
14926                    scrollBar.setParameters(computeHorizontalScrollRange(),
14927                            computeHorizontalScrollOffset(),
14928                            computeHorizontalScrollExtent(), false);
14929                    final Rect bounds = cache.mScrollBarBounds;
14930                    getHorizontalScrollBarBounds(bounds);
14931                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14932                            bounds.right, bounds.bottom);
14933                    if (invalidate) {
14934                        invalidate(bounds);
14935                    }
14936                }
14937
14938                if (drawVerticalScrollBar) {
14939                    scrollBar.setParameters(computeVerticalScrollRange(),
14940                            computeVerticalScrollOffset(),
14941                            computeVerticalScrollExtent(), true);
14942                    final Rect bounds = cache.mScrollBarBounds;
14943                    getVerticalScrollBarBounds(bounds);
14944                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14945                            bounds.right, bounds.bottom);
14946                    if (invalidate) {
14947                        invalidate(bounds);
14948                    }
14949                }
14950            }
14951        }
14952    }
14953
14954    /**
14955     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14956     * FastScroller is visible.
14957     * @return whether to temporarily hide the vertical scrollbar
14958     * @hide
14959     */
14960    protected boolean isVerticalScrollBarHidden() {
14961        return false;
14962    }
14963
14964    /**
14965     * <p>Draw the horizontal scrollbar if
14966     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14967     *
14968     * @param canvas the canvas on which to draw the scrollbar
14969     * @param scrollBar the scrollbar's drawable
14970     *
14971     * @see #isHorizontalScrollBarEnabled()
14972     * @see #computeHorizontalScrollRange()
14973     * @see #computeHorizontalScrollExtent()
14974     * @see #computeHorizontalScrollOffset()
14975     * @see android.widget.ScrollBarDrawable
14976     * @hide
14977     */
14978    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14979            int l, int t, int r, int b) {
14980        scrollBar.setBounds(l, t, r, b);
14981        scrollBar.draw(canvas);
14982    }
14983
14984    /**
14985     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14986     * returns true.</p>
14987     *
14988     * @param canvas the canvas on which to draw the scrollbar
14989     * @param scrollBar the scrollbar's drawable
14990     *
14991     * @see #isVerticalScrollBarEnabled()
14992     * @see #computeVerticalScrollRange()
14993     * @see #computeVerticalScrollExtent()
14994     * @see #computeVerticalScrollOffset()
14995     * @see android.widget.ScrollBarDrawable
14996     * @hide
14997     */
14998    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14999            int l, int t, int r, int b) {
15000        scrollBar.setBounds(l, t, r, b);
15001        scrollBar.draw(canvas);
15002    }
15003
15004    /**
15005     * Implement this to do your drawing.
15006     *
15007     * @param canvas the canvas on which the background will be drawn
15008     */
15009    protected void onDraw(Canvas canvas) {
15010    }
15011
15012    /*
15013     * Caller is responsible for calling requestLayout if necessary.
15014     * (This allows addViewInLayout to not request a new layout.)
15015     */
15016    void assignParent(ViewParent parent) {
15017        if (mParent == null) {
15018            mParent = parent;
15019        } else if (parent == null) {
15020            mParent = null;
15021        } else {
15022            throw new RuntimeException("view " + this + " being added, but"
15023                    + " it already has a parent");
15024        }
15025    }
15026
15027    /**
15028     * This is called when the view is attached to a window.  At this point it
15029     * has a Surface and will start drawing.  Note that this function is
15030     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
15031     * however it may be called any time before the first onDraw -- including
15032     * before or after {@link #onMeasure(int, int)}.
15033     *
15034     * @see #onDetachedFromWindow()
15035     */
15036    @CallSuper
15037    protected void onAttachedToWindow() {
15038        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
15039            mParent.requestTransparentRegion(this);
15040        }
15041
15042        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15043
15044        jumpDrawablesToCurrentState();
15045
15046        resetSubtreeAccessibilityStateChanged();
15047
15048        // rebuild, since Outline not maintained while View is detached
15049        rebuildOutline();
15050
15051        if (isFocused()) {
15052            InputMethodManager imm = InputMethodManager.peekInstance();
15053            if (imm != null) {
15054                imm.focusIn(this);
15055            }
15056        }
15057    }
15058
15059    /**
15060     * Resolve all RTL related properties.
15061     *
15062     * @return true if resolution of RTL properties has been done
15063     *
15064     * @hide
15065     */
15066    public boolean resolveRtlPropertiesIfNeeded() {
15067        if (!needRtlPropertiesResolution()) return false;
15068
15069        // Order is important here: LayoutDirection MUST be resolved first
15070        if (!isLayoutDirectionResolved()) {
15071            resolveLayoutDirection();
15072            resolveLayoutParams();
15073        }
15074        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
15075        if (!isTextDirectionResolved()) {
15076            resolveTextDirection();
15077        }
15078        if (!isTextAlignmentResolved()) {
15079            resolveTextAlignment();
15080        }
15081        // Should resolve Drawables before Padding because we need the layout direction of the
15082        // Drawable to correctly resolve Padding.
15083        if (!areDrawablesResolved()) {
15084            resolveDrawables();
15085        }
15086        if (!isPaddingResolved()) {
15087            resolvePadding();
15088        }
15089        onRtlPropertiesChanged(getLayoutDirection());
15090        return true;
15091    }
15092
15093    /**
15094     * Reset resolution of all RTL related properties.
15095     *
15096     * @hide
15097     */
15098    public void resetRtlProperties() {
15099        resetResolvedLayoutDirection();
15100        resetResolvedTextDirection();
15101        resetResolvedTextAlignment();
15102        resetResolvedPadding();
15103        resetResolvedDrawables();
15104    }
15105
15106    /**
15107     * @see #onScreenStateChanged(int)
15108     */
15109    void dispatchScreenStateChanged(int screenState) {
15110        onScreenStateChanged(screenState);
15111    }
15112
15113    /**
15114     * This method is called whenever the state of the screen this view is
15115     * attached to changes. A state change will usually occurs when the screen
15116     * turns on or off (whether it happens automatically or the user does it
15117     * manually.)
15118     *
15119     * @param screenState The new state of the screen. Can be either
15120     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
15121     */
15122    public void onScreenStateChanged(int screenState) {
15123    }
15124
15125    /**
15126     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
15127     */
15128    private boolean hasRtlSupport() {
15129        return mContext.getApplicationInfo().hasRtlSupport();
15130    }
15131
15132    /**
15133     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
15134     * RTL not supported)
15135     */
15136    private boolean isRtlCompatibilityMode() {
15137        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
15138        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
15139    }
15140
15141    /**
15142     * @return true if RTL properties need resolution.
15143     *
15144     */
15145    private boolean needRtlPropertiesResolution() {
15146        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
15147    }
15148
15149    /**
15150     * Called when any RTL property (layout direction or text direction or text alignment) has
15151     * been changed.
15152     *
15153     * Subclasses need to override this method to take care of cached information that depends on the
15154     * resolved layout direction, or to inform child views that inherit their layout direction.
15155     *
15156     * The default implementation does nothing.
15157     *
15158     * @param layoutDirection the direction of the layout
15159     *
15160     * @see #LAYOUT_DIRECTION_LTR
15161     * @see #LAYOUT_DIRECTION_RTL
15162     */
15163    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
15164    }
15165
15166    /**
15167     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
15168     * that the parent directionality can and will be resolved before its children.
15169     *
15170     * @return true if resolution has been done, false otherwise.
15171     *
15172     * @hide
15173     */
15174    public boolean resolveLayoutDirection() {
15175        // Clear any previous layout direction resolution
15176        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15177
15178        if (hasRtlSupport()) {
15179            // Set resolved depending on layout direction
15180            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
15181                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
15182                case LAYOUT_DIRECTION_INHERIT:
15183                    // We cannot resolve yet. LTR is by default and let the resolution happen again
15184                    // later to get the correct resolved value
15185                    if (!canResolveLayoutDirection()) return false;
15186
15187                    // Parent has not yet resolved, LTR is still the default
15188                    try {
15189                        if (!mParent.isLayoutDirectionResolved()) return false;
15190
15191                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15192                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15193                        }
15194                    } catch (AbstractMethodError e) {
15195                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15196                                " does not fully implement ViewParent", e);
15197                    }
15198                    break;
15199                case LAYOUT_DIRECTION_RTL:
15200                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15201                    break;
15202                case LAYOUT_DIRECTION_LOCALE:
15203                    if((LAYOUT_DIRECTION_RTL ==
15204                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
15205                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15206                    }
15207                    break;
15208                default:
15209                    // Nothing to do, LTR by default
15210            }
15211        }
15212
15213        // Set to resolved
15214        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15215        return true;
15216    }
15217
15218    /**
15219     * Check if layout direction resolution can be done.
15220     *
15221     * @return true if layout direction resolution can be done otherwise return false.
15222     */
15223    public boolean canResolveLayoutDirection() {
15224        switch (getRawLayoutDirection()) {
15225            case LAYOUT_DIRECTION_INHERIT:
15226                if (mParent != null) {
15227                    try {
15228                        return mParent.canResolveLayoutDirection();
15229                    } catch (AbstractMethodError e) {
15230                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15231                                " does not fully implement ViewParent", e);
15232                    }
15233                }
15234                return false;
15235
15236            default:
15237                return true;
15238        }
15239    }
15240
15241    /**
15242     * Reset the resolved layout direction. Layout direction will be resolved during a call to
15243     * {@link #onMeasure(int, int)}.
15244     *
15245     * @hide
15246     */
15247    public void resetResolvedLayoutDirection() {
15248        // Reset the current resolved bits
15249        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15250    }
15251
15252    /**
15253     * @return true if the layout direction is inherited.
15254     *
15255     * @hide
15256     */
15257    public boolean isLayoutDirectionInherited() {
15258        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
15259    }
15260
15261    /**
15262     * @return true if layout direction has been resolved.
15263     */
15264    public boolean isLayoutDirectionResolved() {
15265        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15266    }
15267
15268    /**
15269     * Return if padding has been resolved
15270     *
15271     * @hide
15272     */
15273    boolean isPaddingResolved() {
15274        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
15275    }
15276
15277    /**
15278     * Resolves padding depending on layout direction, if applicable, and
15279     * recomputes internal padding values to adjust for scroll bars.
15280     *
15281     * @hide
15282     */
15283    public void resolvePadding() {
15284        final int resolvedLayoutDirection = getLayoutDirection();
15285
15286        if (!isRtlCompatibilityMode()) {
15287            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
15288            // If start / end padding are defined, they will be resolved (hence overriding) to
15289            // left / right or right / left depending on the resolved layout direction.
15290            // If start / end padding are not defined, use the left / right ones.
15291            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
15292                Rect padding = sThreadLocal.get();
15293                if (padding == null) {
15294                    padding = new Rect();
15295                    sThreadLocal.set(padding);
15296                }
15297                mBackground.getPadding(padding);
15298                if (!mLeftPaddingDefined) {
15299                    mUserPaddingLeftInitial = padding.left;
15300                }
15301                if (!mRightPaddingDefined) {
15302                    mUserPaddingRightInitial = padding.right;
15303                }
15304            }
15305            switch (resolvedLayoutDirection) {
15306                case LAYOUT_DIRECTION_RTL:
15307                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15308                        mUserPaddingRight = mUserPaddingStart;
15309                    } else {
15310                        mUserPaddingRight = mUserPaddingRightInitial;
15311                    }
15312                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15313                        mUserPaddingLeft = mUserPaddingEnd;
15314                    } else {
15315                        mUserPaddingLeft = mUserPaddingLeftInitial;
15316                    }
15317                    break;
15318                case LAYOUT_DIRECTION_LTR:
15319                default:
15320                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15321                        mUserPaddingLeft = mUserPaddingStart;
15322                    } else {
15323                        mUserPaddingLeft = mUserPaddingLeftInitial;
15324                    }
15325                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15326                        mUserPaddingRight = mUserPaddingEnd;
15327                    } else {
15328                        mUserPaddingRight = mUserPaddingRightInitial;
15329                    }
15330            }
15331
15332            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
15333        }
15334
15335        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15336        onRtlPropertiesChanged(resolvedLayoutDirection);
15337
15338        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
15339    }
15340
15341    /**
15342     * Reset the resolved layout direction.
15343     *
15344     * @hide
15345     */
15346    public void resetResolvedPadding() {
15347        resetResolvedPaddingInternal();
15348    }
15349
15350    /**
15351     * Used when we only want to reset *this* view's padding and not trigger overrides
15352     * in ViewGroup that reset children too.
15353     */
15354    void resetResolvedPaddingInternal() {
15355        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
15356    }
15357
15358    /**
15359     * This is called when the view is detached from a window.  At this point it
15360     * no longer has a surface for drawing.
15361     *
15362     * @see #onAttachedToWindow()
15363     */
15364    @CallSuper
15365    protected void onDetachedFromWindow() {
15366    }
15367
15368    /**
15369     * This is a framework-internal mirror of onDetachedFromWindow() that's called
15370     * after onDetachedFromWindow().
15371     *
15372     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
15373     * The super method should be called at the end of the overridden method to ensure
15374     * subclasses are destroyed first
15375     *
15376     * @hide
15377     */
15378    @CallSuper
15379    protected void onDetachedFromWindowInternal() {
15380        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
15381        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15382        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
15383
15384        removeUnsetPressCallback();
15385        removeLongPressCallback();
15386        removePerformClickCallback();
15387        removeSendViewScrolledAccessibilityEventCallback();
15388        stopNestedScroll();
15389
15390        // Anything that started animating right before detach should already
15391        // be in its final state when re-attached.
15392        jumpDrawablesToCurrentState();
15393
15394        destroyDrawingCache();
15395
15396        cleanupDraw();
15397        mCurrentAnimation = null;
15398    }
15399
15400    private void cleanupDraw() {
15401        resetDisplayList();
15402        if (mAttachInfo != null) {
15403            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
15404        }
15405    }
15406
15407    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
15408    }
15409
15410    /**
15411     * @return The number of times this view has been attached to a window
15412     */
15413    protected int getWindowAttachCount() {
15414        return mWindowAttachCount;
15415    }
15416
15417    /**
15418     * Retrieve a unique token identifying the window this view is attached to.
15419     * @return Return the window's token for use in
15420     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
15421     */
15422    public IBinder getWindowToken() {
15423        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
15424    }
15425
15426    /**
15427     * Retrieve the {@link WindowId} for the window this view is
15428     * currently attached to.
15429     */
15430    public WindowId getWindowId() {
15431        if (mAttachInfo == null) {
15432            return null;
15433        }
15434        if (mAttachInfo.mWindowId == null) {
15435            try {
15436                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
15437                        mAttachInfo.mWindowToken);
15438                mAttachInfo.mWindowId = new WindowId(
15439                        mAttachInfo.mIWindowId);
15440            } catch (RemoteException e) {
15441            }
15442        }
15443        return mAttachInfo.mWindowId;
15444    }
15445
15446    /**
15447     * Retrieve a unique token identifying the top-level "real" window of
15448     * the window that this view is attached to.  That is, this is like
15449     * {@link #getWindowToken}, except if the window this view in is a panel
15450     * window (attached to another containing window), then the token of
15451     * the containing window is returned instead.
15452     *
15453     * @return Returns the associated window token, either
15454     * {@link #getWindowToken()} or the containing window's token.
15455     */
15456    public IBinder getApplicationWindowToken() {
15457        AttachInfo ai = mAttachInfo;
15458        if (ai != null) {
15459            IBinder appWindowToken = ai.mPanelParentWindowToken;
15460            if (appWindowToken == null) {
15461                appWindowToken = ai.mWindowToken;
15462            }
15463            return appWindowToken;
15464        }
15465        return null;
15466    }
15467
15468    /**
15469     * Gets the logical display to which the view's window has been attached.
15470     *
15471     * @return The logical display, or null if the view is not currently attached to a window.
15472     */
15473    public Display getDisplay() {
15474        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
15475    }
15476
15477    /**
15478     * Retrieve private session object this view hierarchy is using to
15479     * communicate with the window manager.
15480     * @return the session object to communicate with the window manager
15481     */
15482    /*package*/ IWindowSession getWindowSession() {
15483        return mAttachInfo != null ? mAttachInfo.mSession : null;
15484    }
15485
15486    /**
15487     * Return the visibility value of the least visible component passed.
15488     */
15489    int combineVisibility(int vis1, int vis2) {
15490        // This works because VISIBLE < INVISIBLE < GONE.
15491        return Math.max(vis1, vis2);
15492    }
15493
15494    /**
15495     * @param info the {@link android.view.View.AttachInfo} to associated with
15496     *        this view
15497     */
15498    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
15499        mAttachInfo = info;
15500        if (mOverlay != null) {
15501            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
15502        }
15503        mWindowAttachCount++;
15504        // We will need to evaluate the drawable state at least once.
15505        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15506        if (mFloatingTreeObserver != null) {
15507            info.mTreeObserver.merge(mFloatingTreeObserver);
15508            mFloatingTreeObserver = null;
15509        }
15510
15511        registerPendingFrameMetricsObservers();
15512
15513        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
15514            mAttachInfo.mScrollContainers.add(this);
15515            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
15516        }
15517        // Transfer all pending runnables.
15518        if (mRunQueue != null) {
15519            mRunQueue.executeActions(info.mHandler);
15520            mRunQueue = null;
15521        }
15522        performCollectViewAttributes(mAttachInfo, visibility);
15523        onAttachedToWindow();
15524
15525        ListenerInfo li = mListenerInfo;
15526        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15527                li != null ? li.mOnAttachStateChangeListeners : null;
15528        if (listeners != null && listeners.size() > 0) {
15529            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15530            // perform the dispatching. The iterator is a safe guard against listeners that
15531            // could mutate the list by calling the various add/remove methods. This prevents
15532            // the array from being modified while we iterate it.
15533            for (OnAttachStateChangeListener listener : listeners) {
15534                listener.onViewAttachedToWindow(this);
15535            }
15536        }
15537
15538        int vis = info.mWindowVisibility;
15539        if (vis != GONE) {
15540            onWindowVisibilityChanged(vis);
15541            if (isShown()) {
15542                // Calling onVisibilityAggregated directly here since the subtree will also
15543                // receive dispatchAttachedToWindow and this same call
15544                onVisibilityAggregated(vis == VISIBLE);
15545            }
15546        }
15547
15548        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
15549        // As all views in the subtree will already receive dispatchAttachedToWindow
15550        // traversing the subtree again here is not desired.
15551        onVisibilityChanged(this, visibility);
15552
15553        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
15554            // If nobody has evaluated the drawable state yet, then do it now.
15555            refreshDrawableState();
15556        }
15557        needGlobalAttributesUpdate(false);
15558    }
15559
15560    void dispatchDetachedFromWindow() {
15561        AttachInfo info = mAttachInfo;
15562        if (info != null) {
15563            int vis = info.mWindowVisibility;
15564            if (vis != GONE) {
15565                onWindowVisibilityChanged(GONE);
15566                if (isShown()) {
15567                    // Invoking onVisibilityAggregated directly here since the subtree
15568                    // will also receive detached from window
15569                    onVisibilityAggregated(false);
15570                }
15571            }
15572        }
15573
15574        onDetachedFromWindow();
15575        onDetachedFromWindowInternal();
15576
15577        InputMethodManager imm = InputMethodManager.peekInstance();
15578        if (imm != null) {
15579            imm.onViewDetachedFromWindow(this);
15580        }
15581
15582        ListenerInfo li = mListenerInfo;
15583        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15584                li != null ? li.mOnAttachStateChangeListeners : null;
15585        if (listeners != null && listeners.size() > 0) {
15586            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15587            // perform the dispatching. The iterator is a safe guard against listeners that
15588            // could mutate the list by calling the various add/remove methods. This prevents
15589            // the array from being modified while we iterate it.
15590            for (OnAttachStateChangeListener listener : listeners) {
15591                listener.onViewDetachedFromWindow(this);
15592            }
15593        }
15594
15595        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
15596            mAttachInfo.mScrollContainers.remove(this);
15597            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
15598        }
15599
15600        mAttachInfo = null;
15601        if (mOverlay != null) {
15602            mOverlay.getOverlayView().dispatchDetachedFromWindow();
15603        }
15604    }
15605
15606    /**
15607     * Cancel any deferred high-level input events that were previously posted to the event queue.
15608     *
15609     * <p>Many views post high-level events such as click handlers to the event queue
15610     * to run deferred in order to preserve a desired user experience - clearing visible
15611     * pressed states before executing, etc. This method will abort any events of this nature
15612     * that are currently in flight.</p>
15613     *
15614     * <p>Custom views that generate their own high-level deferred input events should override
15615     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
15616     *
15617     * <p>This will also cancel pending input events for any child views.</p>
15618     *
15619     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
15620     * This will not impact newer events posted after this call that may occur as a result of
15621     * lower-level input events still waiting in the queue. If you are trying to prevent
15622     * double-submitted  events for the duration of some sort of asynchronous transaction
15623     * you should also take other steps to protect against unexpected double inputs e.g. calling
15624     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
15625     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
15626     */
15627    public final void cancelPendingInputEvents() {
15628        dispatchCancelPendingInputEvents();
15629    }
15630
15631    /**
15632     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
15633     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
15634     */
15635    void dispatchCancelPendingInputEvents() {
15636        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
15637        onCancelPendingInputEvents();
15638        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
15639            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
15640                    " did not call through to super.onCancelPendingInputEvents()");
15641        }
15642    }
15643
15644    /**
15645     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
15646     * a parent view.
15647     *
15648     * <p>This method is responsible for removing any pending high-level input events that were
15649     * posted to the event queue to run later. Custom view classes that post their own deferred
15650     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
15651     * {@link android.os.Handler} should override this method, call
15652     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
15653     * </p>
15654     */
15655    public void onCancelPendingInputEvents() {
15656        removePerformClickCallback();
15657        cancelLongPress();
15658        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
15659    }
15660
15661    /**
15662     * Store this view hierarchy's frozen state into the given container.
15663     *
15664     * @param container The SparseArray in which to save the view's state.
15665     *
15666     * @see #restoreHierarchyState(android.util.SparseArray)
15667     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15668     * @see #onSaveInstanceState()
15669     */
15670    public void saveHierarchyState(SparseArray<Parcelable> container) {
15671        dispatchSaveInstanceState(container);
15672    }
15673
15674    /**
15675     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
15676     * this view and its children. May be overridden to modify how freezing happens to a
15677     * view's children; for example, some views may want to not store state for their children.
15678     *
15679     * @param container The SparseArray in which to save the view's state.
15680     *
15681     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15682     * @see #saveHierarchyState(android.util.SparseArray)
15683     * @see #onSaveInstanceState()
15684     */
15685    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
15686        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
15687            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15688            Parcelable state = onSaveInstanceState();
15689            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15690                throw new IllegalStateException(
15691                        "Derived class did not call super.onSaveInstanceState()");
15692            }
15693            if (state != null) {
15694                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
15695                // + ": " + state);
15696                container.put(mID, state);
15697            }
15698        }
15699    }
15700
15701    /**
15702     * Hook allowing a view to generate a representation of its internal state
15703     * that can later be used to create a new instance with that same state.
15704     * This state should only contain information that is not persistent or can
15705     * not be reconstructed later. For example, you will never store your
15706     * current position on screen because that will be computed again when a
15707     * new instance of the view is placed in its view hierarchy.
15708     * <p>
15709     * Some examples of things you may store here: the current cursor position
15710     * in a text view (but usually not the text itself since that is stored in a
15711     * content provider or other persistent storage), the currently selected
15712     * item in a list view.
15713     *
15714     * @return Returns a Parcelable object containing the view's current dynamic
15715     *         state, or null if there is nothing interesting to save. The
15716     *         default implementation returns null.
15717     * @see #onRestoreInstanceState(android.os.Parcelable)
15718     * @see #saveHierarchyState(android.util.SparseArray)
15719     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15720     * @see #setSaveEnabled(boolean)
15721     */
15722    @CallSuper
15723    protected Parcelable onSaveInstanceState() {
15724        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15725        if (mStartActivityRequestWho != null) {
15726            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
15727            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
15728            return state;
15729        }
15730        return BaseSavedState.EMPTY_STATE;
15731    }
15732
15733    /**
15734     * Restore this view hierarchy's frozen state from the given container.
15735     *
15736     * @param container The SparseArray which holds previously frozen states.
15737     *
15738     * @see #saveHierarchyState(android.util.SparseArray)
15739     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15740     * @see #onRestoreInstanceState(android.os.Parcelable)
15741     */
15742    public void restoreHierarchyState(SparseArray<Parcelable> container) {
15743        dispatchRestoreInstanceState(container);
15744    }
15745
15746    /**
15747     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
15748     * state for this view and its children. May be overridden to modify how restoring
15749     * happens to a view's children; for example, some views may want to not store state
15750     * for their children.
15751     *
15752     * @param container The SparseArray which holds previously saved state.
15753     *
15754     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15755     * @see #restoreHierarchyState(android.util.SparseArray)
15756     * @see #onRestoreInstanceState(android.os.Parcelable)
15757     */
15758    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
15759        if (mID != NO_ID) {
15760            Parcelable state = container.get(mID);
15761            if (state != null) {
15762                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
15763                // + ": " + state);
15764                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15765                onRestoreInstanceState(state);
15766                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15767                    throw new IllegalStateException(
15768                            "Derived class did not call super.onRestoreInstanceState()");
15769                }
15770            }
15771        }
15772    }
15773
15774    /**
15775     * Hook allowing a view to re-apply a representation of its internal state that had previously
15776     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
15777     * null state.
15778     *
15779     * @param state The frozen state that had previously been returned by
15780     *        {@link #onSaveInstanceState}.
15781     *
15782     * @see #onSaveInstanceState()
15783     * @see #restoreHierarchyState(android.util.SparseArray)
15784     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15785     */
15786    @CallSuper
15787    protected void onRestoreInstanceState(Parcelable state) {
15788        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15789        if (state != null && !(state instanceof AbsSavedState)) {
15790            throw new IllegalArgumentException("Wrong state class, expecting View State but "
15791                    + "received " + state.getClass().toString() + " instead. This usually happens "
15792                    + "when two views of different type have the same id in the same hierarchy. "
15793                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
15794                    + "other views do not use the same id.");
15795        }
15796        if (state != null && state instanceof BaseSavedState) {
15797            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
15798        }
15799    }
15800
15801    /**
15802     * <p>Return the time at which the drawing of the view hierarchy started.</p>
15803     *
15804     * @return the drawing start time in milliseconds
15805     */
15806    public long getDrawingTime() {
15807        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
15808    }
15809
15810    /**
15811     * <p>Enables or disables the duplication of the parent's state into this view. When
15812     * duplication is enabled, this view gets its drawable state from its parent rather
15813     * than from its own internal properties.</p>
15814     *
15815     * <p>Note: in the current implementation, setting this property to true after the
15816     * view was added to a ViewGroup might have no effect at all. This property should
15817     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
15818     *
15819     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
15820     * property is enabled, an exception will be thrown.</p>
15821     *
15822     * <p>Note: if the child view uses and updates additional states which are unknown to the
15823     * parent, these states should not be affected by this method.</p>
15824     *
15825     * @param enabled True to enable duplication of the parent's drawable state, false
15826     *                to disable it.
15827     *
15828     * @see #getDrawableState()
15829     * @see #isDuplicateParentStateEnabled()
15830     */
15831    public void setDuplicateParentStateEnabled(boolean enabled) {
15832        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
15833    }
15834
15835    /**
15836     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
15837     *
15838     * @return True if this view's drawable state is duplicated from the parent,
15839     *         false otherwise
15840     *
15841     * @see #getDrawableState()
15842     * @see #setDuplicateParentStateEnabled(boolean)
15843     */
15844    public boolean isDuplicateParentStateEnabled() {
15845        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
15846    }
15847
15848    /**
15849     * <p>Specifies the type of layer backing this view. The layer can be
15850     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15851     * {@link #LAYER_TYPE_HARDWARE}.</p>
15852     *
15853     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15854     * instance that controls how the layer is composed on screen. The following
15855     * properties of the paint are taken into account when composing the layer:</p>
15856     * <ul>
15857     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15858     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15859     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15860     * </ul>
15861     *
15862     * <p>If this view has an alpha value set to < 1.0 by calling
15863     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
15864     * by this view's alpha value.</p>
15865     *
15866     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
15867     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
15868     * for more information on when and how to use layers.</p>
15869     *
15870     * @param layerType The type of layer to use with this view, must be one of
15871     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15872     *        {@link #LAYER_TYPE_HARDWARE}
15873     * @param paint The paint used to compose the layer. This argument is optional
15874     *        and can be null. It is ignored when the layer type is
15875     *        {@link #LAYER_TYPE_NONE}
15876     *
15877     * @see #getLayerType()
15878     * @see #LAYER_TYPE_NONE
15879     * @see #LAYER_TYPE_SOFTWARE
15880     * @see #LAYER_TYPE_HARDWARE
15881     * @see #setAlpha(float)
15882     *
15883     * @attr ref android.R.styleable#View_layerType
15884     */
15885    public void setLayerType(int layerType, @Nullable Paint paint) {
15886        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15887            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15888                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15889        }
15890
15891        boolean typeChanged = mRenderNode.setLayerType(layerType);
15892
15893        if (!typeChanged) {
15894            setLayerPaint(paint);
15895            return;
15896        }
15897
15898        if (layerType != LAYER_TYPE_SOFTWARE) {
15899            // Destroy any previous software drawing cache if present
15900            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
15901            // drawing cache created in View#draw when drawing to a SW canvas.
15902            destroyDrawingCache();
15903        }
15904
15905        mLayerType = layerType;
15906        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
15907        mRenderNode.setLayerPaint(mLayerPaint);
15908
15909        // draw() behaves differently if we are on a layer, so we need to
15910        // invalidate() here
15911        invalidateParentCaches();
15912        invalidate(true);
15913    }
15914
15915    /**
15916     * Updates the {@link Paint} object used with the current layer (used only if the current
15917     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15918     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15919     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15920     * ensure that the view gets redrawn immediately.
15921     *
15922     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15923     * instance that controls how the layer is composed on screen. The following
15924     * properties of the paint are taken into account when composing the layer:</p>
15925     * <ul>
15926     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15927     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15928     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15929     * </ul>
15930     *
15931     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15932     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15933     *
15934     * @param paint The paint used to compose the layer. This argument is optional
15935     *        and can be null. It is ignored when the layer type is
15936     *        {@link #LAYER_TYPE_NONE}
15937     *
15938     * @see #setLayerType(int, android.graphics.Paint)
15939     */
15940    public void setLayerPaint(@Nullable Paint paint) {
15941        int layerType = getLayerType();
15942        if (layerType != LAYER_TYPE_NONE) {
15943            mLayerPaint = paint;
15944            if (layerType == LAYER_TYPE_HARDWARE) {
15945                if (mRenderNode.setLayerPaint(paint)) {
15946                    invalidateViewProperty(false, false);
15947                }
15948            } else {
15949                invalidate();
15950            }
15951        }
15952    }
15953
15954    /**
15955     * Indicates what type of layer is currently associated with this view. By default
15956     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15957     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15958     * for more information on the different types of layers.
15959     *
15960     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15961     *         {@link #LAYER_TYPE_HARDWARE}
15962     *
15963     * @see #setLayerType(int, android.graphics.Paint)
15964     * @see #buildLayer()
15965     * @see #LAYER_TYPE_NONE
15966     * @see #LAYER_TYPE_SOFTWARE
15967     * @see #LAYER_TYPE_HARDWARE
15968     */
15969    public int getLayerType() {
15970        return mLayerType;
15971    }
15972
15973    /**
15974     * Forces this view's layer to be created and this view to be rendered
15975     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15976     * invoking this method will have no effect.
15977     *
15978     * This method can for instance be used to render a view into its layer before
15979     * starting an animation. If this view is complex, rendering into the layer
15980     * before starting the animation will avoid skipping frames.
15981     *
15982     * @throws IllegalStateException If this view is not attached to a window
15983     *
15984     * @see #setLayerType(int, android.graphics.Paint)
15985     */
15986    public void buildLayer() {
15987        if (mLayerType == LAYER_TYPE_NONE) return;
15988
15989        final AttachInfo attachInfo = mAttachInfo;
15990        if (attachInfo == null) {
15991            throw new IllegalStateException("This view must be attached to a window first");
15992        }
15993
15994        if (getWidth() == 0 || getHeight() == 0) {
15995            return;
15996        }
15997
15998        switch (mLayerType) {
15999            case LAYER_TYPE_HARDWARE:
16000                updateDisplayListIfDirty();
16001                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
16002                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
16003                }
16004                break;
16005            case LAYER_TYPE_SOFTWARE:
16006                buildDrawingCache(true);
16007                break;
16008        }
16009    }
16010
16011    /**
16012     * Destroys all hardware rendering resources. This method is invoked
16013     * when the system needs to reclaim resources. Upon execution of this
16014     * method, you should free any OpenGL resources created by the view.
16015     *
16016     * Note: you <strong>must</strong> call
16017     * <code>super.destroyHardwareResources()</code> when overriding
16018     * this method.
16019     *
16020     * @hide
16021     */
16022    @CallSuper
16023    protected void destroyHardwareResources() {
16024        // Although the Layer will be destroyed by RenderNode, we want to release
16025        // the staging display list, which is also a signal to RenderNode that it's
16026        // safe to free its copy of the display list as it knows that we will
16027        // push an updated DisplayList if we try to draw again
16028        resetDisplayList();
16029    }
16030
16031    /**
16032     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
16033     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
16034     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
16035     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
16036     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
16037     * null.</p>
16038     *
16039     * <p>Enabling the drawing cache is similar to
16040     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
16041     * acceleration is turned off. When hardware acceleration is turned on, enabling the
16042     * drawing cache has no effect on rendering because the system uses a different mechanism
16043     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
16044     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
16045     * for information on how to enable software and hardware layers.</p>
16046     *
16047     * <p>This API can be used to manually generate
16048     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
16049     * {@link #getDrawingCache()}.</p>
16050     *
16051     * @param enabled true to enable the drawing cache, false otherwise
16052     *
16053     * @see #isDrawingCacheEnabled()
16054     * @see #getDrawingCache()
16055     * @see #buildDrawingCache()
16056     * @see #setLayerType(int, android.graphics.Paint)
16057     */
16058    public void setDrawingCacheEnabled(boolean enabled) {
16059        mCachingFailed = false;
16060        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
16061    }
16062
16063    /**
16064     * <p>Indicates whether the drawing cache is enabled for this view.</p>
16065     *
16066     * @return true if the drawing cache is enabled
16067     *
16068     * @see #setDrawingCacheEnabled(boolean)
16069     * @see #getDrawingCache()
16070     */
16071    @ViewDebug.ExportedProperty(category = "drawing")
16072    public boolean isDrawingCacheEnabled() {
16073        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
16074    }
16075
16076    /**
16077     * Debugging utility which recursively outputs the dirty state of a view and its
16078     * descendants.
16079     *
16080     * @hide
16081     */
16082    @SuppressWarnings({"UnusedDeclaration"})
16083    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
16084        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
16085                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
16086                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
16087                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
16088        if (clear) {
16089            mPrivateFlags &= clearMask;
16090        }
16091        if (this instanceof ViewGroup) {
16092            ViewGroup parent = (ViewGroup) this;
16093            final int count = parent.getChildCount();
16094            for (int i = 0; i < count; i++) {
16095                final View child = parent.getChildAt(i);
16096                child.outputDirtyFlags(indent + "  ", clear, clearMask);
16097            }
16098        }
16099    }
16100
16101    /**
16102     * This method is used by ViewGroup to cause its children to restore or recreate their
16103     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
16104     * to recreate its own display list, which would happen if it went through the normal
16105     * draw/dispatchDraw mechanisms.
16106     *
16107     * @hide
16108     */
16109    protected void dispatchGetDisplayList() {}
16110
16111    /**
16112     * A view that is not attached or hardware accelerated cannot create a display list.
16113     * This method checks these conditions and returns the appropriate result.
16114     *
16115     * @return true if view has the ability to create a display list, false otherwise.
16116     *
16117     * @hide
16118     */
16119    public boolean canHaveDisplayList() {
16120        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
16121    }
16122
16123    /**
16124     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
16125     * @hide
16126     */
16127    @NonNull
16128    public RenderNode updateDisplayListIfDirty() {
16129        final RenderNode renderNode = mRenderNode;
16130        if (!canHaveDisplayList()) {
16131            // can't populate RenderNode, don't try
16132            return renderNode;
16133        }
16134
16135        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
16136                || !renderNode.isValid()
16137                || (mRecreateDisplayList)) {
16138            // Don't need to recreate the display list, just need to tell our
16139            // children to restore/recreate theirs
16140            if (renderNode.isValid()
16141                    && !mRecreateDisplayList) {
16142                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16143                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16144                dispatchGetDisplayList();
16145
16146                return renderNode; // no work needed
16147            }
16148
16149            // If we got here, we're recreating it. Mark it as such to ensure that
16150            // we copy in child display lists into ours in drawChild()
16151            mRecreateDisplayList = true;
16152
16153            int width = mRight - mLeft;
16154            int height = mBottom - mTop;
16155            int layerType = getLayerType();
16156
16157            final DisplayListCanvas canvas = renderNode.start(width, height);
16158            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
16159
16160            try {
16161                if (layerType == LAYER_TYPE_SOFTWARE) {
16162                    buildDrawingCache(true);
16163                    Bitmap cache = getDrawingCache(true);
16164                    if (cache != null) {
16165                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
16166                    }
16167                } else {
16168                    computeScroll();
16169
16170                    canvas.translate(-mScrollX, -mScrollY);
16171                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16172                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16173
16174                    // Fast path for layouts with no backgrounds
16175                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16176                        dispatchDraw(canvas);
16177                        if (mOverlay != null && !mOverlay.isEmpty()) {
16178                            mOverlay.getOverlayView().draw(canvas);
16179                        }
16180                    } else {
16181                        draw(canvas);
16182                    }
16183                }
16184            } finally {
16185                renderNode.end(canvas);
16186                setDisplayListProperties(renderNode);
16187            }
16188        } else {
16189            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16190            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16191        }
16192        return renderNode;
16193    }
16194
16195    private void resetDisplayList() {
16196        if (mRenderNode.isValid()) {
16197            mRenderNode.discardDisplayList();
16198        }
16199
16200        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
16201            mBackgroundRenderNode.discardDisplayList();
16202        }
16203    }
16204
16205    /**
16206     * Called when the passed RenderNode is removed from the draw tree
16207     * @hide
16208     */
16209    public void onRenderNodeDetached(RenderNode renderNode) {
16210    }
16211
16212    /**
16213     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
16214     *
16215     * @return A non-scaled bitmap representing this view or null if cache is disabled.
16216     *
16217     * @see #getDrawingCache(boolean)
16218     */
16219    public Bitmap getDrawingCache() {
16220        return getDrawingCache(false);
16221    }
16222
16223    /**
16224     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
16225     * is null when caching is disabled. If caching is enabled and the cache is not ready,
16226     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
16227     * draw from the cache when the cache is enabled. To benefit from the cache, you must
16228     * request the drawing cache by calling this method and draw it on screen if the
16229     * returned bitmap is not null.</p>
16230     *
16231     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16232     * this method will create a bitmap of the same size as this view. Because this bitmap
16233     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16234     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16235     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16236     * size than the view. This implies that your application must be able to handle this
16237     * size.</p>
16238     *
16239     * @param autoScale Indicates whether the generated bitmap should be scaled based on
16240     *        the current density of the screen when the application is in compatibility
16241     *        mode.
16242     *
16243     * @return A bitmap representing this view or null if cache is disabled.
16244     *
16245     * @see #setDrawingCacheEnabled(boolean)
16246     * @see #isDrawingCacheEnabled()
16247     * @see #buildDrawingCache(boolean)
16248     * @see #destroyDrawingCache()
16249     */
16250    public Bitmap getDrawingCache(boolean autoScale) {
16251        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
16252            return null;
16253        }
16254        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
16255            buildDrawingCache(autoScale);
16256        }
16257        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
16258    }
16259
16260    /**
16261     * <p>Frees the resources used by the drawing cache. If you call
16262     * {@link #buildDrawingCache()} manually without calling
16263     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16264     * should cleanup the cache with this method afterwards.</p>
16265     *
16266     * @see #setDrawingCacheEnabled(boolean)
16267     * @see #buildDrawingCache()
16268     * @see #getDrawingCache()
16269     */
16270    public void destroyDrawingCache() {
16271        if (mDrawingCache != null) {
16272            mDrawingCache.recycle();
16273            mDrawingCache = null;
16274        }
16275        if (mUnscaledDrawingCache != null) {
16276            mUnscaledDrawingCache.recycle();
16277            mUnscaledDrawingCache = null;
16278        }
16279    }
16280
16281    /**
16282     * Setting a solid background color for the drawing cache's bitmaps will improve
16283     * performance and memory usage. Note, though that this should only be used if this
16284     * view will always be drawn on top of a solid color.
16285     *
16286     * @param color The background color to use for the drawing cache's bitmap
16287     *
16288     * @see #setDrawingCacheEnabled(boolean)
16289     * @see #buildDrawingCache()
16290     * @see #getDrawingCache()
16291     */
16292    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
16293        if (color != mDrawingCacheBackgroundColor) {
16294            mDrawingCacheBackgroundColor = color;
16295            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16296        }
16297    }
16298
16299    /**
16300     * @see #setDrawingCacheBackgroundColor(int)
16301     *
16302     * @return The background color to used for the drawing cache's bitmap
16303     */
16304    @ColorInt
16305    public int getDrawingCacheBackgroundColor() {
16306        return mDrawingCacheBackgroundColor;
16307    }
16308
16309    /**
16310     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
16311     *
16312     * @see #buildDrawingCache(boolean)
16313     */
16314    public void buildDrawingCache() {
16315        buildDrawingCache(false);
16316    }
16317
16318    /**
16319     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
16320     *
16321     * <p>If you call {@link #buildDrawingCache()} manually without calling
16322     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16323     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
16324     *
16325     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16326     * this method will create a bitmap of the same size as this view. Because this bitmap
16327     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16328     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16329     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16330     * size than the view. This implies that your application must be able to handle this
16331     * size.</p>
16332     *
16333     * <p>You should avoid calling this method when hardware acceleration is enabled. If
16334     * you do not need the drawing cache bitmap, calling this method will increase memory
16335     * usage and cause the view to be rendered in software once, thus negatively impacting
16336     * performance.</p>
16337     *
16338     * @see #getDrawingCache()
16339     * @see #destroyDrawingCache()
16340     */
16341    public void buildDrawingCache(boolean autoScale) {
16342        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
16343                mDrawingCache == null : mUnscaledDrawingCache == null)) {
16344            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
16345                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
16346                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
16347            }
16348            try {
16349                buildDrawingCacheImpl(autoScale);
16350            } finally {
16351                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
16352            }
16353        }
16354    }
16355
16356    /**
16357     * private, internal implementation of buildDrawingCache, used to enable tracing
16358     */
16359    private void buildDrawingCacheImpl(boolean autoScale) {
16360        mCachingFailed = false;
16361
16362        int width = mRight - mLeft;
16363        int height = mBottom - mTop;
16364
16365        final AttachInfo attachInfo = mAttachInfo;
16366        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
16367
16368        if (autoScale && scalingRequired) {
16369            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
16370            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
16371        }
16372
16373        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
16374        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
16375        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
16376
16377        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
16378        final long drawingCacheSize =
16379                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
16380        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
16381            if (width > 0 && height > 0) {
16382                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
16383                        + " too large to fit into a software layer (or drawing cache), needs "
16384                        + projectedBitmapSize + " bytes, only "
16385                        + drawingCacheSize + " available");
16386            }
16387            destroyDrawingCache();
16388            mCachingFailed = true;
16389            return;
16390        }
16391
16392        boolean clear = true;
16393        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
16394
16395        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
16396            Bitmap.Config quality;
16397            if (!opaque) {
16398                // Never pick ARGB_4444 because it looks awful
16399                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
16400                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
16401                    case DRAWING_CACHE_QUALITY_AUTO:
16402                    case DRAWING_CACHE_QUALITY_LOW:
16403                    case DRAWING_CACHE_QUALITY_HIGH:
16404                    default:
16405                        quality = Bitmap.Config.ARGB_8888;
16406                        break;
16407                }
16408            } else {
16409                // Optimization for translucent windows
16410                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
16411                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
16412            }
16413
16414            // Try to cleanup memory
16415            if (bitmap != null) bitmap.recycle();
16416
16417            try {
16418                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16419                        width, height, quality);
16420                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
16421                if (autoScale) {
16422                    mDrawingCache = bitmap;
16423                } else {
16424                    mUnscaledDrawingCache = bitmap;
16425                }
16426                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
16427            } catch (OutOfMemoryError e) {
16428                // If there is not enough memory to create the bitmap cache, just
16429                // ignore the issue as bitmap caches are not required to draw the
16430                // view hierarchy
16431                if (autoScale) {
16432                    mDrawingCache = null;
16433                } else {
16434                    mUnscaledDrawingCache = null;
16435                }
16436                mCachingFailed = true;
16437                return;
16438            }
16439
16440            clear = drawingCacheBackgroundColor != 0;
16441        }
16442
16443        Canvas canvas;
16444        if (attachInfo != null) {
16445            canvas = attachInfo.mCanvas;
16446            if (canvas == null) {
16447                canvas = new Canvas();
16448            }
16449            canvas.setBitmap(bitmap);
16450            // Temporarily clobber the cached Canvas in case one of our children
16451            // is also using a drawing cache. Without this, the children would
16452            // steal the canvas by attaching their own bitmap to it and bad, bad
16453            // thing would happen (invisible views, corrupted drawings, etc.)
16454            attachInfo.mCanvas = null;
16455        } else {
16456            // This case should hopefully never or seldom happen
16457            canvas = new Canvas(bitmap);
16458        }
16459
16460        if (clear) {
16461            bitmap.eraseColor(drawingCacheBackgroundColor);
16462        }
16463
16464        computeScroll();
16465        final int restoreCount = canvas.save();
16466
16467        if (autoScale && scalingRequired) {
16468            final float scale = attachInfo.mApplicationScale;
16469            canvas.scale(scale, scale);
16470        }
16471
16472        canvas.translate(-mScrollX, -mScrollY);
16473
16474        mPrivateFlags |= PFLAG_DRAWN;
16475        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
16476                mLayerType != LAYER_TYPE_NONE) {
16477            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
16478        }
16479
16480        // Fast path for layouts with no backgrounds
16481        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16482            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16483            dispatchDraw(canvas);
16484            if (mOverlay != null && !mOverlay.isEmpty()) {
16485                mOverlay.getOverlayView().draw(canvas);
16486            }
16487        } else {
16488            draw(canvas);
16489        }
16490
16491        canvas.restoreToCount(restoreCount);
16492        canvas.setBitmap(null);
16493
16494        if (attachInfo != null) {
16495            // Restore the cached Canvas for our siblings
16496            attachInfo.mCanvas = canvas;
16497        }
16498    }
16499
16500    /**
16501     * Create a snapshot of the view into a bitmap.  We should probably make
16502     * some form of this public, but should think about the API.
16503     *
16504     * @hide
16505     */
16506    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
16507        int width = mRight - mLeft;
16508        int height = mBottom - mTop;
16509
16510        final AttachInfo attachInfo = mAttachInfo;
16511        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
16512        width = (int) ((width * scale) + 0.5f);
16513        height = (int) ((height * scale) + 0.5f);
16514
16515        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16516                width > 0 ? width : 1, height > 0 ? height : 1, quality);
16517        if (bitmap == null) {
16518            throw new OutOfMemoryError();
16519        }
16520
16521        Resources resources = getResources();
16522        if (resources != null) {
16523            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
16524        }
16525
16526        Canvas canvas;
16527        if (attachInfo != null) {
16528            canvas = attachInfo.mCanvas;
16529            if (canvas == null) {
16530                canvas = new Canvas();
16531            }
16532            canvas.setBitmap(bitmap);
16533            // Temporarily clobber the cached Canvas in case one of our children
16534            // is also using a drawing cache. Without this, the children would
16535            // steal the canvas by attaching their own bitmap to it and bad, bad
16536            // things would happen (invisible views, corrupted drawings, etc.)
16537            attachInfo.mCanvas = null;
16538        } else {
16539            // This case should hopefully never or seldom happen
16540            canvas = new Canvas(bitmap);
16541        }
16542
16543        if ((backgroundColor & 0xff000000) != 0) {
16544            bitmap.eraseColor(backgroundColor);
16545        }
16546
16547        computeScroll();
16548        final int restoreCount = canvas.save();
16549        canvas.scale(scale, scale);
16550        canvas.translate(-mScrollX, -mScrollY);
16551
16552        // Temporarily remove the dirty mask
16553        int flags = mPrivateFlags;
16554        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16555
16556        // Fast path for layouts with no backgrounds
16557        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16558            dispatchDraw(canvas);
16559            if (mOverlay != null && !mOverlay.isEmpty()) {
16560                mOverlay.getOverlayView().draw(canvas);
16561            }
16562        } else {
16563            draw(canvas);
16564        }
16565
16566        mPrivateFlags = flags;
16567
16568        canvas.restoreToCount(restoreCount);
16569        canvas.setBitmap(null);
16570
16571        if (attachInfo != null) {
16572            // Restore the cached Canvas for our siblings
16573            attachInfo.mCanvas = canvas;
16574        }
16575
16576        return bitmap;
16577    }
16578
16579    /**
16580     * Indicates whether this View is currently in edit mode. A View is usually
16581     * in edit mode when displayed within a developer tool. For instance, if
16582     * this View is being drawn by a visual user interface builder, this method
16583     * should return true.
16584     *
16585     * Subclasses should check the return value of this method to provide
16586     * different behaviors if their normal behavior might interfere with the
16587     * host environment. For instance: the class spawns a thread in its
16588     * constructor, the drawing code relies on device-specific features, etc.
16589     *
16590     * This method is usually checked in the drawing code of custom widgets.
16591     *
16592     * @return True if this View is in edit mode, false otherwise.
16593     */
16594    public boolean isInEditMode() {
16595        return false;
16596    }
16597
16598    /**
16599     * If the View draws content inside its padding and enables fading edges,
16600     * it needs to support padding offsets. Padding offsets are added to the
16601     * fading edges to extend the length of the fade so that it covers pixels
16602     * drawn inside the padding.
16603     *
16604     * Subclasses of this class should override this method if they need
16605     * to draw content inside the padding.
16606     *
16607     * @return True if padding offset must be applied, false otherwise.
16608     *
16609     * @see #getLeftPaddingOffset()
16610     * @see #getRightPaddingOffset()
16611     * @see #getTopPaddingOffset()
16612     * @see #getBottomPaddingOffset()
16613     *
16614     * @since CURRENT
16615     */
16616    protected boolean isPaddingOffsetRequired() {
16617        return false;
16618    }
16619
16620    /**
16621     * Amount by which to extend the left fading region. Called only when
16622     * {@link #isPaddingOffsetRequired()} returns true.
16623     *
16624     * @return The left padding offset in pixels.
16625     *
16626     * @see #isPaddingOffsetRequired()
16627     *
16628     * @since CURRENT
16629     */
16630    protected int getLeftPaddingOffset() {
16631        return 0;
16632    }
16633
16634    /**
16635     * Amount by which to extend the right fading region. Called only when
16636     * {@link #isPaddingOffsetRequired()} returns true.
16637     *
16638     * @return The right padding offset in pixels.
16639     *
16640     * @see #isPaddingOffsetRequired()
16641     *
16642     * @since CURRENT
16643     */
16644    protected int getRightPaddingOffset() {
16645        return 0;
16646    }
16647
16648    /**
16649     * Amount by which to extend the top fading region. Called only when
16650     * {@link #isPaddingOffsetRequired()} returns true.
16651     *
16652     * @return The top padding offset in pixels.
16653     *
16654     * @see #isPaddingOffsetRequired()
16655     *
16656     * @since CURRENT
16657     */
16658    protected int getTopPaddingOffset() {
16659        return 0;
16660    }
16661
16662    /**
16663     * Amount by which to extend the bottom fading region. Called only when
16664     * {@link #isPaddingOffsetRequired()} returns true.
16665     *
16666     * @return The bottom padding offset in pixels.
16667     *
16668     * @see #isPaddingOffsetRequired()
16669     *
16670     * @since CURRENT
16671     */
16672    protected int getBottomPaddingOffset() {
16673        return 0;
16674    }
16675
16676    /**
16677     * @hide
16678     * @param offsetRequired
16679     */
16680    protected int getFadeTop(boolean offsetRequired) {
16681        int top = mPaddingTop;
16682        if (offsetRequired) top += getTopPaddingOffset();
16683        return top;
16684    }
16685
16686    /**
16687     * @hide
16688     * @param offsetRequired
16689     */
16690    protected int getFadeHeight(boolean offsetRequired) {
16691        int padding = mPaddingTop;
16692        if (offsetRequired) padding += getTopPaddingOffset();
16693        return mBottom - mTop - mPaddingBottom - padding;
16694    }
16695
16696    /**
16697     * <p>Indicates whether this view is attached to a hardware accelerated
16698     * window or not.</p>
16699     *
16700     * <p>Even if this method returns true, it does not mean that every call
16701     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
16702     * accelerated {@link android.graphics.Canvas}. For instance, if this view
16703     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
16704     * window is hardware accelerated,
16705     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
16706     * return false, and this method will return true.</p>
16707     *
16708     * @return True if the view is attached to a window and the window is
16709     *         hardware accelerated; false in any other case.
16710     */
16711    @ViewDebug.ExportedProperty(category = "drawing")
16712    public boolean isHardwareAccelerated() {
16713        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
16714    }
16715
16716    /**
16717     * Sets a rectangular area on this view to which the view will be clipped
16718     * when it is drawn. Setting the value to null will remove the clip bounds
16719     * and the view will draw normally, using its full bounds.
16720     *
16721     * @param clipBounds The rectangular area, in the local coordinates of
16722     * this view, to which future drawing operations will be clipped.
16723     */
16724    public void setClipBounds(Rect clipBounds) {
16725        if (clipBounds == mClipBounds
16726                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
16727            return;
16728        }
16729        if (clipBounds != null) {
16730            if (mClipBounds == null) {
16731                mClipBounds = new Rect(clipBounds);
16732            } else {
16733                mClipBounds.set(clipBounds);
16734            }
16735        } else {
16736            mClipBounds = null;
16737        }
16738        mRenderNode.setClipBounds(mClipBounds);
16739        invalidateViewProperty(false, false);
16740    }
16741
16742    /**
16743     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
16744     *
16745     * @return A copy of the current clip bounds if clip bounds are set,
16746     * otherwise null.
16747     */
16748    public Rect getClipBounds() {
16749        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
16750    }
16751
16752
16753    /**
16754     * Populates an output rectangle with the clip bounds of the view,
16755     * returning {@code true} if successful or {@code false} if the view's
16756     * clip bounds are {@code null}.
16757     *
16758     * @param outRect rectangle in which to place the clip bounds of the view
16759     * @return {@code true} if successful or {@code false} if the view's
16760     *         clip bounds are {@code null}
16761     */
16762    public boolean getClipBounds(Rect outRect) {
16763        if (mClipBounds != null) {
16764            outRect.set(mClipBounds);
16765            return true;
16766        }
16767        return false;
16768    }
16769
16770    /**
16771     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
16772     * case of an active Animation being run on the view.
16773     */
16774    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
16775            Animation a, boolean scalingRequired) {
16776        Transformation invalidationTransform;
16777        final int flags = parent.mGroupFlags;
16778        final boolean initialized = a.isInitialized();
16779        if (!initialized) {
16780            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
16781            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
16782            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
16783            onAnimationStart();
16784        }
16785
16786        final Transformation t = parent.getChildTransformation();
16787        boolean more = a.getTransformation(drawingTime, t, 1f);
16788        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
16789            if (parent.mInvalidationTransformation == null) {
16790                parent.mInvalidationTransformation = new Transformation();
16791            }
16792            invalidationTransform = parent.mInvalidationTransformation;
16793            a.getTransformation(drawingTime, invalidationTransform, 1f);
16794        } else {
16795            invalidationTransform = t;
16796        }
16797
16798        if (more) {
16799            if (!a.willChangeBounds()) {
16800                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
16801                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
16802                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
16803                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
16804                    // The child need to draw an animation, potentially offscreen, so
16805                    // make sure we do not cancel invalidate requests
16806                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16807                    parent.invalidate(mLeft, mTop, mRight, mBottom);
16808                }
16809            } else {
16810                if (parent.mInvalidateRegion == null) {
16811                    parent.mInvalidateRegion = new RectF();
16812                }
16813                final RectF region = parent.mInvalidateRegion;
16814                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
16815                        invalidationTransform);
16816
16817                // The child need to draw an animation, potentially offscreen, so
16818                // make sure we do not cancel invalidate requests
16819                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16820
16821                final int left = mLeft + (int) region.left;
16822                final int top = mTop + (int) region.top;
16823                parent.invalidate(left, top, left + (int) (region.width() + .5f),
16824                        top + (int) (region.height() + .5f));
16825            }
16826        }
16827        return more;
16828    }
16829
16830    /**
16831     * This method is called by getDisplayList() when a display list is recorded for a View.
16832     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
16833     */
16834    void setDisplayListProperties(RenderNode renderNode) {
16835        if (renderNode != null) {
16836            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
16837            renderNode.setClipToBounds(mParent instanceof ViewGroup
16838                    && ((ViewGroup) mParent).getClipChildren());
16839
16840            float alpha = 1;
16841            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
16842                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16843                ViewGroup parentVG = (ViewGroup) mParent;
16844                final Transformation t = parentVG.getChildTransformation();
16845                if (parentVG.getChildStaticTransformation(this, t)) {
16846                    final int transformType = t.getTransformationType();
16847                    if (transformType != Transformation.TYPE_IDENTITY) {
16848                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
16849                            alpha = t.getAlpha();
16850                        }
16851                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
16852                            renderNode.setStaticMatrix(t.getMatrix());
16853                        }
16854                    }
16855                }
16856            }
16857            if (mTransformationInfo != null) {
16858                alpha *= getFinalAlpha();
16859                if (alpha < 1) {
16860                    final int multipliedAlpha = (int) (255 * alpha);
16861                    if (onSetAlpha(multipliedAlpha)) {
16862                        alpha = 1;
16863                    }
16864                }
16865                renderNode.setAlpha(alpha);
16866            } else if (alpha < 1) {
16867                renderNode.setAlpha(alpha);
16868            }
16869        }
16870    }
16871
16872    /**
16873     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
16874     *
16875     * This is where the View specializes rendering behavior based on layer type,
16876     * and hardware acceleration.
16877     */
16878    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
16879        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
16880        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
16881         *
16882         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
16883         * HW accelerated, it can't handle drawing RenderNodes.
16884         */
16885        boolean drawingWithRenderNode = mAttachInfo != null
16886                && mAttachInfo.mHardwareAccelerated
16887                && hardwareAcceleratedCanvas;
16888
16889        boolean more = false;
16890        final boolean childHasIdentityMatrix = hasIdentityMatrix();
16891        final int parentFlags = parent.mGroupFlags;
16892
16893        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16894            parent.getChildTransformation().clear();
16895            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16896        }
16897
16898        Transformation transformToApply = null;
16899        boolean concatMatrix = false;
16900        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16901        final Animation a = getAnimation();
16902        if (a != null) {
16903            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16904            concatMatrix = a.willChangeTransformationMatrix();
16905            if (concatMatrix) {
16906                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16907            }
16908            transformToApply = parent.getChildTransformation();
16909        } else {
16910            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16911                // No longer animating: clear out old animation matrix
16912                mRenderNode.setAnimationMatrix(null);
16913                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16914            }
16915            if (!drawingWithRenderNode
16916                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16917                final Transformation t = parent.getChildTransformation();
16918                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16919                if (hasTransform) {
16920                    final int transformType = t.getTransformationType();
16921                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16922                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16923                }
16924            }
16925        }
16926
16927        concatMatrix |= !childHasIdentityMatrix;
16928
16929        // Sets the flag as early as possible to allow draw() implementations
16930        // to call invalidate() successfully when doing animations
16931        mPrivateFlags |= PFLAG_DRAWN;
16932
16933        if (!concatMatrix &&
16934                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16935                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16936                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16937                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16938            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16939            return more;
16940        }
16941        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16942
16943        if (hardwareAcceleratedCanvas) {
16944            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16945            // retain the flag's value temporarily in the mRecreateDisplayList flag
16946            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16947            mPrivateFlags &= ~PFLAG_INVALIDATED;
16948        }
16949
16950        RenderNode renderNode = null;
16951        Bitmap cache = null;
16952        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16953        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
16954             if (layerType != LAYER_TYPE_NONE) {
16955                 // If not drawing with RenderNode, treat HW layers as SW
16956                 layerType = LAYER_TYPE_SOFTWARE;
16957                 buildDrawingCache(true);
16958            }
16959            cache = getDrawingCache(true);
16960        }
16961
16962        if (drawingWithRenderNode) {
16963            // Delay getting the display list until animation-driven alpha values are
16964            // set up and possibly passed on to the view
16965            renderNode = updateDisplayListIfDirty();
16966            if (!renderNode.isValid()) {
16967                // Uncommon, but possible. If a view is removed from the hierarchy during the call
16968                // to getDisplayList(), the display list will be marked invalid and we should not
16969                // try to use it again.
16970                renderNode = null;
16971                drawingWithRenderNode = false;
16972            }
16973        }
16974
16975        int sx = 0;
16976        int sy = 0;
16977        if (!drawingWithRenderNode) {
16978            computeScroll();
16979            sx = mScrollX;
16980            sy = mScrollY;
16981        }
16982
16983        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16984        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16985
16986        int restoreTo = -1;
16987        if (!drawingWithRenderNode || transformToApply != null) {
16988            restoreTo = canvas.save();
16989        }
16990        if (offsetForScroll) {
16991            canvas.translate(mLeft - sx, mTop - sy);
16992        } else {
16993            if (!drawingWithRenderNode) {
16994                canvas.translate(mLeft, mTop);
16995            }
16996            if (scalingRequired) {
16997                if (drawingWithRenderNode) {
16998                    // TODO: Might not need this if we put everything inside the DL
16999                    restoreTo = canvas.save();
17000                }
17001                // mAttachInfo cannot be null, otherwise scalingRequired == false
17002                final float scale = 1.0f / mAttachInfo.mApplicationScale;
17003                canvas.scale(scale, scale);
17004            }
17005        }
17006
17007        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
17008        if (transformToApply != null
17009                || alpha < 1
17010                || !hasIdentityMatrix()
17011                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17012            if (transformToApply != null || !childHasIdentityMatrix) {
17013                int transX = 0;
17014                int transY = 0;
17015
17016                if (offsetForScroll) {
17017                    transX = -sx;
17018                    transY = -sy;
17019                }
17020
17021                if (transformToApply != null) {
17022                    if (concatMatrix) {
17023                        if (drawingWithRenderNode) {
17024                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
17025                        } else {
17026                            // Undo the scroll translation, apply the transformation matrix,
17027                            // then redo the scroll translate to get the correct result.
17028                            canvas.translate(-transX, -transY);
17029                            canvas.concat(transformToApply.getMatrix());
17030                            canvas.translate(transX, transY);
17031                        }
17032                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17033                    }
17034
17035                    float transformAlpha = transformToApply.getAlpha();
17036                    if (transformAlpha < 1) {
17037                        alpha *= transformAlpha;
17038                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17039                    }
17040                }
17041
17042                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
17043                    canvas.translate(-transX, -transY);
17044                    canvas.concat(getMatrix());
17045                    canvas.translate(transX, transY);
17046                }
17047            }
17048
17049            // Deal with alpha if it is or used to be <1
17050            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17051                if (alpha < 1) {
17052                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17053                } else {
17054                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17055                }
17056                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17057                if (!drawingWithDrawingCache) {
17058                    final int multipliedAlpha = (int) (255 * alpha);
17059                    if (!onSetAlpha(multipliedAlpha)) {
17060                        if (drawingWithRenderNode) {
17061                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
17062                        } else if (layerType == LAYER_TYPE_NONE) {
17063                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
17064                                    multipliedAlpha);
17065                        }
17066                    } else {
17067                        // Alpha is handled by the child directly, clobber the layer's alpha
17068                        mPrivateFlags |= PFLAG_ALPHA_SET;
17069                    }
17070                }
17071            }
17072        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17073            onSetAlpha(255);
17074            mPrivateFlags &= ~PFLAG_ALPHA_SET;
17075        }
17076
17077        if (!drawingWithRenderNode) {
17078            // apply clips directly, since RenderNode won't do it for this draw
17079            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
17080                if (offsetForScroll) {
17081                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
17082                } else {
17083                    if (!scalingRequired || cache == null) {
17084                        canvas.clipRect(0, 0, getWidth(), getHeight());
17085                    } else {
17086                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
17087                    }
17088                }
17089            }
17090
17091            if (mClipBounds != null) {
17092                // clip bounds ignore scroll
17093                canvas.clipRect(mClipBounds);
17094            }
17095        }
17096
17097        if (!drawingWithDrawingCache) {
17098            if (drawingWithRenderNode) {
17099                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17100                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17101            } else {
17102                // Fast path for layouts with no backgrounds
17103                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17104                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17105                    dispatchDraw(canvas);
17106                } else {
17107                    draw(canvas);
17108                }
17109            }
17110        } else if (cache != null) {
17111            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17112            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
17113                // no layer paint, use temporary paint to draw bitmap
17114                Paint cachePaint = parent.mCachePaint;
17115                if (cachePaint == null) {
17116                    cachePaint = new Paint();
17117                    cachePaint.setDither(false);
17118                    parent.mCachePaint = cachePaint;
17119                }
17120                cachePaint.setAlpha((int) (alpha * 255));
17121                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
17122            } else {
17123                // use layer paint to draw the bitmap, merging the two alphas, but also restore
17124                int layerPaintAlpha = mLayerPaint.getAlpha();
17125                if (alpha < 1) {
17126                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
17127                }
17128                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
17129                if (alpha < 1) {
17130                    mLayerPaint.setAlpha(layerPaintAlpha);
17131                }
17132            }
17133        }
17134
17135        if (restoreTo >= 0) {
17136            canvas.restoreToCount(restoreTo);
17137        }
17138
17139        if (a != null && !more) {
17140            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
17141                onSetAlpha(255);
17142            }
17143            parent.finishAnimatingView(this, a);
17144        }
17145
17146        if (more && hardwareAcceleratedCanvas) {
17147            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17148                // alpha animations should cause the child to recreate its display list
17149                invalidate(true);
17150            }
17151        }
17152
17153        mRecreateDisplayList = false;
17154
17155        return more;
17156    }
17157
17158    /**
17159     * Manually render this view (and all of its children) to the given Canvas.
17160     * The view must have already done a full layout before this function is
17161     * called.  When implementing a view, implement
17162     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
17163     * If you do need to override this method, call the superclass version.
17164     *
17165     * @param canvas The Canvas to which the View is rendered.
17166     */
17167    @CallSuper
17168    public void draw(Canvas canvas) {
17169        final int privateFlags = mPrivateFlags;
17170        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
17171                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
17172        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
17173
17174        /*
17175         * Draw traversal performs several drawing steps which must be executed
17176         * in the appropriate order:
17177         *
17178         *      1. Draw the background
17179         *      2. If necessary, save the canvas' layers to prepare for fading
17180         *      3. Draw view's content
17181         *      4. Draw children
17182         *      5. If necessary, draw the fading edges and restore layers
17183         *      6. Draw decorations (scrollbars for instance)
17184         */
17185
17186        // Step 1, draw the background, if needed
17187        int saveCount;
17188
17189        if (!dirtyOpaque) {
17190            drawBackground(canvas);
17191        }
17192
17193        // skip step 2 & 5 if possible (common case)
17194        final int viewFlags = mViewFlags;
17195        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
17196        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
17197        if (!verticalEdges && !horizontalEdges) {
17198            // Step 3, draw the content
17199            if (!dirtyOpaque) onDraw(canvas);
17200
17201            // Step 4, draw the children
17202            dispatchDraw(canvas);
17203
17204            // Overlay is part of the content and draws beneath Foreground
17205            if (mOverlay != null && !mOverlay.isEmpty()) {
17206                mOverlay.getOverlayView().dispatchDraw(canvas);
17207            }
17208
17209            // Step 6, draw decorations (foreground, scrollbars)
17210            onDrawForeground(canvas);
17211
17212            // we're done...
17213            return;
17214        }
17215
17216        /*
17217         * Here we do the full fledged routine...
17218         * (this is an uncommon case where speed matters less,
17219         * this is why we repeat some of the tests that have been
17220         * done above)
17221         */
17222
17223        boolean drawTop = false;
17224        boolean drawBottom = false;
17225        boolean drawLeft = false;
17226        boolean drawRight = false;
17227
17228        float topFadeStrength = 0.0f;
17229        float bottomFadeStrength = 0.0f;
17230        float leftFadeStrength = 0.0f;
17231        float rightFadeStrength = 0.0f;
17232
17233        // Step 2, save the canvas' layers
17234        int paddingLeft = mPaddingLeft;
17235
17236        final boolean offsetRequired = isPaddingOffsetRequired();
17237        if (offsetRequired) {
17238            paddingLeft += getLeftPaddingOffset();
17239        }
17240
17241        int left = mScrollX + paddingLeft;
17242        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
17243        int top = mScrollY + getFadeTop(offsetRequired);
17244        int bottom = top + getFadeHeight(offsetRequired);
17245
17246        if (offsetRequired) {
17247            right += getRightPaddingOffset();
17248            bottom += getBottomPaddingOffset();
17249        }
17250
17251        final ScrollabilityCache scrollabilityCache = mScrollCache;
17252        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
17253        int length = (int) fadeHeight;
17254
17255        // clip the fade length if top and bottom fades overlap
17256        // overlapping fades produce odd-looking artifacts
17257        if (verticalEdges && (top + length > bottom - length)) {
17258            length = (bottom - top) / 2;
17259        }
17260
17261        // also clip horizontal fades if necessary
17262        if (horizontalEdges && (left + length > right - length)) {
17263            length = (right - left) / 2;
17264        }
17265
17266        if (verticalEdges) {
17267            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
17268            drawTop = topFadeStrength * fadeHeight > 1.0f;
17269            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
17270            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
17271        }
17272
17273        if (horizontalEdges) {
17274            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
17275            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
17276            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
17277            drawRight = rightFadeStrength * fadeHeight > 1.0f;
17278        }
17279
17280        saveCount = canvas.getSaveCount();
17281
17282        int solidColor = getSolidColor();
17283        if (solidColor == 0) {
17284            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
17285
17286            if (drawTop) {
17287                canvas.saveLayer(left, top, right, top + length, null, flags);
17288            }
17289
17290            if (drawBottom) {
17291                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
17292            }
17293
17294            if (drawLeft) {
17295                canvas.saveLayer(left, top, left + length, bottom, null, flags);
17296            }
17297
17298            if (drawRight) {
17299                canvas.saveLayer(right - length, top, right, bottom, null, flags);
17300            }
17301        } else {
17302            scrollabilityCache.setFadeColor(solidColor);
17303        }
17304
17305        // Step 3, draw the content
17306        if (!dirtyOpaque) onDraw(canvas);
17307
17308        // Step 4, draw the children
17309        dispatchDraw(canvas);
17310
17311        // Step 5, draw the fade effect and restore layers
17312        final Paint p = scrollabilityCache.paint;
17313        final Matrix matrix = scrollabilityCache.matrix;
17314        final Shader fade = scrollabilityCache.shader;
17315
17316        if (drawTop) {
17317            matrix.setScale(1, fadeHeight * topFadeStrength);
17318            matrix.postTranslate(left, top);
17319            fade.setLocalMatrix(matrix);
17320            p.setShader(fade);
17321            canvas.drawRect(left, top, right, top + length, p);
17322        }
17323
17324        if (drawBottom) {
17325            matrix.setScale(1, fadeHeight * bottomFadeStrength);
17326            matrix.postRotate(180);
17327            matrix.postTranslate(left, bottom);
17328            fade.setLocalMatrix(matrix);
17329            p.setShader(fade);
17330            canvas.drawRect(left, bottom - length, right, bottom, p);
17331        }
17332
17333        if (drawLeft) {
17334            matrix.setScale(1, fadeHeight * leftFadeStrength);
17335            matrix.postRotate(-90);
17336            matrix.postTranslate(left, top);
17337            fade.setLocalMatrix(matrix);
17338            p.setShader(fade);
17339            canvas.drawRect(left, top, left + length, bottom, p);
17340        }
17341
17342        if (drawRight) {
17343            matrix.setScale(1, fadeHeight * rightFadeStrength);
17344            matrix.postRotate(90);
17345            matrix.postTranslate(right, top);
17346            fade.setLocalMatrix(matrix);
17347            p.setShader(fade);
17348            canvas.drawRect(right - length, top, right, bottom, p);
17349        }
17350
17351        canvas.restoreToCount(saveCount);
17352
17353        // Overlay is part of the content and draws beneath Foreground
17354        if (mOverlay != null && !mOverlay.isEmpty()) {
17355            mOverlay.getOverlayView().dispatchDraw(canvas);
17356        }
17357
17358        // Step 6, draw decorations (foreground, scrollbars)
17359        onDrawForeground(canvas);
17360    }
17361
17362    /**
17363     * Draws the background onto the specified canvas.
17364     *
17365     * @param canvas Canvas on which to draw the background
17366     */
17367    private void drawBackground(Canvas canvas) {
17368        final Drawable background = mBackground;
17369        if (background == null) {
17370            return;
17371        }
17372
17373        setBackgroundBounds();
17374
17375        // Attempt to use a display list if requested.
17376        if (canvas.isHardwareAccelerated() && mAttachInfo != null
17377                && mAttachInfo.mHardwareRenderer != null) {
17378            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
17379
17380            final RenderNode renderNode = mBackgroundRenderNode;
17381            if (renderNode != null && renderNode.isValid()) {
17382                setBackgroundRenderNodeProperties(renderNode);
17383                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17384                return;
17385            }
17386        }
17387
17388        final int scrollX = mScrollX;
17389        final int scrollY = mScrollY;
17390        if ((scrollX | scrollY) == 0) {
17391            background.draw(canvas);
17392        } else {
17393            canvas.translate(scrollX, scrollY);
17394            background.draw(canvas);
17395            canvas.translate(-scrollX, -scrollY);
17396        }
17397    }
17398
17399    /**
17400     * Sets the correct background bounds and rebuilds the outline, if needed.
17401     * <p/>
17402     * This is called by LayoutLib.
17403     */
17404    void setBackgroundBounds() {
17405        if (mBackgroundSizeChanged && mBackground != null) {
17406            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
17407            mBackgroundSizeChanged = false;
17408            rebuildOutline();
17409        }
17410    }
17411
17412    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
17413        renderNode.setTranslationX(mScrollX);
17414        renderNode.setTranslationY(mScrollY);
17415    }
17416
17417    /**
17418     * Creates a new display list or updates the existing display list for the
17419     * specified Drawable.
17420     *
17421     * @param drawable Drawable for which to create a display list
17422     * @param renderNode Existing RenderNode, or {@code null}
17423     * @return A valid display list for the specified drawable
17424     */
17425    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
17426        if (renderNode == null) {
17427            renderNode = RenderNode.create(drawable.getClass().getName(), this);
17428        }
17429
17430        final Rect bounds = drawable.getBounds();
17431        final int width = bounds.width();
17432        final int height = bounds.height();
17433        final DisplayListCanvas canvas = renderNode.start(width, height);
17434
17435        // Reverse left/top translation done by drawable canvas, which will
17436        // instead be applied by rendernode's LTRB bounds below. This way, the
17437        // drawable's bounds match with its rendernode bounds and its content
17438        // will lie within those bounds in the rendernode tree.
17439        canvas.translate(-bounds.left, -bounds.top);
17440
17441        try {
17442            drawable.draw(canvas);
17443        } finally {
17444            renderNode.end(canvas);
17445        }
17446
17447        // Set up drawable properties that are view-independent.
17448        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
17449        renderNode.setProjectBackwards(drawable.isProjected());
17450        renderNode.setProjectionReceiver(true);
17451        renderNode.setClipToBounds(false);
17452        return renderNode;
17453    }
17454
17455    /**
17456     * Returns the overlay for this view, creating it if it does not yet exist.
17457     * Adding drawables to the overlay will cause them to be displayed whenever
17458     * the view itself is redrawn. Objects in the overlay should be actively
17459     * managed: remove them when they should not be displayed anymore. The
17460     * overlay will always have the same size as its host view.
17461     *
17462     * <p>Note: Overlays do not currently work correctly with {@link
17463     * SurfaceView} or {@link TextureView}; contents in overlays for these
17464     * types of views may not display correctly.</p>
17465     *
17466     * @return The ViewOverlay object for this view.
17467     * @see ViewOverlay
17468     */
17469    public ViewOverlay getOverlay() {
17470        if (mOverlay == null) {
17471            mOverlay = new ViewOverlay(mContext, this);
17472        }
17473        return mOverlay;
17474    }
17475
17476    /**
17477     * Override this if your view is known to always be drawn on top of a solid color background,
17478     * and needs to draw fading edges. Returning a non-zero color enables the view system to
17479     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
17480     * should be set to 0xFF.
17481     *
17482     * @see #setVerticalFadingEdgeEnabled(boolean)
17483     * @see #setHorizontalFadingEdgeEnabled(boolean)
17484     *
17485     * @return The known solid color background for this view, or 0 if the color may vary
17486     */
17487    @ViewDebug.ExportedProperty(category = "drawing")
17488    @ColorInt
17489    public int getSolidColor() {
17490        return 0;
17491    }
17492
17493    /**
17494     * Build a human readable string representation of the specified view flags.
17495     *
17496     * @param flags the view flags to convert to a string
17497     * @return a String representing the supplied flags
17498     */
17499    private static String printFlags(int flags) {
17500        String output = "";
17501        int numFlags = 0;
17502        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
17503            output += "TAKES_FOCUS";
17504            numFlags++;
17505        }
17506
17507        switch (flags & VISIBILITY_MASK) {
17508        case INVISIBLE:
17509            if (numFlags > 0) {
17510                output += " ";
17511            }
17512            output += "INVISIBLE";
17513            // USELESS HERE numFlags++;
17514            break;
17515        case GONE:
17516            if (numFlags > 0) {
17517                output += " ";
17518            }
17519            output += "GONE";
17520            // USELESS HERE numFlags++;
17521            break;
17522        default:
17523            break;
17524        }
17525        return output;
17526    }
17527
17528    /**
17529     * Build a human readable string representation of the specified private
17530     * view flags.
17531     *
17532     * @param privateFlags the private view flags to convert to a string
17533     * @return a String representing the supplied flags
17534     */
17535    private static String printPrivateFlags(int privateFlags) {
17536        String output = "";
17537        int numFlags = 0;
17538
17539        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
17540            output += "WANTS_FOCUS";
17541            numFlags++;
17542        }
17543
17544        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
17545            if (numFlags > 0) {
17546                output += " ";
17547            }
17548            output += "FOCUSED";
17549            numFlags++;
17550        }
17551
17552        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
17553            if (numFlags > 0) {
17554                output += " ";
17555            }
17556            output += "SELECTED";
17557            numFlags++;
17558        }
17559
17560        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
17561            if (numFlags > 0) {
17562                output += " ";
17563            }
17564            output += "IS_ROOT_NAMESPACE";
17565            numFlags++;
17566        }
17567
17568        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
17569            if (numFlags > 0) {
17570                output += " ";
17571            }
17572            output += "HAS_BOUNDS";
17573            numFlags++;
17574        }
17575
17576        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
17577            if (numFlags > 0) {
17578                output += " ";
17579            }
17580            output += "DRAWN";
17581            // USELESS HERE numFlags++;
17582        }
17583        return output;
17584    }
17585
17586    /**
17587     * <p>Indicates whether or not this view's layout will be requested during
17588     * the next hierarchy layout pass.</p>
17589     *
17590     * @return true if the layout will be forced during next layout pass
17591     */
17592    public boolean isLayoutRequested() {
17593        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
17594    }
17595
17596    /**
17597     * Return true if o is a ViewGroup that is laying out using optical bounds.
17598     * @hide
17599     */
17600    public static boolean isLayoutModeOptical(Object o) {
17601        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
17602    }
17603
17604    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
17605        Insets parentInsets = mParent instanceof View ?
17606                ((View) mParent).getOpticalInsets() : Insets.NONE;
17607        Insets childInsets = getOpticalInsets();
17608        return setFrame(
17609                left   + parentInsets.left - childInsets.left,
17610                top    + parentInsets.top  - childInsets.top,
17611                right  + parentInsets.left + childInsets.right,
17612                bottom + parentInsets.top  + childInsets.bottom);
17613    }
17614
17615    /**
17616     * Assign a size and position to a view and all of its
17617     * descendants
17618     *
17619     * <p>This is the second phase of the layout mechanism.
17620     * (The first is measuring). In this phase, each parent calls
17621     * layout on all of its children to position them.
17622     * This is typically done using the child measurements
17623     * that were stored in the measure pass().</p>
17624     *
17625     * <p>Derived classes should not override this method.
17626     * Derived classes with children should override
17627     * onLayout. In that method, they should
17628     * call layout on each of their children.</p>
17629     *
17630     * @param l Left position, relative to parent
17631     * @param t Top position, relative to parent
17632     * @param r Right position, relative to parent
17633     * @param b Bottom position, relative to parent
17634     */
17635    @SuppressWarnings({"unchecked"})
17636    public void layout(int l, int t, int r, int b) {
17637        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
17638            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
17639            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17640        }
17641
17642        int oldL = mLeft;
17643        int oldT = mTop;
17644        int oldB = mBottom;
17645        int oldR = mRight;
17646
17647        boolean changed = isLayoutModeOptical(mParent) ?
17648                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
17649
17650        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
17651            onLayout(changed, l, t, r, b);
17652
17653            if (shouldDrawRoundScrollbar()) {
17654                if(mRoundScrollbarRenderer == null) {
17655                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
17656                }
17657            } else {
17658                mRoundScrollbarRenderer = null;
17659            }
17660
17661            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
17662
17663            ListenerInfo li = mListenerInfo;
17664            if (li != null && li.mOnLayoutChangeListeners != null) {
17665                ArrayList<OnLayoutChangeListener> listenersCopy =
17666                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
17667                int numListeners = listenersCopy.size();
17668                for (int i = 0; i < numListeners; ++i) {
17669                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
17670                }
17671            }
17672        }
17673
17674        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
17675        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
17676    }
17677
17678    /**
17679     * Called from layout when this view should
17680     * assign a size and position to each of its children.
17681     *
17682     * Derived classes with children should override
17683     * this method and call layout on each of
17684     * their children.
17685     * @param changed This is a new size or position for this view
17686     * @param left Left position, relative to parent
17687     * @param top Top position, relative to parent
17688     * @param right Right position, relative to parent
17689     * @param bottom Bottom position, relative to parent
17690     */
17691    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
17692    }
17693
17694    /**
17695     * Assign a size and position to this view.
17696     *
17697     * This is called from layout.
17698     *
17699     * @param left Left position, relative to parent
17700     * @param top Top position, relative to parent
17701     * @param right Right position, relative to parent
17702     * @param bottom Bottom position, relative to parent
17703     * @return true if the new size and position are different than the
17704     *         previous ones
17705     * {@hide}
17706     */
17707    protected boolean setFrame(int left, int top, int right, int bottom) {
17708        boolean changed = false;
17709
17710        if (DBG) {
17711            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
17712                    + right + "," + bottom + ")");
17713        }
17714
17715        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
17716            changed = true;
17717
17718            // Remember our drawn bit
17719            int drawn = mPrivateFlags & PFLAG_DRAWN;
17720
17721            int oldWidth = mRight - mLeft;
17722            int oldHeight = mBottom - mTop;
17723            int newWidth = right - left;
17724            int newHeight = bottom - top;
17725            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
17726
17727            // Invalidate our old position
17728            invalidate(sizeChanged);
17729
17730            mLeft = left;
17731            mTop = top;
17732            mRight = right;
17733            mBottom = bottom;
17734            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
17735
17736            mPrivateFlags |= PFLAG_HAS_BOUNDS;
17737
17738
17739            if (sizeChanged) {
17740                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
17741            }
17742
17743            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
17744                // If we are visible, force the DRAWN bit to on so that
17745                // this invalidate will go through (at least to our parent).
17746                // This is because someone may have invalidated this view
17747                // before this call to setFrame came in, thereby clearing
17748                // the DRAWN bit.
17749                mPrivateFlags |= PFLAG_DRAWN;
17750                invalidate(sizeChanged);
17751                // parent display list may need to be recreated based on a change in the bounds
17752                // of any child
17753                invalidateParentCaches();
17754            }
17755
17756            // Reset drawn bit to original value (invalidate turns it off)
17757            mPrivateFlags |= drawn;
17758
17759            mBackgroundSizeChanged = true;
17760            if (mForegroundInfo != null) {
17761                mForegroundInfo.mBoundsChanged = true;
17762            }
17763
17764            notifySubtreeAccessibilityStateChangedIfNeeded();
17765        }
17766        return changed;
17767    }
17768
17769    /**
17770     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
17771     * @hide
17772     */
17773    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
17774        setFrame(left, top, right, bottom);
17775    }
17776
17777    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
17778        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
17779        if (mOverlay != null) {
17780            mOverlay.getOverlayView().setRight(newWidth);
17781            mOverlay.getOverlayView().setBottom(newHeight);
17782        }
17783        rebuildOutline();
17784    }
17785
17786    /**
17787     * Finalize inflating a view from XML.  This is called as the last phase
17788     * of inflation, after all child views have been added.
17789     *
17790     * <p>Even if the subclass overrides onFinishInflate, they should always be
17791     * sure to call the super method, so that we get called.
17792     */
17793    @CallSuper
17794    protected void onFinishInflate() {
17795    }
17796
17797    /**
17798     * Returns the resources associated with this view.
17799     *
17800     * @return Resources object.
17801     */
17802    public Resources getResources() {
17803        return mResources;
17804    }
17805
17806    /**
17807     * Invalidates the specified Drawable.
17808     *
17809     * @param drawable the drawable to invalidate
17810     */
17811    @Override
17812    public void invalidateDrawable(@NonNull Drawable drawable) {
17813        if (verifyDrawable(drawable)) {
17814            final Rect dirty = drawable.getDirtyBounds();
17815            final int scrollX = mScrollX;
17816            final int scrollY = mScrollY;
17817
17818            invalidate(dirty.left + scrollX, dirty.top + scrollY,
17819                    dirty.right + scrollX, dirty.bottom + scrollY);
17820            rebuildOutline();
17821        }
17822    }
17823
17824    /**
17825     * Schedules an action on a drawable to occur at a specified time.
17826     *
17827     * @param who the recipient of the action
17828     * @param what the action to run on the drawable
17829     * @param when the time at which the action must occur. Uses the
17830     *        {@link SystemClock#uptimeMillis} timebase.
17831     */
17832    @Override
17833    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
17834        if (verifyDrawable(who) && what != null) {
17835            final long delay = when - SystemClock.uptimeMillis();
17836            if (mAttachInfo != null) {
17837                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17838                        Choreographer.CALLBACK_ANIMATION, what, who,
17839                        Choreographer.subtractFrameDelay(delay));
17840            } else {
17841                // Postpone the runnable until we know
17842                // on which thread it needs to run.
17843                getRunQueue().postDelayed(what, delay);
17844            }
17845        }
17846    }
17847
17848    /**
17849     * Cancels a scheduled action on a drawable.
17850     *
17851     * @param who the recipient of the action
17852     * @param what the action to cancel
17853     */
17854    @Override
17855    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
17856        if (verifyDrawable(who) && what != null) {
17857            if (mAttachInfo != null) {
17858                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17859                        Choreographer.CALLBACK_ANIMATION, what, who);
17860            }
17861            getRunQueue().removeCallbacks(what);
17862        }
17863    }
17864
17865    /**
17866     * Unschedule any events associated with the given Drawable.  This can be
17867     * used when selecting a new Drawable into a view, so that the previous
17868     * one is completely unscheduled.
17869     *
17870     * @param who The Drawable to unschedule.
17871     *
17872     * @see #drawableStateChanged
17873     */
17874    public void unscheduleDrawable(Drawable who) {
17875        if (mAttachInfo != null && who != null) {
17876            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17877                    Choreographer.CALLBACK_ANIMATION, null, who);
17878        }
17879    }
17880
17881    /**
17882     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
17883     * that the View directionality can and will be resolved before its Drawables.
17884     *
17885     * Will call {@link View#onResolveDrawables} when resolution is done.
17886     *
17887     * @hide
17888     */
17889    protected void resolveDrawables() {
17890        // Drawables resolution may need to happen before resolving the layout direction (which is
17891        // done only during the measure() call).
17892        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
17893        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
17894        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
17895        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
17896        // direction to be resolved as its resolved value will be the same as its raw value.
17897        if (!isLayoutDirectionResolved() &&
17898                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17899            return;
17900        }
17901
17902        final int layoutDirection = isLayoutDirectionResolved() ?
17903                getLayoutDirection() : getRawLayoutDirection();
17904
17905        if (mBackground != null) {
17906            mBackground.setLayoutDirection(layoutDirection);
17907        }
17908        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17909            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17910        }
17911        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17912        onResolveDrawables(layoutDirection);
17913    }
17914
17915    boolean areDrawablesResolved() {
17916        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17917    }
17918
17919    /**
17920     * Called when layout direction has been resolved.
17921     *
17922     * The default implementation does nothing.
17923     *
17924     * @param layoutDirection The resolved layout direction.
17925     *
17926     * @see #LAYOUT_DIRECTION_LTR
17927     * @see #LAYOUT_DIRECTION_RTL
17928     *
17929     * @hide
17930     */
17931    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17932    }
17933
17934    /**
17935     * @hide
17936     */
17937    protected void resetResolvedDrawables() {
17938        resetResolvedDrawablesInternal();
17939    }
17940
17941    void resetResolvedDrawablesInternal() {
17942        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17943    }
17944
17945    /**
17946     * If your view subclass is displaying its own Drawable objects, it should
17947     * override this function and return true for any Drawable it is
17948     * displaying.  This allows animations for those drawables to be
17949     * scheduled.
17950     *
17951     * <p>Be sure to call through to the super class when overriding this
17952     * function.
17953     *
17954     * @param who The Drawable to verify.  Return true if it is one you are
17955     *            displaying, else return the result of calling through to the
17956     *            super class.
17957     *
17958     * @return boolean If true than the Drawable is being displayed in the
17959     *         view; else false and it is not allowed to animate.
17960     *
17961     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17962     * @see #drawableStateChanged()
17963     */
17964    @CallSuper
17965    protected boolean verifyDrawable(@NonNull Drawable who) {
17966        // Avoid verifying the scroll bar drawable so that we don't end up in
17967        // an invalidation loop. This effectively prevents the scroll bar
17968        // drawable from triggering invalidations and scheduling runnables.
17969        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17970    }
17971
17972    /**
17973     * This function is called whenever the state of the view changes in such
17974     * a way that it impacts the state of drawables being shown.
17975     * <p>
17976     * If the View has a StateListAnimator, it will also be called to run necessary state
17977     * change animations.
17978     * <p>
17979     * Be sure to call through to the superclass when overriding this function.
17980     *
17981     * @see Drawable#setState(int[])
17982     */
17983    @CallSuper
17984    protected void drawableStateChanged() {
17985        final int[] state = getDrawableState();
17986        boolean changed = false;
17987
17988        final Drawable bg = mBackground;
17989        if (bg != null && bg.isStateful()) {
17990            changed |= bg.setState(state);
17991        }
17992
17993        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17994        if (fg != null && fg.isStateful()) {
17995            changed |= fg.setState(state);
17996        }
17997
17998        if (mScrollCache != null) {
17999            final Drawable scrollBar = mScrollCache.scrollBar;
18000            if (scrollBar != null && scrollBar.isStateful()) {
18001                changed |= scrollBar.setState(state)
18002                        && mScrollCache.state != ScrollabilityCache.OFF;
18003            }
18004        }
18005
18006        if (mStateListAnimator != null) {
18007            mStateListAnimator.setState(state);
18008        }
18009
18010        if (changed) {
18011            invalidate();
18012        }
18013    }
18014
18015    /**
18016     * This function is called whenever the view hotspot changes and needs to
18017     * be propagated to drawables or child views managed by the view.
18018     * <p>
18019     * Dispatching to child views is handled by
18020     * {@link #dispatchDrawableHotspotChanged(float, float)}.
18021     * <p>
18022     * Be sure to call through to the superclass when overriding this function.
18023     *
18024     * @param x hotspot x coordinate
18025     * @param y hotspot y coordinate
18026     */
18027    @CallSuper
18028    public void drawableHotspotChanged(float x, float y) {
18029        if (mBackground != null) {
18030            mBackground.setHotspot(x, y);
18031        }
18032        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18033            mForegroundInfo.mDrawable.setHotspot(x, y);
18034        }
18035
18036        dispatchDrawableHotspotChanged(x, y);
18037    }
18038
18039    /**
18040     * Dispatches drawableHotspotChanged to all of this View's children.
18041     *
18042     * @param x hotspot x coordinate
18043     * @param y hotspot y coordinate
18044     * @see #drawableHotspotChanged(float, float)
18045     */
18046    public void dispatchDrawableHotspotChanged(float x, float y) {
18047    }
18048
18049    /**
18050     * Call this to force a view to update its drawable state. This will cause
18051     * drawableStateChanged to be called on this view. Views that are interested
18052     * in the new state should call getDrawableState.
18053     *
18054     * @see #drawableStateChanged
18055     * @see #getDrawableState
18056     */
18057    public void refreshDrawableState() {
18058        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
18059        drawableStateChanged();
18060
18061        ViewParent parent = mParent;
18062        if (parent != null) {
18063            parent.childDrawableStateChanged(this);
18064        }
18065    }
18066
18067    /**
18068     * Return an array of resource IDs of the drawable states representing the
18069     * current state of the view.
18070     *
18071     * @return The current drawable state
18072     *
18073     * @see Drawable#setState(int[])
18074     * @see #drawableStateChanged()
18075     * @see #onCreateDrawableState(int)
18076     */
18077    public final int[] getDrawableState() {
18078        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
18079            return mDrawableState;
18080        } else {
18081            mDrawableState = onCreateDrawableState(0);
18082            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
18083            return mDrawableState;
18084        }
18085    }
18086
18087    /**
18088     * Generate the new {@link android.graphics.drawable.Drawable} state for
18089     * this view. This is called by the view
18090     * system when the cached Drawable state is determined to be invalid.  To
18091     * retrieve the current state, you should use {@link #getDrawableState}.
18092     *
18093     * @param extraSpace if non-zero, this is the number of extra entries you
18094     * would like in the returned array in which you can place your own
18095     * states.
18096     *
18097     * @return Returns an array holding the current {@link Drawable} state of
18098     * the view.
18099     *
18100     * @see #mergeDrawableStates(int[], int[])
18101     */
18102    protected int[] onCreateDrawableState(int extraSpace) {
18103        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
18104                mParent instanceof View) {
18105            return ((View) mParent).onCreateDrawableState(extraSpace);
18106        }
18107
18108        int[] drawableState;
18109
18110        int privateFlags = mPrivateFlags;
18111
18112        int viewStateIndex = 0;
18113        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
18114        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
18115        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
18116        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
18117        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
18118        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
18119        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
18120                ThreadedRenderer.isAvailable()) {
18121            // This is set if HW acceleration is requested, even if the current
18122            // process doesn't allow it.  This is just to allow app preview
18123            // windows to better match their app.
18124            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
18125        }
18126        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
18127
18128        final int privateFlags2 = mPrivateFlags2;
18129        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
18130            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
18131        }
18132        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
18133            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
18134        }
18135
18136        drawableState = StateSet.get(viewStateIndex);
18137
18138        //noinspection ConstantIfStatement
18139        if (false) {
18140            Log.i("View", "drawableStateIndex=" + viewStateIndex);
18141            Log.i("View", toString()
18142                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
18143                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
18144                    + " fo=" + hasFocus()
18145                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
18146                    + " wf=" + hasWindowFocus()
18147                    + ": " + Arrays.toString(drawableState));
18148        }
18149
18150        if (extraSpace == 0) {
18151            return drawableState;
18152        }
18153
18154        final int[] fullState;
18155        if (drawableState != null) {
18156            fullState = new int[drawableState.length + extraSpace];
18157            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
18158        } else {
18159            fullState = new int[extraSpace];
18160        }
18161
18162        return fullState;
18163    }
18164
18165    /**
18166     * Merge your own state values in <var>additionalState</var> into the base
18167     * state values <var>baseState</var> that were returned by
18168     * {@link #onCreateDrawableState(int)}.
18169     *
18170     * @param baseState The base state values returned by
18171     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
18172     * own additional state values.
18173     *
18174     * @param additionalState The additional state values you would like
18175     * added to <var>baseState</var>; this array is not modified.
18176     *
18177     * @return As a convenience, the <var>baseState</var> array you originally
18178     * passed into the function is returned.
18179     *
18180     * @see #onCreateDrawableState(int)
18181     */
18182    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
18183        final int N = baseState.length;
18184        int i = N - 1;
18185        while (i >= 0 && baseState[i] == 0) {
18186            i--;
18187        }
18188        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
18189        return baseState;
18190    }
18191
18192    /**
18193     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
18194     * on all Drawable objects associated with this view.
18195     * <p>
18196     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
18197     * attached to this view.
18198     */
18199    @CallSuper
18200    public void jumpDrawablesToCurrentState() {
18201        if (mBackground != null) {
18202            mBackground.jumpToCurrentState();
18203        }
18204        if (mStateListAnimator != null) {
18205            mStateListAnimator.jumpToCurrentState();
18206        }
18207        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18208            mForegroundInfo.mDrawable.jumpToCurrentState();
18209        }
18210    }
18211
18212    /**
18213     * Sets the background color for this view.
18214     * @param color the color of the background
18215     */
18216    @RemotableViewMethod
18217    public void setBackgroundColor(@ColorInt int color) {
18218        if (mBackground instanceof ColorDrawable) {
18219            ((ColorDrawable) mBackground.mutate()).setColor(color);
18220            computeOpaqueFlags();
18221            mBackgroundResource = 0;
18222        } else {
18223            setBackground(new ColorDrawable(color));
18224        }
18225    }
18226
18227    /**
18228     * Set the background to a given resource. The resource should refer to
18229     * a Drawable object or 0 to remove the background.
18230     * @param resid The identifier of the resource.
18231     *
18232     * @attr ref android.R.styleable#View_background
18233     */
18234    @RemotableViewMethod
18235    public void setBackgroundResource(@DrawableRes int resid) {
18236        if (resid != 0 && resid == mBackgroundResource) {
18237            return;
18238        }
18239
18240        Drawable d = null;
18241        if (resid != 0) {
18242            d = mContext.getDrawable(resid);
18243        }
18244        setBackground(d);
18245
18246        mBackgroundResource = resid;
18247    }
18248
18249    /**
18250     * Set the background to a given Drawable, or remove the background. If the
18251     * background has padding, this View's padding is set to the background's
18252     * padding. However, when a background is removed, this View's padding isn't
18253     * touched. If setting the padding is desired, please use
18254     * {@link #setPadding(int, int, int, int)}.
18255     *
18256     * @param background The Drawable to use as the background, or null to remove the
18257     *        background
18258     */
18259    public void setBackground(Drawable background) {
18260        //noinspection deprecation
18261        setBackgroundDrawable(background);
18262    }
18263
18264    /**
18265     * @deprecated use {@link #setBackground(Drawable)} instead
18266     */
18267    @Deprecated
18268    public void setBackgroundDrawable(Drawable background) {
18269        computeOpaqueFlags();
18270
18271        if (background == mBackground) {
18272            return;
18273        }
18274
18275        boolean requestLayout = false;
18276
18277        mBackgroundResource = 0;
18278
18279        /*
18280         * Regardless of whether we're setting a new background or not, we want
18281         * to clear the previous drawable. setVisible first while we still have the callback set.
18282         */
18283        if (mBackground != null) {
18284            if (isAttachedToWindow()) {
18285                mBackground.setVisible(false, false);
18286            }
18287            mBackground.setCallback(null);
18288            unscheduleDrawable(mBackground);
18289        }
18290
18291        if (background != null) {
18292            Rect padding = sThreadLocal.get();
18293            if (padding == null) {
18294                padding = new Rect();
18295                sThreadLocal.set(padding);
18296            }
18297            resetResolvedDrawablesInternal();
18298            background.setLayoutDirection(getLayoutDirection());
18299            if (background.getPadding(padding)) {
18300                resetResolvedPaddingInternal();
18301                switch (background.getLayoutDirection()) {
18302                    case LAYOUT_DIRECTION_RTL:
18303                        mUserPaddingLeftInitial = padding.right;
18304                        mUserPaddingRightInitial = padding.left;
18305                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
18306                        break;
18307                    case LAYOUT_DIRECTION_LTR:
18308                    default:
18309                        mUserPaddingLeftInitial = padding.left;
18310                        mUserPaddingRightInitial = padding.right;
18311                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
18312                }
18313                mLeftPaddingDefined = false;
18314                mRightPaddingDefined = false;
18315            }
18316
18317            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
18318            // if it has a different minimum size, we should layout again
18319            if (mBackground == null
18320                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
18321                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
18322                requestLayout = true;
18323            }
18324
18325            // Set mBackground before we set this as the callback and start making other
18326            // background drawable state change calls. In particular, the setVisible call below
18327            // can result in drawables attempting to start animations or otherwise invalidate,
18328            // which requires the view set as the callback (us) to recognize the drawable as
18329            // belonging to it as per verifyDrawable.
18330            mBackground = background;
18331            if (background.isStateful()) {
18332                background.setState(getDrawableState());
18333            }
18334            if (isAttachedToWindow()) {
18335                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18336            }
18337
18338            applyBackgroundTint();
18339
18340            // Set callback last, since the view may still be initializing.
18341            background.setCallback(this);
18342
18343            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18344                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18345                requestLayout = true;
18346            }
18347        } else {
18348            /* Remove the background */
18349            mBackground = null;
18350            if ((mViewFlags & WILL_NOT_DRAW) != 0
18351                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
18352                mPrivateFlags |= PFLAG_SKIP_DRAW;
18353            }
18354
18355            /*
18356             * When the background is set, we try to apply its padding to this
18357             * View. When the background is removed, we don't touch this View's
18358             * padding. This is noted in the Javadocs. Hence, we don't need to
18359             * requestLayout(), the invalidate() below is sufficient.
18360             */
18361
18362            // The old background's minimum size could have affected this
18363            // View's layout, so let's requestLayout
18364            requestLayout = true;
18365        }
18366
18367        computeOpaqueFlags();
18368
18369        if (requestLayout) {
18370            requestLayout();
18371        }
18372
18373        mBackgroundSizeChanged = true;
18374        invalidate(true);
18375        invalidateOutline();
18376    }
18377
18378    /**
18379     * Gets the background drawable
18380     *
18381     * @return The drawable used as the background for this view, if any.
18382     *
18383     * @see #setBackground(Drawable)
18384     *
18385     * @attr ref android.R.styleable#View_background
18386     */
18387    public Drawable getBackground() {
18388        return mBackground;
18389    }
18390
18391    /**
18392     * Applies a tint to the background drawable. Does not modify the current tint
18393     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18394     * <p>
18395     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
18396     * mutate the drawable and apply the specified tint and tint mode using
18397     * {@link Drawable#setTintList(ColorStateList)}.
18398     *
18399     * @param tint the tint to apply, may be {@code null} to clear tint
18400     *
18401     * @attr ref android.R.styleable#View_backgroundTint
18402     * @see #getBackgroundTintList()
18403     * @see Drawable#setTintList(ColorStateList)
18404     */
18405    public void setBackgroundTintList(@Nullable ColorStateList tint) {
18406        if (mBackgroundTint == null) {
18407            mBackgroundTint = new TintInfo();
18408        }
18409        mBackgroundTint.mTintList = tint;
18410        mBackgroundTint.mHasTintList = true;
18411
18412        applyBackgroundTint();
18413    }
18414
18415    /**
18416     * Return the tint applied to the background drawable, if specified.
18417     *
18418     * @return the tint applied to the background drawable
18419     * @attr ref android.R.styleable#View_backgroundTint
18420     * @see #setBackgroundTintList(ColorStateList)
18421     */
18422    @Nullable
18423    public ColorStateList getBackgroundTintList() {
18424        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
18425    }
18426
18427    /**
18428     * Specifies the blending mode used to apply the tint specified by
18429     * {@link #setBackgroundTintList(ColorStateList)}} to the background
18430     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18431     *
18432     * @param tintMode the blending mode used to apply the tint, may be
18433     *                 {@code null} to clear tint
18434     * @attr ref android.R.styleable#View_backgroundTintMode
18435     * @see #getBackgroundTintMode()
18436     * @see Drawable#setTintMode(PorterDuff.Mode)
18437     */
18438    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18439        if (mBackgroundTint == null) {
18440            mBackgroundTint = new TintInfo();
18441        }
18442        mBackgroundTint.mTintMode = tintMode;
18443        mBackgroundTint.mHasTintMode = true;
18444
18445        applyBackgroundTint();
18446    }
18447
18448    /**
18449     * Return the blending mode used to apply the tint to the background
18450     * drawable, if specified.
18451     *
18452     * @return the blending mode used to apply the tint to the background
18453     *         drawable
18454     * @attr ref android.R.styleable#View_backgroundTintMode
18455     * @see #setBackgroundTintMode(PorterDuff.Mode)
18456     */
18457    @Nullable
18458    public PorterDuff.Mode getBackgroundTintMode() {
18459        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
18460    }
18461
18462    private void applyBackgroundTint() {
18463        if (mBackground != null && mBackgroundTint != null) {
18464            final TintInfo tintInfo = mBackgroundTint;
18465            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18466                mBackground = mBackground.mutate();
18467
18468                if (tintInfo.mHasTintList) {
18469                    mBackground.setTintList(tintInfo.mTintList);
18470                }
18471
18472                if (tintInfo.mHasTintMode) {
18473                    mBackground.setTintMode(tintInfo.mTintMode);
18474                }
18475
18476                // The drawable (or one of its children) may not have been
18477                // stateful before applying the tint, so let's try again.
18478                if (mBackground.isStateful()) {
18479                    mBackground.setState(getDrawableState());
18480                }
18481            }
18482        }
18483    }
18484
18485    /**
18486     * Returns the drawable used as the foreground of this View. The
18487     * foreground drawable, if non-null, is always drawn on top of the view's content.
18488     *
18489     * @return a Drawable or null if no foreground was set
18490     *
18491     * @see #onDrawForeground(Canvas)
18492     */
18493    public Drawable getForeground() {
18494        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18495    }
18496
18497    /**
18498     * Supply a Drawable that is to be rendered on top of all of the content in the view.
18499     *
18500     * @param foreground the Drawable to be drawn on top of the children
18501     *
18502     * @attr ref android.R.styleable#View_foreground
18503     */
18504    public void setForeground(Drawable foreground) {
18505        if (mForegroundInfo == null) {
18506            if (foreground == null) {
18507                // Nothing to do.
18508                return;
18509            }
18510            mForegroundInfo = new ForegroundInfo();
18511        }
18512
18513        if (foreground == mForegroundInfo.mDrawable) {
18514            // Nothing to do
18515            return;
18516        }
18517
18518        if (mForegroundInfo.mDrawable != null) {
18519            if (isAttachedToWindow()) {
18520                mForegroundInfo.mDrawable.setVisible(false, false);
18521            }
18522            mForegroundInfo.mDrawable.setCallback(null);
18523            unscheduleDrawable(mForegroundInfo.mDrawable);
18524        }
18525
18526        mForegroundInfo.mDrawable = foreground;
18527        mForegroundInfo.mBoundsChanged = true;
18528        if (foreground != null) {
18529            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18530                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18531            }
18532            foreground.setLayoutDirection(getLayoutDirection());
18533            if (foreground.isStateful()) {
18534                foreground.setState(getDrawableState());
18535            }
18536            applyForegroundTint();
18537            if (isAttachedToWindow()) {
18538                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18539            }
18540            // Set callback last, since the view may still be initializing.
18541            foreground.setCallback(this);
18542        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
18543            mPrivateFlags |= PFLAG_SKIP_DRAW;
18544        }
18545        requestLayout();
18546        invalidate();
18547    }
18548
18549    /**
18550     * Magic bit used to support features of framework-internal window decor implementation details.
18551     * This used to live exclusively in FrameLayout.
18552     *
18553     * @return true if the foreground should draw inside the padding region or false
18554     *         if it should draw inset by the view's padding
18555     * @hide internal use only; only used by FrameLayout and internal screen layouts.
18556     */
18557    public boolean isForegroundInsidePadding() {
18558        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
18559    }
18560
18561    /**
18562     * Describes how the foreground is positioned.
18563     *
18564     * @return foreground gravity.
18565     *
18566     * @see #setForegroundGravity(int)
18567     *
18568     * @attr ref android.R.styleable#View_foregroundGravity
18569     */
18570    public int getForegroundGravity() {
18571        return mForegroundInfo != null ? mForegroundInfo.mGravity
18572                : Gravity.START | Gravity.TOP;
18573    }
18574
18575    /**
18576     * Describes how the foreground is positioned. Defaults to START and TOP.
18577     *
18578     * @param gravity see {@link android.view.Gravity}
18579     *
18580     * @see #getForegroundGravity()
18581     *
18582     * @attr ref android.R.styleable#View_foregroundGravity
18583     */
18584    public void setForegroundGravity(int gravity) {
18585        if (mForegroundInfo == null) {
18586            mForegroundInfo = new ForegroundInfo();
18587        }
18588
18589        if (mForegroundInfo.mGravity != gravity) {
18590            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
18591                gravity |= Gravity.START;
18592            }
18593
18594            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
18595                gravity |= Gravity.TOP;
18596            }
18597
18598            mForegroundInfo.mGravity = gravity;
18599            requestLayout();
18600        }
18601    }
18602
18603    /**
18604     * Applies a tint to the foreground drawable. Does not modify the current tint
18605     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18606     * <p>
18607     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
18608     * mutate the drawable and apply the specified tint and tint mode using
18609     * {@link Drawable#setTintList(ColorStateList)}.
18610     *
18611     * @param tint the tint to apply, may be {@code null} to clear tint
18612     *
18613     * @attr ref android.R.styleable#View_foregroundTint
18614     * @see #getForegroundTintList()
18615     * @see Drawable#setTintList(ColorStateList)
18616     */
18617    public void setForegroundTintList(@Nullable ColorStateList tint) {
18618        if (mForegroundInfo == null) {
18619            mForegroundInfo = new ForegroundInfo();
18620        }
18621        if (mForegroundInfo.mTintInfo == null) {
18622            mForegroundInfo.mTintInfo = new TintInfo();
18623        }
18624        mForegroundInfo.mTintInfo.mTintList = tint;
18625        mForegroundInfo.mTintInfo.mHasTintList = true;
18626
18627        applyForegroundTint();
18628    }
18629
18630    /**
18631     * Return the tint applied to the foreground drawable, if specified.
18632     *
18633     * @return the tint applied to the foreground drawable
18634     * @attr ref android.R.styleable#View_foregroundTint
18635     * @see #setForegroundTintList(ColorStateList)
18636     */
18637    @Nullable
18638    public ColorStateList getForegroundTintList() {
18639        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18640                ? mForegroundInfo.mTintInfo.mTintList : null;
18641    }
18642
18643    /**
18644     * Specifies the blending mode used to apply the tint specified by
18645     * {@link #setForegroundTintList(ColorStateList)}} to the background
18646     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18647     *
18648     * @param tintMode the blending mode used to apply the tint, may be
18649     *                 {@code null} to clear tint
18650     * @attr ref android.R.styleable#View_foregroundTintMode
18651     * @see #getForegroundTintMode()
18652     * @see Drawable#setTintMode(PorterDuff.Mode)
18653     */
18654    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18655        if (mForegroundInfo == null) {
18656            mForegroundInfo = new ForegroundInfo();
18657        }
18658        if (mForegroundInfo.mTintInfo == null) {
18659            mForegroundInfo.mTintInfo = new TintInfo();
18660        }
18661        mForegroundInfo.mTintInfo.mTintMode = tintMode;
18662        mForegroundInfo.mTintInfo.mHasTintMode = true;
18663
18664        applyForegroundTint();
18665    }
18666
18667    /**
18668     * Return the blending mode used to apply the tint to the foreground
18669     * drawable, if specified.
18670     *
18671     * @return the blending mode used to apply the tint to the foreground
18672     *         drawable
18673     * @attr ref android.R.styleable#View_foregroundTintMode
18674     * @see #setForegroundTintMode(PorterDuff.Mode)
18675     */
18676    @Nullable
18677    public PorterDuff.Mode getForegroundTintMode() {
18678        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18679                ? mForegroundInfo.mTintInfo.mTintMode : null;
18680    }
18681
18682    private void applyForegroundTint() {
18683        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
18684                && mForegroundInfo.mTintInfo != null) {
18685            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
18686            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18687                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
18688
18689                if (tintInfo.mHasTintList) {
18690                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
18691                }
18692
18693                if (tintInfo.mHasTintMode) {
18694                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
18695                }
18696
18697                // The drawable (or one of its children) may not have been
18698                // stateful before applying the tint, so let's try again.
18699                if (mForegroundInfo.mDrawable.isStateful()) {
18700                    mForegroundInfo.mDrawable.setState(getDrawableState());
18701                }
18702            }
18703        }
18704    }
18705
18706    /**
18707     * Draw any foreground content for this view.
18708     *
18709     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
18710     * drawable or other view-specific decorations. The foreground is drawn on top of the
18711     * primary view content.</p>
18712     *
18713     * @param canvas canvas to draw into
18714     */
18715    public void onDrawForeground(Canvas canvas) {
18716        onDrawScrollIndicators(canvas);
18717        onDrawScrollBars(canvas);
18718
18719        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18720        if (foreground != null) {
18721            if (mForegroundInfo.mBoundsChanged) {
18722                mForegroundInfo.mBoundsChanged = false;
18723                final Rect selfBounds = mForegroundInfo.mSelfBounds;
18724                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
18725
18726                if (mForegroundInfo.mInsidePadding) {
18727                    selfBounds.set(0, 0, getWidth(), getHeight());
18728                } else {
18729                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
18730                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
18731                }
18732
18733                final int ld = getLayoutDirection();
18734                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
18735                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
18736                foreground.setBounds(overlayBounds);
18737            }
18738
18739            foreground.draw(canvas);
18740        }
18741    }
18742
18743    /**
18744     * Sets the padding. The view may add on the space required to display
18745     * the scrollbars, depending on the style and visibility of the scrollbars.
18746     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
18747     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
18748     * from the values set in this call.
18749     *
18750     * @attr ref android.R.styleable#View_padding
18751     * @attr ref android.R.styleable#View_paddingBottom
18752     * @attr ref android.R.styleable#View_paddingLeft
18753     * @attr ref android.R.styleable#View_paddingRight
18754     * @attr ref android.R.styleable#View_paddingTop
18755     * @param left the left padding in pixels
18756     * @param top the top padding in pixels
18757     * @param right the right padding in pixels
18758     * @param bottom the bottom padding in pixels
18759     */
18760    public void setPadding(int left, int top, int right, int bottom) {
18761        resetResolvedPaddingInternal();
18762
18763        mUserPaddingStart = UNDEFINED_PADDING;
18764        mUserPaddingEnd = UNDEFINED_PADDING;
18765
18766        mUserPaddingLeftInitial = left;
18767        mUserPaddingRightInitial = right;
18768
18769        mLeftPaddingDefined = true;
18770        mRightPaddingDefined = true;
18771
18772        internalSetPadding(left, top, right, bottom);
18773    }
18774
18775    /**
18776     * @hide
18777     */
18778    protected void internalSetPadding(int left, int top, int right, int bottom) {
18779        mUserPaddingLeft = left;
18780        mUserPaddingRight = right;
18781        mUserPaddingBottom = bottom;
18782
18783        final int viewFlags = mViewFlags;
18784        boolean changed = false;
18785
18786        // Common case is there are no scroll bars.
18787        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
18788            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
18789                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
18790                        ? 0 : getVerticalScrollbarWidth();
18791                switch (mVerticalScrollbarPosition) {
18792                    case SCROLLBAR_POSITION_DEFAULT:
18793                        if (isLayoutRtl()) {
18794                            left += offset;
18795                        } else {
18796                            right += offset;
18797                        }
18798                        break;
18799                    case SCROLLBAR_POSITION_RIGHT:
18800                        right += offset;
18801                        break;
18802                    case SCROLLBAR_POSITION_LEFT:
18803                        left += offset;
18804                        break;
18805                }
18806            }
18807            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
18808                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
18809                        ? 0 : getHorizontalScrollbarHeight();
18810            }
18811        }
18812
18813        if (mPaddingLeft != left) {
18814            changed = true;
18815            mPaddingLeft = left;
18816        }
18817        if (mPaddingTop != top) {
18818            changed = true;
18819            mPaddingTop = top;
18820        }
18821        if (mPaddingRight != right) {
18822            changed = true;
18823            mPaddingRight = right;
18824        }
18825        if (mPaddingBottom != bottom) {
18826            changed = true;
18827            mPaddingBottom = bottom;
18828        }
18829
18830        if (changed) {
18831            requestLayout();
18832            invalidateOutline();
18833        }
18834    }
18835
18836    /**
18837     * Sets the relative padding. The view may add on the space required to display
18838     * the scrollbars, depending on the style and visibility of the scrollbars.
18839     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
18840     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
18841     * from the values set in this call.
18842     *
18843     * @attr ref android.R.styleable#View_padding
18844     * @attr ref android.R.styleable#View_paddingBottom
18845     * @attr ref android.R.styleable#View_paddingStart
18846     * @attr ref android.R.styleable#View_paddingEnd
18847     * @attr ref android.R.styleable#View_paddingTop
18848     * @param start the start padding in pixels
18849     * @param top the top padding in pixels
18850     * @param end the end padding in pixels
18851     * @param bottom the bottom padding in pixels
18852     */
18853    public void setPaddingRelative(int start, int top, int end, int bottom) {
18854        resetResolvedPaddingInternal();
18855
18856        mUserPaddingStart = start;
18857        mUserPaddingEnd = end;
18858        mLeftPaddingDefined = true;
18859        mRightPaddingDefined = true;
18860
18861        switch(getLayoutDirection()) {
18862            case LAYOUT_DIRECTION_RTL:
18863                mUserPaddingLeftInitial = end;
18864                mUserPaddingRightInitial = start;
18865                internalSetPadding(end, top, start, bottom);
18866                break;
18867            case LAYOUT_DIRECTION_LTR:
18868            default:
18869                mUserPaddingLeftInitial = start;
18870                mUserPaddingRightInitial = end;
18871                internalSetPadding(start, top, end, bottom);
18872        }
18873    }
18874
18875    /**
18876     * Returns the top padding of this view.
18877     *
18878     * @return the top padding in pixels
18879     */
18880    public int getPaddingTop() {
18881        return mPaddingTop;
18882    }
18883
18884    /**
18885     * Returns the bottom padding of this view. If there are inset and enabled
18886     * scrollbars, this value may include the space required to display the
18887     * scrollbars as well.
18888     *
18889     * @return the bottom padding in pixels
18890     */
18891    public int getPaddingBottom() {
18892        return mPaddingBottom;
18893    }
18894
18895    /**
18896     * Returns the left padding of this view. If there are inset and enabled
18897     * scrollbars, this value may include the space required to display the
18898     * scrollbars as well.
18899     *
18900     * @return the left padding in pixels
18901     */
18902    public int getPaddingLeft() {
18903        if (!isPaddingResolved()) {
18904            resolvePadding();
18905        }
18906        return mPaddingLeft;
18907    }
18908
18909    /**
18910     * Returns the start padding of this view depending on its resolved layout direction.
18911     * If there are inset and enabled scrollbars, this value may include the space
18912     * required to display the scrollbars as well.
18913     *
18914     * @return the start padding in pixels
18915     */
18916    public int getPaddingStart() {
18917        if (!isPaddingResolved()) {
18918            resolvePadding();
18919        }
18920        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18921                mPaddingRight : mPaddingLeft;
18922    }
18923
18924    /**
18925     * Returns the right padding of this view. If there are inset and enabled
18926     * scrollbars, this value may include the space required to display the
18927     * scrollbars as well.
18928     *
18929     * @return the right padding in pixels
18930     */
18931    public int getPaddingRight() {
18932        if (!isPaddingResolved()) {
18933            resolvePadding();
18934        }
18935        return mPaddingRight;
18936    }
18937
18938    /**
18939     * Returns the end padding of this view depending on its resolved layout direction.
18940     * If there are inset and enabled scrollbars, this value may include the space
18941     * required to display the scrollbars as well.
18942     *
18943     * @return the end padding in pixels
18944     */
18945    public int getPaddingEnd() {
18946        if (!isPaddingResolved()) {
18947            resolvePadding();
18948        }
18949        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18950                mPaddingLeft : mPaddingRight;
18951    }
18952
18953    /**
18954     * Return if the padding has been set through relative values
18955     * {@link #setPaddingRelative(int, int, int, int)} or through
18956     * @attr ref android.R.styleable#View_paddingStart or
18957     * @attr ref android.R.styleable#View_paddingEnd
18958     *
18959     * @return true if the padding is relative or false if it is not.
18960     */
18961    public boolean isPaddingRelative() {
18962        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18963    }
18964
18965    Insets computeOpticalInsets() {
18966        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18967    }
18968
18969    /**
18970     * @hide
18971     */
18972    public void resetPaddingToInitialValues() {
18973        if (isRtlCompatibilityMode()) {
18974            mPaddingLeft = mUserPaddingLeftInitial;
18975            mPaddingRight = mUserPaddingRightInitial;
18976            return;
18977        }
18978        if (isLayoutRtl()) {
18979            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18980            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18981        } else {
18982            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18983            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18984        }
18985    }
18986
18987    /**
18988     * @hide
18989     */
18990    public Insets getOpticalInsets() {
18991        if (mLayoutInsets == null) {
18992            mLayoutInsets = computeOpticalInsets();
18993        }
18994        return mLayoutInsets;
18995    }
18996
18997    /**
18998     * Set this view's optical insets.
18999     *
19000     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
19001     * property. Views that compute their own optical insets should call it as part of measurement.
19002     * This method does not request layout. If you are setting optical insets outside of
19003     * measure/layout itself you will want to call requestLayout() yourself.
19004     * </p>
19005     * @hide
19006     */
19007    public void setOpticalInsets(Insets insets) {
19008        mLayoutInsets = insets;
19009    }
19010
19011    /**
19012     * Changes the selection state of this view. A view can be selected or not.
19013     * Note that selection is not the same as focus. Views are typically
19014     * selected in the context of an AdapterView like ListView or GridView;
19015     * the selected view is the view that is highlighted.
19016     *
19017     * @param selected true if the view must be selected, false otherwise
19018     */
19019    public void setSelected(boolean selected) {
19020        //noinspection DoubleNegation
19021        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
19022            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
19023            if (!selected) resetPressedState();
19024            invalidate(true);
19025            refreshDrawableState();
19026            dispatchSetSelected(selected);
19027            if (selected) {
19028                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
19029            } else {
19030                notifyViewAccessibilityStateChangedIfNeeded(
19031                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
19032            }
19033        }
19034    }
19035
19036    /**
19037     * Dispatch setSelected to all of this View's children.
19038     *
19039     * @see #setSelected(boolean)
19040     *
19041     * @param selected The new selected state
19042     */
19043    protected void dispatchSetSelected(boolean selected) {
19044    }
19045
19046    /**
19047     * Indicates the selection state of this view.
19048     *
19049     * @return true if the view is selected, false otherwise
19050     */
19051    @ViewDebug.ExportedProperty
19052    public boolean isSelected() {
19053        return (mPrivateFlags & PFLAG_SELECTED) != 0;
19054    }
19055
19056    /**
19057     * Changes the activated state of this view. A view can be activated or not.
19058     * Note that activation is not the same as selection.  Selection is
19059     * a transient property, representing the view (hierarchy) the user is
19060     * currently interacting with.  Activation is a longer-term state that the
19061     * user can move views in and out of.  For example, in a list view with
19062     * single or multiple selection enabled, the views in the current selection
19063     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
19064     * here.)  The activated state is propagated down to children of the view it
19065     * is set on.
19066     *
19067     * @param activated true if the view must be activated, false otherwise
19068     */
19069    public void setActivated(boolean activated) {
19070        //noinspection DoubleNegation
19071        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
19072            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
19073            invalidate(true);
19074            refreshDrawableState();
19075            dispatchSetActivated(activated);
19076        }
19077    }
19078
19079    /**
19080     * Dispatch setActivated to all of this View's children.
19081     *
19082     * @see #setActivated(boolean)
19083     *
19084     * @param activated The new activated state
19085     */
19086    protected void dispatchSetActivated(boolean activated) {
19087    }
19088
19089    /**
19090     * Indicates the activation state of this view.
19091     *
19092     * @return true if the view is activated, false otherwise
19093     */
19094    @ViewDebug.ExportedProperty
19095    public boolean isActivated() {
19096        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
19097    }
19098
19099    /**
19100     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
19101     * observer can be used to get notifications when global events, like
19102     * layout, happen.
19103     *
19104     * The returned ViewTreeObserver observer is not guaranteed to remain
19105     * valid for the lifetime of this View. If the caller of this method keeps
19106     * a long-lived reference to ViewTreeObserver, it should always check for
19107     * the return value of {@link ViewTreeObserver#isAlive()}.
19108     *
19109     * @return The ViewTreeObserver for this view's hierarchy.
19110     */
19111    public ViewTreeObserver getViewTreeObserver() {
19112        if (mAttachInfo != null) {
19113            return mAttachInfo.mTreeObserver;
19114        }
19115        if (mFloatingTreeObserver == null) {
19116            mFloatingTreeObserver = new ViewTreeObserver();
19117        }
19118        return mFloatingTreeObserver;
19119    }
19120
19121    /**
19122     * <p>Finds the topmost view in the current view hierarchy.</p>
19123     *
19124     * @return the topmost view containing this view
19125     */
19126    public View getRootView() {
19127        if (mAttachInfo != null) {
19128            final View v = mAttachInfo.mRootView;
19129            if (v != null) {
19130                return v;
19131            }
19132        }
19133
19134        View parent = this;
19135
19136        while (parent.mParent != null && parent.mParent instanceof View) {
19137            parent = (View) parent.mParent;
19138        }
19139
19140        return parent;
19141    }
19142
19143    /**
19144     * Transforms a motion event from view-local coordinates to on-screen
19145     * coordinates.
19146     *
19147     * @param ev the view-local motion event
19148     * @return false if the transformation could not be applied
19149     * @hide
19150     */
19151    public boolean toGlobalMotionEvent(MotionEvent ev) {
19152        final AttachInfo info = mAttachInfo;
19153        if (info == null) {
19154            return false;
19155        }
19156
19157        final Matrix m = info.mTmpMatrix;
19158        m.set(Matrix.IDENTITY_MATRIX);
19159        transformMatrixToGlobal(m);
19160        ev.transform(m);
19161        return true;
19162    }
19163
19164    /**
19165     * Transforms a motion event from on-screen coordinates to view-local
19166     * coordinates.
19167     *
19168     * @param ev the on-screen motion event
19169     * @return false if the transformation could not be applied
19170     * @hide
19171     */
19172    public boolean toLocalMotionEvent(MotionEvent ev) {
19173        final AttachInfo info = mAttachInfo;
19174        if (info == null) {
19175            return false;
19176        }
19177
19178        final Matrix m = info.mTmpMatrix;
19179        m.set(Matrix.IDENTITY_MATRIX);
19180        transformMatrixToLocal(m);
19181        ev.transform(m);
19182        return true;
19183    }
19184
19185    /**
19186     * Modifies the input matrix such that it maps view-local coordinates to
19187     * on-screen coordinates.
19188     *
19189     * @param m input matrix to modify
19190     * @hide
19191     */
19192    public void transformMatrixToGlobal(Matrix m) {
19193        final ViewParent parent = mParent;
19194        if (parent instanceof View) {
19195            final View vp = (View) parent;
19196            vp.transformMatrixToGlobal(m);
19197            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
19198        } else if (parent instanceof ViewRootImpl) {
19199            final ViewRootImpl vr = (ViewRootImpl) parent;
19200            vr.transformMatrixToGlobal(m);
19201            m.preTranslate(0, -vr.mCurScrollY);
19202        }
19203
19204        m.preTranslate(mLeft, mTop);
19205
19206        if (!hasIdentityMatrix()) {
19207            m.preConcat(getMatrix());
19208        }
19209    }
19210
19211    /**
19212     * Modifies the input matrix such that it maps on-screen coordinates to
19213     * view-local coordinates.
19214     *
19215     * @param m input matrix to modify
19216     * @hide
19217     */
19218    public void transformMatrixToLocal(Matrix m) {
19219        final ViewParent parent = mParent;
19220        if (parent instanceof View) {
19221            final View vp = (View) parent;
19222            vp.transformMatrixToLocal(m);
19223            m.postTranslate(vp.mScrollX, vp.mScrollY);
19224        } else if (parent instanceof ViewRootImpl) {
19225            final ViewRootImpl vr = (ViewRootImpl) parent;
19226            vr.transformMatrixToLocal(m);
19227            m.postTranslate(0, vr.mCurScrollY);
19228        }
19229
19230        m.postTranslate(-mLeft, -mTop);
19231
19232        if (!hasIdentityMatrix()) {
19233            m.postConcat(getInverseMatrix());
19234        }
19235    }
19236
19237    /**
19238     * @hide
19239     */
19240    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
19241            @ViewDebug.IntToString(from = 0, to = "x"),
19242            @ViewDebug.IntToString(from = 1, to = "y")
19243    })
19244    public int[] getLocationOnScreen() {
19245        int[] location = new int[2];
19246        getLocationOnScreen(location);
19247        return location;
19248    }
19249
19250    /**
19251     * <p>Computes the coordinates of this view on the screen. The argument
19252     * must be an array of two integers. After the method returns, the array
19253     * contains the x and y location in that order.</p>
19254     *
19255     * @param outLocation an array of two integers in which to hold the coordinates
19256     */
19257    public void getLocationOnScreen(@Size(2) int[] outLocation) {
19258        getLocationInWindow(outLocation);
19259
19260        final AttachInfo info = mAttachInfo;
19261        if (info != null) {
19262            outLocation[0] += info.mWindowLeft;
19263            outLocation[1] += info.mWindowTop;
19264        }
19265    }
19266
19267    /**
19268     * <p>Computes the coordinates of this view in its window. The argument
19269     * must be an array of two integers. After the method returns, the array
19270     * contains the x and y location in that order.</p>
19271     *
19272     * @param outLocation an array of two integers in which to hold the coordinates
19273     */
19274    public void getLocationInWindow(@Size(2) int[] outLocation) {
19275        if (outLocation == null || outLocation.length < 2) {
19276            throw new IllegalArgumentException("outLocation must be an array of two integers");
19277        }
19278
19279        outLocation[0] = 0;
19280        outLocation[1] = 0;
19281
19282        transformFromViewToWindowSpace(outLocation);
19283    }
19284
19285    /** @hide */
19286    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
19287        if (inOutLocation == null || inOutLocation.length < 2) {
19288            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
19289        }
19290
19291        if (mAttachInfo == null) {
19292            // When the view is not attached to a window, this method does not make sense
19293            inOutLocation[0] = inOutLocation[1] = 0;
19294            return;
19295        }
19296
19297        float position[] = mAttachInfo.mTmpTransformLocation;
19298        position[0] = inOutLocation[0];
19299        position[1] = inOutLocation[1];
19300
19301        if (!hasIdentityMatrix()) {
19302            getMatrix().mapPoints(position);
19303        }
19304
19305        position[0] += mLeft;
19306        position[1] += mTop;
19307
19308        ViewParent viewParent = mParent;
19309        while (viewParent instanceof View) {
19310            final View view = (View) viewParent;
19311
19312            position[0] -= view.mScrollX;
19313            position[1] -= view.mScrollY;
19314
19315            if (!view.hasIdentityMatrix()) {
19316                view.getMatrix().mapPoints(position);
19317            }
19318
19319            position[0] += view.mLeft;
19320            position[1] += view.mTop;
19321
19322            viewParent = view.mParent;
19323         }
19324
19325        if (viewParent instanceof ViewRootImpl) {
19326            // *cough*
19327            final ViewRootImpl vr = (ViewRootImpl) viewParent;
19328            position[1] -= vr.mCurScrollY;
19329        }
19330
19331        inOutLocation[0] = Math.round(position[0]);
19332        inOutLocation[1] = Math.round(position[1]);
19333    }
19334
19335    /**
19336     * {@hide}
19337     * @param id the id of the view to be found
19338     * @return the view of the specified id, null if cannot be found
19339     */
19340    protected View findViewTraversal(@IdRes int id) {
19341        if (id == mID) {
19342            return this;
19343        }
19344        return null;
19345    }
19346
19347    /**
19348     * {@hide}
19349     * @param tag the tag of the view to be found
19350     * @return the view of specified tag, null if cannot be found
19351     */
19352    protected View findViewWithTagTraversal(Object tag) {
19353        if (tag != null && tag.equals(mTag)) {
19354            return this;
19355        }
19356        return null;
19357    }
19358
19359    /**
19360     * {@hide}
19361     * @param predicate The predicate to evaluate.
19362     * @param childToSkip If not null, ignores this child during the recursive traversal.
19363     * @return The first view that matches the predicate or null.
19364     */
19365    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
19366        if (predicate.apply(this)) {
19367            return this;
19368        }
19369        return null;
19370    }
19371
19372    /**
19373     * Look for a child view with the given id.  If this view has the given
19374     * id, return this view.
19375     *
19376     * @param id The id to search for.
19377     * @return The view that has the given id in the hierarchy or null
19378     */
19379    @Nullable
19380    public final View findViewById(@IdRes int id) {
19381        if (id < 0) {
19382            return null;
19383        }
19384        return findViewTraversal(id);
19385    }
19386
19387    /**
19388     * Finds a view by its unuque and stable accessibility id.
19389     *
19390     * @param accessibilityId The searched accessibility id.
19391     * @return The found view.
19392     */
19393    final View findViewByAccessibilityId(int accessibilityId) {
19394        if (accessibilityId < 0) {
19395            return null;
19396        }
19397        View view = findViewByAccessibilityIdTraversal(accessibilityId);
19398        if (view != null) {
19399            return view.includeForAccessibility() ? view : null;
19400        }
19401        return null;
19402    }
19403
19404    /**
19405     * Performs the traversal to find a view by its unuque and stable accessibility id.
19406     *
19407     * <strong>Note:</strong>This method does not stop at the root namespace
19408     * boundary since the user can touch the screen at an arbitrary location
19409     * potentially crossing the root namespace bounday which will send an
19410     * accessibility event to accessibility services and they should be able
19411     * to obtain the event source. Also accessibility ids are guaranteed to be
19412     * unique in the window.
19413     *
19414     * @param accessibilityId The accessibility id.
19415     * @return The found view.
19416     *
19417     * @hide
19418     */
19419    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
19420        if (getAccessibilityViewId() == accessibilityId) {
19421            return this;
19422        }
19423        return null;
19424    }
19425
19426    /**
19427     * Look for a child view with the given tag.  If this view has the given
19428     * tag, return this view.
19429     *
19430     * @param tag The tag to search for, using "tag.equals(getTag())".
19431     * @return The View that has the given tag in the hierarchy or null
19432     */
19433    public final View findViewWithTag(Object tag) {
19434        if (tag == null) {
19435            return null;
19436        }
19437        return findViewWithTagTraversal(tag);
19438    }
19439
19440    /**
19441     * {@hide}
19442     * Look for a child view that matches the specified predicate.
19443     * If this view matches the predicate, return this view.
19444     *
19445     * @param predicate The predicate to evaluate.
19446     * @return The first view that matches the predicate or null.
19447     */
19448    public final View findViewByPredicate(Predicate<View> predicate) {
19449        return findViewByPredicateTraversal(predicate, null);
19450    }
19451
19452    /**
19453     * {@hide}
19454     * Look for a child view that matches the specified predicate,
19455     * starting with the specified view and its descendents and then
19456     * recusively searching the ancestors and siblings of that view
19457     * until this view is reached.
19458     *
19459     * This method is useful in cases where the predicate does not match
19460     * a single unique view (perhaps multiple views use the same id)
19461     * and we are trying to find the view that is "closest" in scope to the
19462     * starting view.
19463     *
19464     * @param start The view to start from.
19465     * @param predicate The predicate to evaluate.
19466     * @return The first view that matches the predicate or null.
19467     */
19468    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
19469        View childToSkip = null;
19470        for (;;) {
19471            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
19472            if (view != null || start == this) {
19473                return view;
19474            }
19475
19476            ViewParent parent = start.getParent();
19477            if (parent == null || !(parent instanceof View)) {
19478                return null;
19479            }
19480
19481            childToSkip = start;
19482            start = (View) parent;
19483        }
19484    }
19485
19486    /**
19487     * Sets the identifier for this view. The identifier does not have to be
19488     * unique in this view's hierarchy. The identifier should be a positive
19489     * number.
19490     *
19491     * @see #NO_ID
19492     * @see #getId()
19493     * @see #findViewById(int)
19494     *
19495     * @param id a number used to identify the view
19496     *
19497     * @attr ref android.R.styleable#View_id
19498     */
19499    public void setId(@IdRes int id) {
19500        mID = id;
19501        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
19502            mID = generateViewId();
19503        }
19504    }
19505
19506    /**
19507     * {@hide}
19508     *
19509     * @param isRoot true if the view belongs to the root namespace, false
19510     *        otherwise
19511     */
19512    public void setIsRootNamespace(boolean isRoot) {
19513        if (isRoot) {
19514            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
19515        } else {
19516            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
19517        }
19518    }
19519
19520    /**
19521     * {@hide}
19522     *
19523     * @return true if the view belongs to the root namespace, false otherwise
19524     */
19525    public boolean isRootNamespace() {
19526        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
19527    }
19528
19529    /**
19530     * Returns this view's identifier.
19531     *
19532     * @return a positive integer used to identify the view or {@link #NO_ID}
19533     *         if the view has no ID
19534     *
19535     * @see #setId(int)
19536     * @see #findViewById(int)
19537     * @attr ref android.R.styleable#View_id
19538     */
19539    @IdRes
19540    @ViewDebug.CapturedViewProperty
19541    public int getId() {
19542        return mID;
19543    }
19544
19545    /**
19546     * Returns this view's tag.
19547     *
19548     * @return the Object stored in this view as a tag, or {@code null} if not
19549     *         set
19550     *
19551     * @see #setTag(Object)
19552     * @see #getTag(int)
19553     */
19554    @ViewDebug.ExportedProperty
19555    public Object getTag() {
19556        return mTag;
19557    }
19558
19559    /**
19560     * Sets the tag associated with this view. A tag can be used to mark
19561     * a view in its hierarchy and does not have to be unique within the
19562     * hierarchy. Tags can also be used to store data within a view without
19563     * resorting to another data structure.
19564     *
19565     * @param tag an Object to tag the view with
19566     *
19567     * @see #getTag()
19568     * @see #setTag(int, Object)
19569     */
19570    public void setTag(final Object tag) {
19571        mTag = tag;
19572    }
19573
19574    /**
19575     * Returns the tag associated with this view and the specified key.
19576     *
19577     * @param key The key identifying the tag
19578     *
19579     * @return the Object stored in this view as a tag, or {@code null} if not
19580     *         set
19581     *
19582     * @see #setTag(int, Object)
19583     * @see #getTag()
19584     */
19585    public Object getTag(int key) {
19586        if (mKeyedTags != null) return mKeyedTags.get(key);
19587        return null;
19588    }
19589
19590    /**
19591     * Sets a tag associated with this view and a key. A tag can be used
19592     * to mark a view in its hierarchy and does not have to be unique within
19593     * the hierarchy. Tags can also be used to store data within a view
19594     * without resorting to another data structure.
19595     *
19596     * The specified key should be an id declared in the resources of the
19597     * application to ensure it is unique (see the <a
19598     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
19599     * Keys identified as belonging to
19600     * the Android framework or not associated with any package will cause
19601     * an {@link IllegalArgumentException} to be thrown.
19602     *
19603     * @param key The key identifying the tag
19604     * @param tag An Object to tag the view with
19605     *
19606     * @throws IllegalArgumentException If they specified key is not valid
19607     *
19608     * @see #setTag(Object)
19609     * @see #getTag(int)
19610     */
19611    public void setTag(int key, final Object tag) {
19612        // If the package id is 0x00 or 0x01, it's either an undefined package
19613        // or a framework id
19614        if ((key >>> 24) < 2) {
19615            throw new IllegalArgumentException("The key must be an application-specific "
19616                    + "resource id.");
19617        }
19618
19619        setKeyedTag(key, tag);
19620    }
19621
19622    /**
19623     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
19624     * framework id.
19625     *
19626     * @hide
19627     */
19628    public void setTagInternal(int key, Object tag) {
19629        if ((key >>> 24) != 0x1) {
19630            throw new IllegalArgumentException("The key must be a framework-specific "
19631                    + "resource id.");
19632        }
19633
19634        setKeyedTag(key, tag);
19635    }
19636
19637    private void setKeyedTag(int key, Object tag) {
19638        if (mKeyedTags == null) {
19639            mKeyedTags = new SparseArray<Object>(2);
19640        }
19641
19642        mKeyedTags.put(key, tag);
19643    }
19644
19645    /**
19646     * Prints information about this view in the log output, with the tag
19647     * {@link #VIEW_LOG_TAG}.
19648     *
19649     * @hide
19650     */
19651    public void debug() {
19652        debug(0);
19653    }
19654
19655    /**
19656     * Prints information about this view in the log output, with the tag
19657     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
19658     * indentation defined by the <code>depth</code>.
19659     *
19660     * @param depth the indentation level
19661     *
19662     * @hide
19663     */
19664    protected void debug(int depth) {
19665        String output = debugIndent(depth - 1);
19666
19667        output += "+ " + this;
19668        int id = getId();
19669        if (id != -1) {
19670            output += " (id=" + id + ")";
19671        }
19672        Object tag = getTag();
19673        if (tag != null) {
19674            output += " (tag=" + tag + ")";
19675        }
19676        Log.d(VIEW_LOG_TAG, output);
19677
19678        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
19679            output = debugIndent(depth) + " FOCUSED";
19680            Log.d(VIEW_LOG_TAG, output);
19681        }
19682
19683        output = debugIndent(depth);
19684        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
19685                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
19686                + "} ";
19687        Log.d(VIEW_LOG_TAG, output);
19688
19689        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
19690                || mPaddingBottom != 0) {
19691            output = debugIndent(depth);
19692            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
19693                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
19694            Log.d(VIEW_LOG_TAG, output);
19695        }
19696
19697        output = debugIndent(depth);
19698        output += "mMeasureWidth=" + mMeasuredWidth +
19699                " mMeasureHeight=" + mMeasuredHeight;
19700        Log.d(VIEW_LOG_TAG, output);
19701
19702        output = debugIndent(depth);
19703        if (mLayoutParams == null) {
19704            output += "BAD! no layout params";
19705        } else {
19706            output = mLayoutParams.debug(output);
19707        }
19708        Log.d(VIEW_LOG_TAG, output);
19709
19710        output = debugIndent(depth);
19711        output += "flags={";
19712        output += View.printFlags(mViewFlags);
19713        output += "}";
19714        Log.d(VIEW_LOG_TAG, output);
19715
19716        output = debugIndent(depth);
19717        output += "privateFlags={";
19718        output += View.printPrivateFlags(mPrivateFlags);
19719        output += "}";
19720        Log.d(VIEW_LOG_TAG, output);
19721    }
19722
19723    /**
19724     * Creates a string of whitespaces used for indentation.
19725     *
19726     * @param depth the indentation level
19727     * @return a String containing (depth * 2 + 3) * 2 white spaces
19728     *
19729     * @hide
19730     */
19731    protected static String debugIndent(int depth) {
19732        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
19733        for (int i = 0; i < (depth * 2) + 3; i++) {
19734            spaces.append(' ').append(' ');
19735        }
19736        return spaces.toString();
19737    }
19738
19739    /**
19740     * <p>Return the offset of the widget's text baseline from the widget's top
19741     * boundary. If this widget does not support baseline alignment, this
19742     * method returns -1. </p>
19743     *
19744     * @return the offset of the baseline within the widget's bounds or -1
19745     *         if baseline alignment is not supported
19746     */
19747    @ViewDebug.ExportedProperty(category = "layout")
19748    public int getBaseline() {
19749        return -1;
19750    }
19751
19752    /**
19753     * Returns whether the view hierarchy is currently undergoing a layout pass. This
19754     * information is useful to avoid situations such as calling {@link #requestLayout()} during
19755     * a layout pass.
19756     *
19757     * @return whether the view hierarchy is currently undergoing a layout pass
19758     */
19759    public boolean isInLayout() {
19760        ViewRootImpl viewRoot = getViewRootImpl();
19761        return (viewRoot != null && viewRoot.isInLayout());
19762    }
19763
19764    /**
19765     * Call this when something has changed which has invalidated the
19766     * layout of this view. This will schedule a layout pass of the view
19767     * tree. This should not be called while the view hierarchy is currently in a layout
19768     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
19769     * end of the current layout pass (and then layout will run again) or after the current
19770     * frame is drawn and the next layout occurs.
19771     *
19772     * <p>Subclasses which override this method should call the superclass method to
19773     * handle possible request-during-layout errors correctly.</p>
19774     */
19775    @CallSuper
19776    public void requestLayout() {
19777        if (mMeasureCache != null) mMeasureCache.clear();
19778
19779        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
19780            // Only trigger request-during-layout logic if this is the view requesting it,
19781            // not the views in its parent hierarchy
19782            ViewRootImpl viewRoot = getViewRootImpl();
19783            if (viewRoot != null && viewRoot.isInLayout()) {
19784                if (!viewRoot.requestLayoutDuringLayout(this)) {
19785                    return;
19786                }
19787            }
19788            mAttachInfo.mViewRequestingLayout = this;
19789        }
19790
19791        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19792        mPrivateFlags |= PFLAG_INVALIDATED;
19793
19794        if (mParent != null && !mParent.isLayoutRequested()) {
19795            mParent.requestLayout();
19796        }
19797        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
19798            mAttachInfo.mViewRequestingLayout = null;
19799        }
19800    }
19801
19802    /**
19803     * Forces this view to be laid out during the next layout pass.
19804     * This method does not call requestLayout() or forceLayout()
19805     * on the parent.
19806     */
19807    public void forceLayout() {
19808        if (mMeasureCache != null) mMeasureCache.clear();
19809
19810        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19811        mPrivateFlags |= PFLAG_INVALIDATED;
19812    }
19813
19814    /**
19815     * <p>
19816     * This is called to find out how big a view should be. The parent
19817     * supplies constraint information in the width and height parameters.
19818     * </p>
19819     *
19820     * <p>
19821     * The actual measurement work of a view is performed in
19822     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
19823     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
19824     * </p>
19825     *
19826     *
19827     * @param widthMeasureSpec Horizontal space requirements as imposed by the
19828     *        parent
19829     * @param heightMeasureSpec Vertical space requirements as imposed by the
19830     *        parent
19831     *
19832     * @see #onMeasure(int, int)
19833     */
19834    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
19835        boolean optical = isLayoutModeOptical(this);
19836        if (optical != isLayoutModeOptical(mParent)) {
19837            Insets insets = getOpticalInsets();
19838            int oWidth  = insets.left + insets.right;
19839            int oHeight = insets.top  + insets.bottom;
19840            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
19841            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
19842        }
19843
19844        // Suppress sign extension for the low bytes
19845        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
19846        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
19847
19848        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19849
19850        // Optimize layout by avoiding an extra EXACTLY pass when the view is
19851        // already measured as the correct size. In API 23 and below, this
19852        // extra pass is required to make LinearLayout re-distribute weight.
19853        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
19854                || heightMeasureSpec != mOldHeightMeasureSpec;
19855        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
19856                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
19857        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
19858                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
19859        final boolean needsLayout = specChanged
19860                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
19861
19862        if (forceLayout || needsLayout) {
19863            // first clears the measured dimension flag
19864            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
19865
19866            resolveRtlPropertiesIfNeeded();
19867
19868            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
19869            if (cacheIndex < 0 || sIgnoreMeasureCache) {
19870                // measure ourselves, this should set the measured dimension flag back
19871                onMeasure(widthMeasureSpec, heightMeasureSpec);
19872                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19873            } else {
19874                long value = mMeasureCache.valueAt(cacheIndex);
19875                // Casting a long to int drops the high 32 bits, no mask needed
19876                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
19877                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19878            }
19879
19880            // flag not set, setMeasuredDimension() was not invoked, we raise
19881            // an exception to warn the developer
19882            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
19883                throw new IllegalStateException("View with id " + getId() + ": "
19884                        + getClass().getName() + "#onMeasure() did not set the"
19885                        + " measured dimension by calling"
19886                        + " setMeasuredDimension()");
19887            }
19888
19889            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
19890        }
19891
19892        mOldWidthMeasureSpec = widthMeasureSpec;
19893        mOldHeightMeasureSpec = heightMeasureSpec;
19894
19895        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
19896                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
19897    }
19898
19899    /**
19900     * <p>
19901     * Measure the view and its content to determine the measured width and the
19902     * measured height. This method is invoked by {@link #measure(int, int)} and
19903     * should be overridden by subclasses to provide accurate and efficient
19904     * measurement of their contents.
19905     * </p>
19906     *
19907     * <p>
19908     * <strong>CONTRACT:</strong> When overriding this method, you
19909     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
19910     * measured width and height of this view. Failure to do so will trigger an
19911     * <code>IllegalStateException</code>, thrown by
19912     * {@link #measure(int, int)}. Calling the superclass'
19913     * {@link #onMeasure(int, int)} is a valid use.
19914     * </p>
19915     *
19916     * <p>
19917     * The base class implementation of measure defaults to the background size,
19918     * unless a larger size is allowed by the MeasureSpec. Subclasses should
19919     * override {@link #onMeasure(int, int)} to provide better measurements of
19920     * their content.
19921     * </p>
19922     *
19923     * <p>
19924     * If this method is overridden, it is the subclass's responsibility to make
19925     * sure the measured height and width are at least the view's minimum height
19926     * and width ({@link #getSuggestedMinimumHeight()} and
19927     * {@link #getSuggestedMinimumWidth()}).
19928     * </p>
19929     *
19930     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
19931     *                         The requirements are encoded with
19932     *                         {@link android.view.View.MeasureSpec}.
19933     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19934     *                         The requirements are encoded with
19935     *                         {@link android.view.View.MeasureSpec}.
19936     *
19937     * @see #getMeasuredWidth()
19938     * @see #getMeasuredHeight()
19939     * @see #setMeasuredDimension(int, int)
19940     * @see #getSuggestedMinimumHeight()
19941     * @see #getSuggestedMinimumWidth()
19942     * @see android.view.View.MeasureSpec#getMode(int)
19943     * @see android.view.View.MeasureSpec#getSize(int)
19944     */
19945    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19946        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19947                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19948    }
19949
19950    /**
19951     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19952     * measured width and measured height. Failing to do so will trigger an
19953     * exception at measurement time.</p>
19954     *
19955     * @param measuredWidth The measured width of this view.  May be a complex
19956     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19957     * {@link #MEASURED_STATE_TOO_SMALL}.
19958     * @param measuredHeight The measured height of this view.  May be a complex
19959     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19960     * {@link #MEASURED_STATE_TOO_SMALL}.
19961     */
19962    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19963        boolean optical = isLayoutModeOptical(this);
19964        if (optical != isLayoutModeOptical(mParent)) {
19965            Insets insets = getOpticalInsets();
19966            int opticalWidth  = insets.left + insets.right;
19967            int opticalHeight = insets.top  + insets.bottom;
19968
19969            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
19970            measuredHeight += optical ? opticalHeight : -opticalHeight;
19971        }
19972        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19973    }
19974
19975    /**
19976     * Sets the measured dimension without extra processing for things like optical bounds.
19977     * Useful for reapplying consistent values that have already been cooked with adjustments
19978     * for optical bounds, etc. such as those from the measurement cache.
19979     *
19980     * @param measuredWidth The measured width of this view.  May be a complex
19981     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19982     * {@link #MEASURED_STATE_TOO_SMALL}.
19983     * @param measuredHeight The measured height of this view.  May be a complex
19984     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19985     * {@link #MEASURED_STATE_TOO_SMALL}.
19986     */
19987    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19988        mMeasuredWidth = measuredWidth;
19989        mMeasuredHeight = measuredHeight;
19990
19991        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19992    }
19993
19994    /**
19995     * Merge two states as returned by {@link #getMeasuredState()}.
19996     * @param curState The current state as returned from a view or the result
19997     * of combining multiple views.
19998     * @param newState The new view state to combine.
19999     * @return Returns a new integer reflecting the combination of the two
20000     * states.
20001     */
20002    public static int combineMeasuredStates(int curState, int newState) {
20003        return curState | newState;
20004    }
20005
20006    /**
20007     * Version of {@link #resolveSizeAndState(int, int, int)}
20008     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
20009     */
20010    public static int resolveSize(int size, int measureSpec) {
20011        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
20012    }
20013
20014    /**
20015     * Utility to reconcile a desired size and state, with constraints imposed
20016     * by a MeasureSpec. Will take the desired size, unless a different size
20017     * is imposed by the constraints. The returned value is a compound integer,
20018     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
20019     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
20020     * resulting size is smaller than the size the view wants to be.
20021     *
20022     * @param size How big the view wants to be.
20023     * @param measureSpec Constraints imposed by the parent.
20024     * @param childMeasuredState Size information bit mask for the view's
20025     *                           children.
20026     * @return Size information bit mask as defined by
20027     *         {@link #MEASURED_SIZE_MASK} and
20028     *         {@link #MEASURED_STATE_TOO_SMALL}.
20029     */
20030    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
20031        final int specMode = MeasureSpec.getMode(measureSpec);
20032        final int specSize = MeasureSpec.getSize(measureSpec);
20033        final int result;
20034        switch (specMode) {
20035            case MeasureSpec.AT_MOST:
20036                if (specSize < size) {
20037                    result = specSize | MEASURED_STATE_TOO_SMALL;
20038                } else {
20039                    result = size;
20040                }
20041                break;
20042            case MeasureSpec.EXACTLY:
20043                result = specSize;
20044                break;
20045            case MeasureSpec.UNSPECIFIED:
20046            default:
20047                result = size;
20048        }
20049        return result | (childMeasuredState & MEASURED_STATE_MASK);
20050    }
20051
20052    /**
20053     * Utility to return a default size. Uses the supplied size if the
20054     * MeasureSpec imposed no constraints. Will get larger if allowed
20055     * by the MeasureSpec.
20056     *
20057     * @param size Default size for this view
20058     * @param measureSpec Constraints imposed by the parent
20059     * @return The size this view should be.
20060     */
20061    public static int getDefaultSize(int size, int measureSpec) {
20062        int result = size;
20063        int specMode = MeasureSpec.getMode(measureSpec);
20064        int specSize = MeasureSpec.getSize(measureSpec);
20065
20066        switch (specMode) {
20067        case MeasureSpec.UNSPECIFIED:
20068            result = size;
20069            break;
20070        case MeasureSpec.AT_MOST:
20071        case MeasureSpec.EXACTLY:
20072            result = specSize;
20073            break;
20074        }
20075        return result;
20076    }
20077
20078    /**
20079     * Returns the suggested minimum height that the view should use. This
20080     * returns the maximum of the view's minimum height
20081     * and the background's minimum height
20082     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
20083     * <p>
20084     * When being used in {@link #onMeasure(int, int)}, the caller should still
20085     * ensure the returned height is within the requirements of the parent.
20086     *
20087     * @return The suggested minimum height of the view.
20088     */
20089    protected int getSuggestedMinimumHeight() {
20090        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
20091
20092    }
20093
20094    /**
20095     * Returns the suggested minimum width that the view should use. This
20096     * returns the maximum of the view's minimum width
20097     * and the background's minimum width
20098     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
20099     * <p>
20100     * When being used in {@link #onMeasure(int, int)}, the caller should still
20101     * ensure the returned width is within the requirements of the parent.
20102     *
20103     * @return The suggested minimum width of the view.
20104     */
20105    protected int getSuggestedMinimumWidth() {
20106        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
20107    }
20108
20109    /**
20110     * Returns the minimum height of the view.
20111     *
20112     * @return the minimum height the view will try to be.
20113     *
20114     * @see #setMinimumHeight(int)
20115     *
20116     * @attr ref android.R.styleable#View_minHeight
20117     */
20118    public int getMinimumHeight() {
20119        return mMinHeight;
20120    }
20121
20122    /**
20123     * Sets the minimum height of the view. It is not guaranteed the view will
20124     * be able to achieve this minimum height (for example, if its parent layout
20125     * constrains it with less available height).
20126     *
20127     * @param minHeight The minimum height the view will try to be.
20128     *
20129     * @see #getMinimumHeight()
20130     *
20131     * @attr ref android.R.styleable#View_minHeight
20132     */
20133    @RemotableViewMethod
20134    public void setMinimumHeight(int minHeight) {
20135        mMinHeight = minHeight;
20136        requestLayout();
20137    }
20138
20139    /**
20140     * Returns the minimum width of the view.
20141     *
20142     * @return the minimum width the view will try to be.
20143     *
20144     * @see #setMinimumWidth(int)
20145     *
20146     * @attr ref android.R.styleable#View_minWidth
20147     */
20148    public int getMinimumWidth() {
20149        return mMinWidth;
20150    }
20151
20152    /**
20153     * Sets the minimum width of the view. It is not guaranteed the view will
20154     * be able to achieve this minimum width (for example, if its parent layout
20155     * constrains it with less available width).
20156     *
20157     * @param minWidth The minimum width the view will try to be.
20158     *
20159     * @see #getMinimumWidth()
20160     *
20161     * @attr ref android.R.styleable#View_minWidth
20162     */
20163    public void setMinimumWidth(int minWidth) {
20164        mMinWidth = minWidth;
20165        requestLayout();
20166
20167    }
20168
20169    /**
20170     * Get the animation currently associated with this view.
20171     *
20172     * @return The animation that is currently playing or
20173     *         scheduled to play for this view.
20174     */
20175    public Animation getAnimation() {
20176        return mCurrentAnimation;
20177    }
20178
20179    /**
20180     * Start the specified animation now.
20181     *
20182     * @param animation the animation to start now
20183     */
20184    public void startAnimation(Animation animation) {
20185        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
20186        setAnimation(animation);
20187        invalidateParentCaches();
20188        invalidate(true);
20189    }
20190
20191    /**
20192     * Cancels any animations for this view.
20193     */
20194    public void clearAnimation() {
20195        if (mCurrentAnimation != null) {
20196            mCurrentAnimation.detach();
20197        }
20198        mCurrentAnimation = null;
20199        invalidateParentIfNeeded();
20200    }
20201
20202    /**
20203     * Sets the next animation to play for this view.
20204     * If you want the animation to play immediately, use
20205     * {@link #startAnimation(android.view.animation.Animation)} instead.
20206     * This method provides allows fine-grained
20207     * control over the start time and invalidation, but you
20208     * must make sure that 1) the animation has a start time set, and
20209     * 2) the view's parent (which controls animations on its children)
20210     * will be invalidated when the animation is supposed to
20211     * start.
20212     *
20213     * @param animation The next animation, or null.
20214     */
20215    public void setAnimation(Animation animation) {
20216        mCurrentAnimation = animation;
20217
20218        if (animation != null) {
20219            // If the screen is off assume the animation start time is now instead of
20220            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
20221            // would cause the animation to start when the screen turns back on
20222            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
20223                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
20224                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
20225            }
20226            animation.reset();
20227        }
20228    }
20229
20230    /**
20231     * Invoked by a parent ViewGroup to notify the start of the animation
20232     * currently associated with this view. If you override this method,
20233     * always call super.onAnimationStart();
20234     *
20235     * @see #setAnimation(android.view.animation.Animation)
20236     * @see #getAnimation()
20237     */
20238    @CallSuper
20239    protected void onAnimationStart() {
20240        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
20241    }
20242
20243    /**
20244     * Invoked by a parent ViewGroup to notify the end of the animation
20245     * currently associated with this view. If you override this method,
20246     * always call super.onAnimationEnd();
20247     *
20248     * @see #setAnimation(android.view.animation.Animation)
20249     * @see #getAnimation()
20250     */
20251    @CallSuper
20252    protected void onAnimationEnd() {
20253        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
20254    }
20255
20256    /**
20257     * Invoked if there is a Transform that involves alpha. Subclass that can
20258     * draw themselves with the specified alpha should return true, and then
20259     * respect that alpha when their onDraw() is called. If this returns false
20260     * then the view may be redirected to draw into an offscreen buffer to
20261     * fulfill the request, which will look fine, but may be slower than if the
20262     * subclass handles it internally. The default implementation returns false.
20263     *
20264     * @param alpha The alpha (0..255) to apply to the view's drawing
20265     * @return true if the view can draw with the specified alpha.
20266     */
20267    protected boolean onSetAlpha(int alpha) {
20268        return false;
20269    }
20270
20271    /**
20272     * This is used by the RootView to perform an optimization when
20273     * the view hierarchy contains one or several SurfaceView.
20274     * SurfaceView is always considered transparent, but its children are not,
20275     * therefore all View objects remove themselves from the global transparent
20276     * region (passed as a parameter to this function).
20277     *
20278     * @param region The transparent region for this ViewAncestor (window).
20279     *
20280     * @return Returns true if the effective visibility of the view at this
20281     * point is opaque, regardless of the transparent region; returns false
20282     * if it is possible for underlying windows to be seen behind the view.
20283     *
20284     * {@hide}
20285     */
20286    public boolean gatherTransparentRegion(Region region) {
20287        final AttachInfo attachInfo = mAttachInfo;
20288        if (region != null && attachInfo != null) {
20289            final int pflags = mPrivateFlags;
20290            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
20291                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
20292                // remove it from the transparent region.
20293                final int[] location = attachInfo.mTransparentLocation;
20294                getLocationInWindow(location);
20295                // When a view has Z value, then it will be better to leave some area below the view
20296                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
20297                // the bottom part needs more offset than the left, top and right parts due to the
20298                // spot light effects.
20299                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
20300                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
20301                        location[0] + mRight - mLeft + shadowOffset,
20302                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
20303            } else {
20304                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
20305                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
20306                    // the background drawable's non-transparent parts from this transparent region.
20307                    applyDrawableToTransparentRegion(mBackground, region);
20308                }
20309                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20310                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
20311                    // Similarly, we remove the foreground drawable's non-transparent parts.
20312                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
20313                }
20314            }
20315        }
20316        return true;
20317    }
20318
20319    /**
20320     * Play a sound effect for this view.
20321     *
20322     * <p>The framework will play sound effects for some built in actions, such as
20323     * clicking, but you may wish to play these effects in your widget,
20324     * for instance, for internal navigation.
20325     *
20326     * <p>The sound effect will only be played if sound effects are enabled by the user, and
20327     * {@link #isSoundEffectsEnabled()} is true.
20328     *
20329     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
20330     */
20331    public void playSoundEffect(int soundConstant) {
20332        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
20333            return;
20334        }
20335        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
20336    }
20337
20338    /**
20339     * BZZZTT!!1!
20340     *
20341     * <p>Provide haptic feedback to the user for this view.
20342     *
20343     * <p>The framework will provide haptic feedback for some built in actions,
20344     * such as long presses, but you may wish to provide feedback for your
20345     * own widget.
20346     *
20347     * <p>The feedback will only be performed if
20348     * {@link #isHapticFeedbackEnabled()} is true.
20349     *
20350     * @param feedbackConstant One of the constants defined in
20351     * {@link HapticFeedbackConstants}
20352     */
20353    public boolean performHapticFeedback(int feedbackConstant) {
20354        return performHapticFeedback(feedbackConstant, 0);
20355    }
20356
20357    /**
20358     * BZZZTT!!1!
20359     *
20360     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
20361     *
20362     * @param feedbackConstant One of the constants defined in
20363     * {@link HapticFeedbackConstants}
20364     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
20365     */
20366    public boolean performHapticFeedback(int feedbackConstant, int flags) {
20367        if (mAttachInfo == null) {
20368            return false;
20369        }
20370        //noinspection SimplifiableIfStatement
20371        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
20372                && !isHapticFeedbackEnabled()) {
20373            return false;
20374        }
20375        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
20376                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
20377    }
20378
20379    /**
20380     * Request that the visibility of the status bar or other screen/window
20381     * decorations be changed.
20382     *
20383     * <p>This method is used to put the over device UI into temporary modes
20384     * where the user's attention is focused more on the application content,
20385     * by dimming or hiding surrounding system affordances.  This is typically
20386     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
20387     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
20388     * to be placed behind the action bar (and with these flags other system
20389     * affordances) so that smooth transitions between hiding and showing them
20390     * can be done.
20391     *
20392     * <p>Two representative examples of the use of system UI visibility is
20393     * implementing a content browsing application (like a magazine reader)
20394     * and a video playing application.
20395     *
20396     * <p>The first code shows a typical implementation of a View in a content
20397     * browsing application.  In this implementation, the application goes
20398     * into a content-oriented mode by hiding the status bar and action bar,
20399     * and putting the navigation elements into lights out mode.  The user can
20400     * then interact with content while in this mode.  Such an application should
20401     * provide an easy way for the user to toggle out of the mode (such as to
20402     * check information in the status bar or access notifications).  In the
20403     * implementation here, this is done simply by tapping on the content.
20404     *
20405     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
20406     *      content}
20407     *
20408     * <p>This second code sample shows a typical implementation of a View
20409     * in a video playing application.  In this situation, while the video is
20410     * playing the application would like to go into a complete full-screen mode,
20411     * to use as much of the display as possible for the video.  When in this state
20412     * the user can not interact with the application; the system intercepts
20413     * touching on the screen to pop the UI out of full screen mode.  See
20414     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
20415     *
20416     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
20417     *      content}
20418     *
20419     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20420     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20421     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20422     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20423     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20424     */
20425    public void setSystemUiVisibility(int visibility) {
20426        if (visibility != mSystemUiVisibility) {
20427            mSystemUiVisibility = visibility;
20428            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20429                mParent.recomputeViewAttributes(this);
20430            }
20431        }
20432    }
20433
20434    /**
20435     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
20436     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20437     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20438     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20439     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20440     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20441     */
20442    public int getSystemUiVisibility() {
20443        return mSystemUiVisibility;
20444    }
20445
20446    /**
20447     * Returns the current system UI visibility that is currently set for
20448     * the entire window.  This is the combination of the
20449     * {@link #setSystemUiVisibility(int)} values supplied by all of the
20450     * views in the window.
20451     */
20452    public int getWindowSystemUiVisibility() {
20453        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
20454    }
20455
20456    /**
20457     * Override to find out when the window's requested system UI visibility
20458     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
20459     * This is different from the callbacks received through
20460     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
20461     * in that this is only telling you about the local request of the window,
20462     * not the actual values applied by the system.
20463     */
20464    public void onWindowSystemUiVisibilityChanged(int visible) {
20465    }
20466
20467    /**
20468     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
20469     * the view hierarchy.
20470     */
20471    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
20472        onWindowSystemUiVisibilityChanged(visible);
20473    }
20474
20475    /**
20476     * Set a listener to receive callbacks when the visibility of the system bar changes.
20477     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
20478     */
20479    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
20480        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
20481        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20482            mParent.recomputeViewAttributes(this);
20483        }
20484    }
20485
20486    /**
20487     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
20488     * the view hierarchy.
20489     */
20490    public void dispatchSystemUiVisibilityChanged(int visibility) {
20491        ListenerInfo li = mListenerInfo;
20492        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
20493            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
20494                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
20495        }
20496    }
20497
20498    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
20499        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
20500        if (val != mSystemUiVisibility) {
20501            setSystemUiVisibility(val);
20502            return true;
20503        }
20504        return false;
20505    }
20506
20507    /** @hide */
20508    public void setDisabledSystemUiVisibility(int flags) {
20509        if (mAttachInfo != null) {
20510            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
20511                mAttachInfo.mDisabledSystemUiVisibility = flags;
20512                if (mParent != null) {
20513                    mParent.recomputeViewAttributes(this);
20514                }
20515            }
20516        }
20517    }
20518
20519    /**
20520     * Creates an image that the system displays during the drag and drop
20521     * operation. This is called a &quot;drag shadow&quot;. The default implementation
20522     * for a DragShadowBuilder based on a View returns an image that has exactly the same
20523     * appearance as the given View. The default also positions the center of the drag shadow
20524     * directly under the touch point. If no View is provided (the constructor with no parameters
20525     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
20526     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
20527     * default is an invisible drag shadow.
20528     * <p>
20529     * You are not required to use the View you provide to the constructor as the basis of the
20530     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
20531     * anything you want as the drag shadow.
20532     * </p>
20533     * <p>
20534     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
20535     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
20536     *  size and position of the drag shadow. It uses this data to construct a
20537     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
20538     *  so that your application can draw the shadow image in the Canvas.
20539     * </p>
20540     *
20541     * <div class="special reference">
20542     * <h3>Developer Guides</h3>
20543     * <p>For a guide to implementing drag and drop features, read the
20544     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20545     * </div>
20546     */
20547    public static class DragShadowBuilder {
20548        private final WeakReference<View> mView;
20549
20550        /**
20551         * Constructs a shadow image builder based on a View. By default, the resulting drag
20552         * shadow will have the same appearance and dimensions as the View, with the touch point
20553         * over the center of the View.
20554         * @param view A View. Any View in scope can be used.
20555         */
20556        public DragShadowBuilder(View view) {
20557            mView = new WeakReference<View>(view);
20558        }
20559
20560        /**
20561         * Construct a shadow builder object with no associated View.  This
20562         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
20563         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
20564         * to supply the drag shadow's dimensions and appearance without
20565         * reference to any View object. If they are not overridden, then the result is an
20566         * invisible drag shadow.
20567         */
20568        public DragShadowBuilder() {
20569            mView = new WeakReference<View>(null);
20570        }
20571
20572        /**
20573         * Returns the View object that had been passed to the
20574         * {@link #View.DragShadowBuilder(View)}
20575         * constructor.  If that View parameter was {@code null} or if the
20576         * {@link #View.DragShadowBuilder()}
20577         * constructor was used to instantiate the builder object, this method will return
20578         * null.
20579         *
20580         * @return The View object associate with this builder object.
20581         */
20582        @SuppressWarnings({"JavadocReference"})
20583        final public View getView() {
20584            return mView.get();
20585        }
20586
20587        /**
20588         * Provides the metrics for the shadow image. These include the dimensions of
20589         * the shadow image, and the point within that shadow that should
20590         * be centered under the touch location while dragging.
20591         * <p>
20592         * The default implementation sets the dimensions of the shadow to be the
20593         * same as the dimensions of the View itself and centers the shadow under
20594         * the touch point.
20595         * </p>
20596         *
20597         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
20598         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
20599         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
20600         * image.
20601         *
20602         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
20603         * shadow image that should be underneath the touch point during the drag and drop
20604         * operation. Your application must set {@link android.graphics.Point#x} to the
20605         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
20606         */
20607        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
20608            final View view = mView.get();
20609            if (view != null) {
20610                outShadowSize.set(view.getWidth(), view.getHeight());
20611                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
20612            } else {
20613                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
20614            }
20615        }
20616
20617        /**
20618         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
20619         * based on the dimensions it received from the
20620         * {@link #onProvideShadowMetrics(Point, Point)} callback.
20621         *
20622         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
20623         */
20624        public void onDrawShadow(Canvas canvas) {
20625            final View view = mView.get();
20626            if (view != null) {
20627                view.draw(canvas);
20628            } else {
20629                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
20630            }
20631        }
20632    }
20633
20634    /**
20635     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
20636     * startDragAndDrop()} for newer platform versions.
20637     */
20638    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
20639                                   Object myLocalState, int flags) {
20640        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
20641    }
20642
20643    /**
20644     * Starts a drag and drop operation. When your application calls this method, it passes a
20645     * {@link android.view.View.DragShadowBuilder} object to the system. The
20646     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
20647     * to get metrics for the drag shadow, and then calls the object's
20648     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
20649     * <p>
20650     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
20651     *  drag events to all the View objects in your application that are currently visible. It does
20652     *  this either by calling the View object's drag listener (an implementation of
20653     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
20654     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
20655     *  Both are passed a {@link android.view.DragEvent} object that has a
20656     *  {@link android.view.DragEvent#getAction()} value of
20657     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
20658     * </p>
20659     * <p>
20660     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
20661     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
20662     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
20663     * to the View the user selected for dragging.
20664     * </p>
20665     * @param data A {@link android.content.ClipData} object pointing to the data to be
20666     * transferred by the drag and drop operation.
20667     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20668     * drag shadow.
20669     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
20670     * drop operation. When dispatching drag events to views in the same activity this object
20671     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
20672     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
20673     * will return null).
20674     * <p>
20675     * myLocalState is a lightweight mechanism for the sending information from the dragged View
20676     * to the target Views. For example, it can contain flags that differentiate between a
20677     * a copy operation and a move operation.
20678     * </p>
20679     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
20680     * flags, or any combination of the following:
20681     *     <ul>
20682     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
20683     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
20684     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
20685     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
20686     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
20687     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
20688     *     </ul>
20689     * @return {@code true} if the method completes successfully, or
20690     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
20691     * do a drag, and so no drag operation is in progress.
20692     */
20693    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
20694            Object myLocalState, int flags) {
20695        if (ViewDebug.DEBUG_DRAG) {
20696            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
20697        }
20698        if (mAttachInfo == null) {
20699            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
20700            return false;
20701        }
20702        boolean okay = false;
20703
20704        Point shadowSize = new Point();
20705        Point shadowTouchPoint = new Point();
20706        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
20707
20708        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
20709                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
20710            throw new IllegalStateException("Drag shadow dimensions must not be negative");
20711        }
20712
20713        if (ViewDebug.DEBUG_DRAG) {
20714            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
20715                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
20716        }
20717        if (mAttachInfo.mDragSurface != null) {
20718            mAttachInfo.mDragSurface.release();
20719        }
20720        mAttachInfo.mDragSurface = new Surface();
20721        try {
20722            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
20723                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
20724            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
20725                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
20726            if (mAttachInfo.mDragToken != null) {
20727                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20728                try {
20729                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20730                    shadowBuilder.onDrawShadow(canvas);
20731                } finally {
20732                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20733                }
20734
20735                final ViewRootImpl root = getViewRootImpl();
20736
20737                // Cache the local state object for delivery with DragEvents
20738                root.setLocalDragState(myLocalState);
20739
20740                // repurpose 'shadowSize' for the last touch point
20741                root.getLastTouchPoint(shadowSize);
20742
20743                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
20744                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
20745                        shadowTouchPoint.x, shadowTouchPoint.y, data);
20746                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
20747            }
20748        } catch (Exception e) {
20749            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
20750            mAttachInfo.mDragSurface.destroy();
20751            mAttachInfo.mDragSurface = null;
20752        }
20753
20754        return okay;
20755    }
20756
20757    /**
20758     * Cancels an ongoing drag and drop operation.
20759     * <p>
20760     * A {@link android.view.DragEvent} object with
20761     * {@link android.view.DragEvent#getAction()} value of
20762     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
20763     * {@link android.view.DragEvent#getResult()} value of {@code false}
20764     * will be sent to every
20765     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
20766     * even if they are not currently visible.
20767     * </p>
20768     * <p>
20769     * This method can be called on any View in the same window as the View on which
20770     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
20771     * was called.
20772     * </p>
20773     */
20774    public final void cancelDragAndDrop() {
20775        if (ViewDebug.DEBUG_DRAG) {
20776            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
20777        }
20778        if (mAttachInfo == null) {
20779            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
20780            return;
20781        }
20782        if (mAttachInfo.mDragToken != null) {
20783            try {
20784                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
20785            } catch (Exception e) {
20786                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
20787            }
20788            mAttachInfo.mDragToken = null;
20789        } else {
20790            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
20791        }
20792    }
20793
20794    /**
20795     * Updates the drag shadow for the ongoing drag and drop operation.
20796     *
20797     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20798     * new drag shadow.
20799     */
20800    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
20801        if (ViewDebug.DEBUG_DRAG) {
20802            Log.d(VIEW_LOG_TAG, "updateDragShadow");
20803        }
20804        if (mAttachInfo == null) {
20805            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
20806            return;
20807        }
20808        if (mAttachInfo.mDragToken != null) {
20809            try {
20810                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20811                try {
20812                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20813                    shadowBuilder.onDrawShadow(canvas);
20814                } finally {
20815                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20816                }
20817            } catch (Exception e) {
20818                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
20819            }
20820        } else {
20821            Log.e(VIEW_LOG_TAG, "No active drag");
20822        }
20823    }
20824
20825    /**
20826     * Starts a move from {startX, startY}, the amount of the movement will be the offset
20827     * between {startX, startY} and the new cursor positon.
20828     * @param startX horizontal coordinate where the move started.
20829     * @param startY vertical coordinate where the move started.
20830     * @return whether moving was started successfully.
20831     * @hide
20832     */
20833    public final boolean startMovingTask(float startX, float startY) {
20834        if (ViewDebug.DEBUG_POSITIONING) {
20835            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
20836        }
20837        try {
20838            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
20839        } catch (RemoteException e) {
20840            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
20841        }
20842        return false;
20843    }
20844
20845    /**
20846     * Handles drag events sent by the system following a call to
20847     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
20848     * startDragAndDrop()}.
20849     *<p>
20850     * When the system calls this method, it passes a
20851     * {@link android.view.DragEvent} object. A call to
20852     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
20853     * in DragEvent. The method uses these to determine what is happening in the drag and drop
20854     * operation.
20855     * @param event The {@link android.view.DragEvent} sent by the system.
20856     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
20857     * in DragEvent, indicating the type of drag event represented by this object.
20858     * @return {@code true} if the method was successful, otherwise {@code false}.
20859     * <p>
20860     *  The method should return {@code true} in response to an action type of
20861     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
20862     *  operation.
20863     * </p>
20864     * <p>
20865     *  The method should also return {@code true} in response to an action type of
20866     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
20867     *  {@code false} if it didn't.
20868     * </p>
20869     */
20870    public boolean onDragEvent(DragEvent event) {
20871        return false;
20872    }
20873
20874    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
20875    boolean dispatchDragEnterExitInPreN(DragEvent event) {
20876        return callDragEventHandler(event);
20877    }
20878
20879    /**
20880     * Detects if this View is enabled and has a drag event listener.
20881     * If both are true, then it calls the drag event listener with the
20882     * {@link android.view.DragEvent} it received. If the drag event listener returns
20883     * {@code true}, then dispatchDragEvent() returns {@code true}.
20884     * <p>
20885     * For all other cases, the method calls the
20886     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
20887     * method and returns its result.
20888     * </p>
20889     * <p>
20890     * This ensures that a drag event is always consumed, even if the View does not have a drag
20891     * event listener. However, if the View has a listener and the listener returns true, then
20892     * onDragEvent() is not called.
20893     * </p>
20894     */
20895    public boolean dispatchDragEvent(DragEvent event) {
20896        event.mEventHandlerWasCalled = true;
20897        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
20898            event.mAction == DragEvent.ACTION_DROP) {
20899            // About to deliver an event with coordinates to this view. Notify that now this view
20900            // has drag focus. This will send exit/enter events as needed.
20901            getViewRootImpl().setDragFocus(this, event);
20902        }
20903        return callDragEventHandler(event);
20904    }
20905
20906    final boolean callDragEventHandler(DragEvent event) {
20907        final boolean result;
20908
20909        ListenerInfo li = mListenerInfo;
20910        //noinspection SimplifiableIfStatement
20911        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
20912                && li.mOnDragListener.onDrag(this, event)) {
20913            result = true;
20914        } else {
20915            result = onDragEvent(event);
20916        }
20917
20918        switch (event.mAction) {
20919            case DragEvent.ACTION_DRAG_ENTERED: {
20920                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
20921                refreshDrawableState();
20922            } break;
20923            case DragEvent.ACTION_DRAG_EXITED: {
20924                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
20925                refreshDrawableState();
20926            } break;
20927            case DragEvent.ACTION_DRAG_ENDED: {
20928                mPrivateFlags2 &= ~View.DRAG_MASK;
20929                refreshDrawableState();
20930            } break;
20931        }
20932
20933        return result;
20934    }
20935
20936    boolean canAcceptDrag() {
20937        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
20938    }
20939
20940    /**
20941     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
20942     * it is ever exposed at all.
20943     * @hide
20944     */
20945    public void onCloseSystemDialogs(String reason) {
20946    }
20947
20948    /**
20949     * Given a Drawable whose bounds have been set to draw into this view,
20950     * update a Region being computed for
20951     * {@link #gatherTransparentRegion(android.graphics.Region)} so
20952     * that any non-transparent parts of the Drawable are removed from the
20953     * given transparent region.
20954     *
20955     * @param dr The Drawable whose transparency is to be applied to the region.
20956     * @param region A Region holding the current transparency information,
20957     * where any parts of the region that are set are considered to be
20958     * transparent.  On return, this region will be modified to have the
20959     * transparency information reduced by the corresponding parts of the
20960     * Drawable that are not transparent.
20961     * {@hide}
20962     */
20963    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
20964        if (DBG) {
20965            Log.i("View", "Getting transparent region for: " + this);
20966        }
20967        final Region r = dr.getTransparentRegion();
20968        final Rect db = dr.getBounds();
20969        final AttachInfo attachInfo = mAttachInfo;
20970        if (r != null && attachInfo != null) {
20971            final int w = getRight()-getLeft();
20972            final int h = getBottom()-getTop();
20973            if (db.left > 0) {
20974                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
20975                r.op(0, 0, db.left, h, Region.Op.UNION);
20976            }
20977            if (db.right < w) {
20978                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
20979                r.op(db.right, 0, w, h, Region.Op.UNION);
20980            }
20981            if (db.top > 0) {
20982                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
20983                r.op(0, 0, w, db.top, Region.Op.UNION);
20984            }
20985            if (db.bottom < h) {
20986                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
20987                r.op(0, db.bottom, w, h, Region.Op.UNION);
20988            }
20989            final int[] location = attachInfo.mTransparentLocation;
20990            getLocationInWindow(location);
20991            r.translate(location[0], location[1]);
20992            region.op(r, Region.Op.INTERSECT);
20993        } else {
20994            region.op(db, Region.Op.DIFFERENCE);
20995        }
20996    }
20997
20998    private void checkForLongClick(int delayOffset, float x, float y) {
20999        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
21000            mHasPerformedLongPress = false;
21001
21002            if (mPendingCheckForLongPress == null) {
21003                mPendingCheckForLongPress = new CheckForLongPress();
21004            }
21005            mPendingCheckForLongPress.setAnchor(x, y);
21006            mPendingCheckForLongPress.rememberWindowAttachCount();
21007            postDelayed(mPendingCheckForLongPress,
21008                    ViewConfiguration.getLongPressTimeout() - delayOffset);
21009        }
21010    }
21011
21012    /**
21013     * Inflate a view from an XML resource.  This convenience method wraps the {@link
21014     * LayoutInflater} class, which provides a full range of options for view inflation.
21015     *
21016     * @param context The Context object for your activity or application.
21017     * @param resource The resource ID to inflate
21018     * @param root A view group that will be the parent.  Used to properly inflate the
21019     * layout_* parameters.
21020     * @see LayoutInflater
21021     */
21022    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
21023        LayoutInflater factory = LayoutInflater.from(context);
21024        return factory.inflate(resource, root);
21025    }
21026
21027    /**
21028     * Scroll the view with standard behavior for scrolling beyond the normal
21029     * content boundaries. Views that call this method should override
21030     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
21031     * results of an over-scroll operation.
21032     *
21033     * Views can use this method to handle any touch or fling-based scrolling.
21034     *
21035     * @param deltaX Change in X in pixels
21036     * @param deltaY Change in Y in pixels
21037     * @param scrollX Current X scroll value in pixels before applying deltaX
21038     * @param scrollY Current Y scroll value in pixels before applying deltaY
21039     * @param scrollRangeX Maximum content scroll range along the X axis
21040     * @param scrollRangeY Maximum content scroll range along the Y axis
21041     * @param maxOverScrollX Number of pixels to overscroll by in either direction
21042     *          along the X axis.
21043     * @param maxOverScrollY Number of pixels to overscroll by in either direction
21044     *          along the Y axis.
21045     * @param isTouchEvent true if this scroll operation is the result of a touch event.
21046     * @return true if scrolling was clamped to an over-scroll boundary along either
21047     *          axis, false otherwise.
21048     */
21049    @SuppressWarnings({"UnusedParameters"})
21050    protected boolean overScrollBy(int deltaX, int deltaY,
21051            int scrollX, int scrollY,
21052            int scrollRangeX, int scrollRangeY,
21053            int maxOverScrollX, int maxOverScrollY,
21054            boolean isTouchEvent) {
21055        final int overScrollMode = mOverScrollMode;
21056        final boolean canScrollHorizontal =
21057                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
21058        final boolean canScrollVertical =
21059                computeVerticalScrollRange() > computeVerticalScrollExtent();
21060        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
21061                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
21062        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
21063                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
21064
21065        int newScrollX = scrollX + deltaX;
21066        if (!overScrollHorizontal) {
21067            maxOverScrollX = 0;
21068        }
21069
21070        int newScrollY = scrollY + deltaY;
21071        if (!overScrollVertical) {
21072            maxOverScrollY = 0;
21073        }
21074
21075        // Clamp values if at the limits and record
21076        final int left = -maxOverScrollX;
21077        final int right = maxOverScrollX + scrollRangeX;
21078        final int top = -maxOverScrollY;
21079        final int bottom = maxOverScrollY + scrollRangeY;
21080
21081        boolean clampedX = false;
21082        if (newScrollX > right) {
21083            newScrollX = right;
21084            clampedX = true;
21085        } else if (newScrollX < left) {
21086            newScrollX = left;
21087            clampedX = true;
21088        }
21089
21090        boolean clampedY = false;
21091        if (newScrollY > bottom) {
21092            newScrollY = bottom;
21093            clampedY = true;
21094        } else if (newScrollY < top) {
21095            newScrollY = top;
21096            clampedY = true;
21097        }
21098
21099        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
21100
21101        return clampedX || clampedY;
21102    }
21103
21104    /**
21105     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
21106     * respond to the results of an over-scroll operation.
21107     *
21108     * @param scrollX New X scroll value in pixels
21109     * @param scrollY New Y scroll value in pixels
21110     * @param clampedX True if scrollX was clamped to an over-scroll boundary
21111     * @param clampedY True if scrollY was clamped to an over-scroll boundary
21112     */
21113    protected void onOverScrolled(int scrollX, int scrollY,
21114            boolean clampedX, boolean clampedY) {
21115        // Intentionally empty.
21116    }
21117
21118    /**
21119     * Returns the over-scroll mode for this view. The result will be
21120     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21121     * (allow over-scrolling only if the view content is larger than the container),
21122     * or {@link #OVER_SCROLL_NEVER}.
21123     *
21124     * @return This view's over-scroll mode.
21125     */
21126    public int getOverScrollMode() {
21127        return mOverScrollMode;
21128    }
21129
21130    /**
21131     * Set the over-scroll mode for this view. Valid over-scroll modes are
21132     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21133     * (allow over-scrolling only if the view content is larger than the container),
21134     * or {@link #OVER_SCROLL_NEVER}.
21135     *
21136     * Setting the over-scroll mode of a view will have an effect only if the
21137     * view is capable of scrolling.
21138     *
21139     * @param overScrollMode The new over-scroll mode for this view.
21140     */
21141    public void setOverScrollMode(int overScrollMode) {
21142        if (overScrollMode != OVER_SCROLL_ALWAYS &&
21143                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
21144                overScrollMode != OVER_SCROLL_NEVER) {
21145            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
21146        }
21147        mOverScrollMode = overScrollMode;
21148    }
21149
21150    /**
21151     * Enable or disable nested scrolling for this view.
21152     *
21153     * <p>If this property is set to true the view will be permitted to initiate nested
21154     * scrolling operations with a compatible parent view in the current hierarchy. If this
21155     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
21156     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
21157     * the nested scroll.</p>
21158     *
21159     * @param enabled true to enable nested scrolling, false to disable
21160     *
21161     * @see #isNestedScrollingEnabled()
21162     */
21163    public void setNestedScrollingEnabled(boolean enabled) {
21164        if (enabled) {
21165            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
21166        } else {
21167            stopNestedScroll();
21168            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
21169        }
21170    }
21171
21172    /**
21173     * Returns true if nested scrolling is enabled for this view.
21174     *
21175     * <p>If nested scrolling is enabled and this View class implementation supports it,
21176     * this view will act as a nested scrolling child view when applicable, forwarding data
21177     * about the scroll operation in progress to a compatible and cooperating nested scrolling
21178     * parent.</p>
21179     *
21180     * @return true if nested scrolling is enabled
21181     *
21182     * @see #setNestedScrollingEnabled(boolean)
21183     */
21184    public boolean isNestedScrollingEnabled() {
21185        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
21186                PFLAG3_NESTED_SCROLLING_ENABLED;
21187    }
21188
21189    /**
21190     * Begin a nestable scroll operation along the given axes.
21191     *
21192     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
21193     *
21194     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
21195     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
21196     * In the case of touch scrolling the nested scroll will be terminated automatically in
21197     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
21198     * In the event of programmatic scrolling the caller must explicitly call
21199     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
21200     *
21201     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
21202     * If it returns false the caller may ignore the rest of this contract until the next scroll.
21203     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
21204     *
21205     * <p>At each incremental step of the scroll the caller should invoke
21206     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
21207     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
21208     * parent at least partially consumed the scroll and the caller should adjust the amount it
21209     * scrolls by.</p>
21210     *
21211     * <p>After applying the remainder of the scroll delta the caller should invoke
21212     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
21213     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
21214     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
21215     * </p>
21216     *
21217     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
21218     *             {@link #SCROLL_AXIS_VERTICAL}.
21219     * @return true if a cooperative parent was found and nested scrolling has been enabled for
21220     *         the current gesture.
21221     *
21222     * @see #stopNestedScroll()
21223     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21224     * @see #dispatchNestedScroll(int, int, int, int, int[])
21225     */
21226    public boolean startNestedScroll(int axes) {
21227        if (hasNestedScrollingParent()) {
21228            // Already in progress
21229            return true;
21230        }
21231        if (isNestedScrollingEnabled()) {
21232            ViewParent p = getParent();
21233            View child = this;
21234            while (p != null) {
21235                try {
21236                    if (p.onStartNestedScroll(child, this, axes)) {
21237                        mNestedScrollingParent = p;
21238                        p.onNestedScrollAccepted(child, this, axes);
21239                        return true;
21240                    }
21241                } catch (AbstractMethodError e) {
21242                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
21243                            "method onStartNestedScroll", e);
21244                    // Allow the search upward to continue
21245                }
21246                if (p instanceof View) {
21247                    child = (View) p;
21248                }
21249                p = p.getParent();
21250            }
21251        }
21252        return false;
21253    }
21254
21255    /**
21256     * Stop a nested scroll in progress.
21257     *
21258     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
21259     *
21260     * @see #startNestedScroll(int)
21261     */
21262    public void stopNestedScroll() {
21263        if (mNestedScrollingParent != null) {
21264            mNestedScrollingParent.onStopNestedScroll(this);
21265            mNestedScrollingParent = null;
21266        }
21267    }
21268
21269    /**
21270     * Returns true if this view has a nested scrolling parent.
21271     *
21272     * <p>The presence of a nested scrolling parent indicates that this view has initiated
21273     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
21274     *
21275     * @return whether this view has a nested scrolling parent
21276     */
21277    public boolean hasNestedScrollingParent() {
21278        return mNestedScrollingParent != null;
21279    }
21280
21281    /**
21282     * Dispatch one step of a nested scroll in progress.
21283     *
21284     * <p>Implementations of views that support nested scrolling should call this to report
21285     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
21286     * is not currently in progress or nested scrolling is not
21287     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
21288     *
21289     * <p>Compatible View implementations should also call
21290     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
21291     * consuming a component of the scroll event themselves.</p>
21292     *
21293     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
21294     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
21295     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
21296     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
21297     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21298     *                       in local view coordinates of this view from before this operation
21299     *                       to after it completes. View implementations may use this to adjust
21300     *                       expected input coordinate tracking.
21301     * @return true if the event was dispatched, false if it could not be dispatched.
21302     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21303     */
21304    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
21305            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
21306        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21307            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
21308                int startX = 0;
21309                int startY = 0;
21310                if (offsetInWindow != null) {
21311                    getLocationInWindow(offsetInWindow);
21312                    startX = offsetInWindow[0];
21313                    startY = offsetInWindow[1];
21314                }
21315
21316                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
21317                        dxUnconsumed, dyUnconsumed);
21318
21319                if (offsetInWindow != null) {
21320                    getLocationInWindow(offsetInWindow);
21321                    offsetInWindow[0] -= startX;
21322                    offsetInWindow[1] -= startY;
21323                }
21324                return true;
21325            } else if (offsetInWindow != null) {
21326                // No motion, no dispatch. Keep offsetInWindow up to date.
21327                offsetInWindow[0] = 0;
21328                offsetInWindow[1] = 0;
21329            }
21330        }
21331        return false;
21332    }
21333
21334    /**
21335     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
21336     *
21337     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
21338     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
21339     * scrolling operation to consume some or all of the scroll operation before the child view
21340     * consumes it.</p>
21341     *
21342     * @param dx Horizontal scroll distance in pixels
21343     * @param dy Vertical scroll distance in pixels
21344     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
21345     *                 and consumed[1] the consumed dy.
21346     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21347     *                       in local view coordinates of this view from before this operation
21348     *                       to after it completes. View implementations may use this to adjust
21349     *                       expected input coordinate tracking.
21350     * @return true if the parent consumed some or all of the scroll delta
21351     * @see #dispatchNestedScroll(int, int, int, int, int[])
21352     */
21353    public boolean dispatchNestedPreScroll(int dx, int dy,
21354            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
21355        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21356            if (dx != 0 || dy != 0) {
21357                int startX = 0;
21358                int startY = 0;
21359                if (offsetInWindow != null) {
21360                    getLocationInWindow(offsetInWindow);
21361                    startX = offsetInWindow[0];
21362                    startY = offsetInWindow[1];
21363                }
21364
21365                if (consumed == null) {
21366                    if (mTempNestedScrollConsumed == null) {
21367                        mTempNestedScrollConsumed = new int[2];
21368                    }
21369                    consumed = mTempNestedScrollConsumed;
21370                }
21371                consumed[0] = 0;
21372                consumed[1] = 0;
21373                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
21374
21375                if (offsetInWindow != null) {
21376                    getLocationInWindow(offsetInWindow);
21377                    offsetInWindow[0] -= startX;
21378                    offsetInWindow[1] -= startY;
21379                }
21380                return consumed[0] != 0 || consumed[1] != 0;
21381            } else if (offsetInWindow != null) {
21382                offsetInWindow[0] = 0;
21383                offsetInWindow[1] = 0;
21384            }
21385        }
21386        return false;
21387    }
21388
21389    /**
21390     * Dispatch a fling to a nested scrolling parent.
21391     *
21392     * <p>This method should be used to indicate that a nested scrolling child has detected
21393     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
21394     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
21395     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
21396     * along a scrollable axis.</p>
21397     *
21398     * <p>If a nested scrolling child view would normally fling but it is at the edge of
21399     * its own content, it can use this method to delegate the fling to its nested scrolling
21400     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
21401     *
21402     * @param velocityX Horizontal fling velocity in pixels per second
21403     * @param velocityY Vertical fling velocity in pixels per second
21404     * @param consumed true if the child consumed the fling, false otherwise
21405     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
21406     */
21407    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
21408        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21409            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
21410        }
21411        return false;
21412    }
21413
21414    /**
21415     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
21416     *
21417     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
21418     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
21419     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
21420     * before the child view consumes it. If this method returns <code>true</code>, a nested
21421     * parent view consumed the fling and this view should not scroll as a result.</p>
21422     *
21423     * <p>For a better user experience, only one view in a nested scrolling chain should consume
21424     * the fling at a time. If a parent view consumed the fling this method will return false.
21425     * Custom view implementations should account for this in two ways:</p>
21426     *
21427     * <ul>
21428     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
21429     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
21430     *     position regardless.</li>
21431     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
21432     *     even to settle back to a valid idle position.</li>
21433     * </ul>
21434     *
21435     * <p>Views should also not offer fling velocities to nested parent views along an axis
21436     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
21437     * should not offer a horizontal fling velocity to its parents since scrolling along that
21438     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
21439     *
21440     * @param velocityX Horizontal fling velocity in pixels per second
21441     * @param velocityY Vertical fling velocity in pixels per second
21442     * @return true if a nested scrolling parent consumed the fling
21443     */
21444    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
21445        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21446            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
21447        }
21448        return false;
21449    }
21450
21451    /**
21452     * Gets a scale factor that determines the distance the view should scroll
21453     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
21454     * @return The vertical scroll scale factor.
21455     * @hide
21456     */
21457    protected float getVerticalScrollFactor() {
21458        if (mVerticalScrollFactor == 0) {
21459            TypedValue outValue = new TypedValue();
21460            if (!mContext.getTheme().resolveAttribute(
21461                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
21462                throw new IllegalStateException(
21463                        "Expected theme to define listPreferredItemHeight.");
21464            }
21465            mVerticalScrollFactor = outValue.getDimension(
21466                    mContext.getResources().getDisplayMetrics());
21467        }
21468        return mVerticalScrollFactor;
21469    }
21470
21471    /**
21472     * Gets a scale factor that determines the distance the view should scroll
21473     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
21474     * @return The horizontal scroll scale factor.
21475     * @hide
21476     */
21477    protected float getHorizontalScrollFactor() {
21478        // TODO: Should use something else.
21479        return getVerticalScrollFactor();
21480    }
21481
21482    /**
21483     * Return the value specifying the text direction or policy that was set with
21484     * {@link #setTextDirection(int)}.
21485     *
21486     * @return the defined text direction. It can be one of:
21487     *
21488     * {@link #TEXT_DIRECTION_INHERIT},
21489     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21490     * {@link #TEXT_DIRECTION_ANY_RTL},
21491     * {@link #TEXT_DIRECTION_LTR},
21492     * {@link #TEXT_DIRECTION_RTL},
21493     * {@link #TEXT_DIRECTION_LOCALE},
21494     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21495     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21496     *
21497     * @attr ref android.R.styleable#View_textDirection
21498     *
21499     * @hide
21500     */
21501    @ViewDebug.ExportedProperty(category = "text", mapping = {
21502            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21503            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21504            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21505            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21506            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21507            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21508            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21509            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21510    })
21511    public int getRawTextDirection() {
21512        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
21513    }
21514
21515    /**
21516     * Set the text direction.
21517     *
21518     * @param textDirection the direction to set. Should be one of:
21519     *
21520     * {@link #TEXT_DIRECTION_INHERIT},
21521     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21522     * {@link #TEXT_DIRECTION_ANY_RTL},
21523     * {@link #TEXT_DIRECTION_LTR},
21524     * {@link #TEXT_DIRECTION_RTL},
21525     * {@link #TEXT_DIRECTION_LOCALE}
21526     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21527     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
21528     *
21529     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
21530     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
21531     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
21532     *
21533     * @attr ref android.R.styleable#View_textDirection
21534     */
21535    public void setTextDirection(int textDirection) {
21536        if (getRawTextDirection() != textDirection) {
21537            // Reset the current text direction and the resolved one
21538            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
21539            resetResolvedTextDirection();
21540            // Set the new text direction
21541            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
21542            // Do resolution
21543            resolveTextDirection();
21544            // Notify change
21545            onRtlPropertiesChanged(getLayoutDirection());
21546            // Refresh
21547            requestLayout();
21548            invalidate(true);
21549        }
21550    }
21551
21552    /**
21553     * Return the resolved text direction.
21554     *
21555     * @return the resolved text direction. Returns one of:
21556     *
21557     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21558     * {@link #TEXT_DIRECTION_ANY_RTL},
21559     * {@link #TEXT_DIRECTION_LTR},
21560     * {@link #TEXT_DIRECTION_RTL},
21561     * {@link #TEXT_DIRECTION_LOCALE},
21562     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21563     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21564     *
21565     * @attr ref android.R.styleable#View_textDirection
21566     */
21567    @ViewDebug.ExportedProperty(category = "text", mapping = {
21568            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21569            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21570            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21571            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21572            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21573            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21574            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21575            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21576    })
21577    public int getTextDirection() {
21578        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
21579    }
21580
21581    /**
21582     * Resolve the text direction.
21583     *
21584     * @return true if resolution has been done, false otherwise.
21585     *
21586     * @hide
21587     */
21588    public boolean resolveTextDirection() {
21589        // Reset any previous text direction resolution
21590        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21591
21592        if (hasRtlSupport()) {
21593            // Set resolved text direction flag depending on text direction flag
21594            final int textDirection = getRawTextDirection();
21595            switch(textDirection) {
21596                case TEXT_DIRECTION_INHERIT:
21597                    if (!canResolveTextDirection()) {
21598                        // We cannot do the resolution if there is no parent, so use the default one
21599                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21600                        // Resolution will need to happen again later
21601                        return false;
21602                    }
21603
21604                    // Parent has not yet resolved, so we still return the default
21605                    try {
21606                        if (!mParent.isTextDirectionResolved()) {
21607                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21608                            // Resolution will need to happen again later
21609                            return false;
21610                        }
21611                    } catch (AbstractMethodError e) {
21612                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21613                                " does not fully implement ViewParent", e);
21614                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
21615                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21616                        return true;
21617                    }
21618
21619                    // Set current resolved direction to the same value as the parent's one
21620                    int parentResolvedDirection;
21621                    try {
21622                        parentResolvedDirection = mParent.getTextDirection();
21623                    } catch (AbstractMethodError e) {
21624                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21625                                " does not fully implement ViewParent", e);
21626                        parentResolvedDirection = TEXT_DIRECTION_LTR;
21627                    }
21628                    switch (parentResolvedDirection) {
21629                        case TEXT_DIRECTION_FIRST_STRONG:
21630                        case TEXT_DIRECTION_ANY_RTL:
21631                        case TEXT_DIRECTION_LTR:
21632                        case TEXT_DIRECTION_RTL:
21633                        case TEXT_DIRECTION_LOCALE:
21634                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
21635                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
21636                            mPrivateFlags2 |=
21637                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21638                            break;
21639                        default:
21640                            // Default resolved direction is "first strong" heuristic
21641                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21642                    }
21643                    break;
21644                case TEXT_DIRECTION_FIRST_STRONG:
21645                case TEXT_DIRECTION_ANY_RTL:
21646                case TEXT_DIRECTION_LTR:
21647                case TEXT_DIRECTION_RTL:
21648                case TEXT_DIRECTION_LOCALE:
21649                case TEXT_DIRECTION_FIRST_STRONG_LTR:
21650                case TEXT_DIRECTION_FIRST_STRONG_RTL:
21651                    // Resolved direction is the same as text direction
21652                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21653                    break;
21654                default:
21655                    // Default resolved direction is "first strong" heuristic
21656                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21657            }
21658        } else {
21659            // Default resolved direction is "first strong" heuristic
21660            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21661        }
21662
21663        // Set to resolved
21664        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
21665        return true;
21666    }
21667
21668    /**
21669     * Check if text direction resolution can be done.
21670     *
21671     * @return true if text direction resolution can be done otherwise return false.
21672     */
21673    public boolean canResolveTextDirection() {
21674        switch (getRawTextDirection()) {
21675            case TEXT_DIRECTION_INHERIT:
21676                if (mParent != null) {
21677                    try {
21678                        return mParent.canResolveTextDirection();
21679                    } catch (AbstractMethodError e) {
21680                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21681                                " does not fully implement ViewParent", e);
21682                    }
21683                }
21684                return false;
21685
21686            default:
21687                return true;
21688        }
21689    }
21690
21691    /**
21692     * Reset resolved text direction. Text direction will be resolved during a call to
21693     * {@link #onMeasure(int, int)}.
21694     *
21695     * @hide
21696     */
21697    public void resetResolvedTextDirection() {
21698        // Reset any previous text direction resolution
21699        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21700        // Set to default value
21701        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21702    }
21703
21704    /**
21705     * @return true if text direction is inherited.
21706     *
21707     * @hide
21708     */
21709    public boolean isTextDirectionInherited() {
21710        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
21711    }
21712
21713    /**
21714     * @return true if text direction is resolved.
21715     */
21716    public boolean isTextDirectionResolved() {
21717        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
21718    }
21719
21720    /**
21721     * Return the value specifying the text alignment or policy that was set with
21722     * {@link #setTextAlignment(int)}.
21723     *
21724     * @return the defined text alignment. It can be one of:
21725     *
21726     * {@link #TEXT_ALIGNMENT_INHERIT},
21727     * {@link #TEXT_ALIGNMENT_GRAVITY},
21728     * {@link #TEXT_ALIGNMENT_CENTER},
21729     * {@link #TEXT_ALIGNMENT_TEXT_START},
21730     * {@link #TEXT_ALIGNMENT_TEXT_END},
21731     * {@link #TEXT_ALIGNMENT_VIEW_START},
21732     * {@link #TEXT_ALIGNMENT_VIEW_END}
21733     *
21734     * @attr ref android.R.styleable#View_textAlignment
21735     *
21736     * @hide
21737     */
21738    @ViewDebug.ExportedProperty(category = "text", mapping = {
21739            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21740            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21741            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21742            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21743            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21744            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21745            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21746    })
21747    @TextAlignment
21748    public int getRawTextAlignment() {
21749        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
21750    }
21751
21752    /**
21753     * Set the text alignment.
21754     *
21755     * @param textAlignment The text alignment to set. Should be one of
21756     *
21757     * {@link #TEXT_ALIGNMENT_INHERIT},
21758     * {@link #TEXT_ALIGNMENT_GRAVITY},
21759     * {@link #TEXT_ALIGNMENT_CENTER},
21760     * {@link #TEXT_ALIGNMENT_TEXT_START},
21761     * {@link #TEXT_ALIGNMENT_TEXT_END},
21762     * {@link #TEXT_ALIGNMENT_VIEW_START},
21763     * {@link #TEXT_ALIGNMENT_VIEW_END}
21764     *
21765     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
21766     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
21767     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
21768     *
21769     * @attr ref android.R.styleable#View_textAlignment
21770     */
21771    public void setTextAlignment(@TextAlignment int textAlignment) {
21772        if (textAlignment != getRawTextAlignment()) {
21773            // Reset the current and resolved text alignment
21774            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
21775            resetResolvedTextAlignment();
21776            // Set the new text alignment
21777            mPrivateFlags2 |=
21778                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
21779            // Do resolution
21780            resolveTextAlignment();
21781            // Notify change
21782            onRtlPropertiesChanged(getLayoutDirection());
21783            // Refresh
21784            requestLayout();
21785            invalidate(true);
21786        }
21787    }
21788
21789    /**
21790     * Return the resolved text alignment.
21791     *
21792     * @return the resolved text alignment. Returns one of:
21793     *
21794     * {@link #TEXT_ALIGNMENT_GRAVITY},
21795     * {@link #TEXT_ALIGNMENT_CENTER},
21796     * {@link #TEXT_ALIGNMENT_TEXT_START},
21797     * {@link #TEXT_ALIGNMENT_TEXT_END},
21798     * {@link #TEXT_ALIGNMENT_VIEW_START},
21799     * {@link #TEXT_ALIGNMENT_VIEW_END}
21800     *
21801     * @attr ref android.R.styleable#View_textAlignment
21802     */
21803    @ViewDebug.ExportedProperty(category = "text", mapping = {
21804            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21805            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21806            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21807            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21808            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21809            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21810            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21811    })
21812    @TextAlignment
21813    public int getTextAlignment() {
21814        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
21815                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
21816    }
21817
21818    /**
21819     * Resolve the text alignment.
21820     *
21821     * @return true if resolution has been done, false otherwise.
21822     *
21823     * @hide
21824     */
21825    public boolean resolveTextAlignment() {
21826        // Reset any previous text alignment resolution
21827        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21828
21829        if (hasRtlSupport()) {
21830            // Set resolved text alignment flag depending on text alignment flag
21831            final int textAlignment = getRawTextAlignment();
21832            switch (textAlignment) {
21833                case TEXT_ALIGNMENT_INHERIT:
21834                    // Check if we can resolve the text alignment
21835                    if (!canResolveTextAlignment()) {
21836                        // We cannot do the resolution if there is no parent so use the default
21837                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21838                        // Resolution will need to happen again later
21839                        return false;
21840                    }
21841
21842                    // Parent has not yet resolved, so we still return the default
21843                    try {
21844                        if (!mParent.isTextAlignmentResolved()) {
21845                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21846                            // Resolution will need to happen again later
21847                            return false;
21848                        }
21849                    } catch (AbstractMethodError e) {
21850                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21851                                " does not fully implement ViewParent", e);
21852                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
21853                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21854                        return true;
21855                    }
21856
21857                    int parentResolvedTextAlignment;
21858                    try {
21859                        parentResolvedTextAlignment = mParent.getTextAlignment();
21860                    } catch (AbstractMethodError e) {
21861                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21862                                " does not fully implement ViewParent", e);
21863                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
21864                    }
21865                    switch (parentResolvedTextAlignment) {
21866                        case TEXT_ALIGNMENT_GRAVITY:
21867                        case TEXT_ALIGNMENT_TEXT_START:
21868                        case TEXT_ALIGNMENT_TEXT_END:
21869                        case TEXT_ALIGNMENT_CENTER:
21870                        case TEXT_ALIGNMENT_VIEW_START:
21871                        case TEXT_ALIGNMENT_VIEW_END:
21872                            // Resolved text alignment is the same as the parent resolved
21873                            // text alignment
21874                            mPrivateFlags2 |=
21875                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21876                            break;
21877                        default:
21878                            // Use default resolved text alignment
21879                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21880                    }
21881                    break;
21882                case TEXT_ALIGNMENT_GRAVITY:
21883                case TEXT_ALIGNMENT_TEXT_START:
21884                case TEXT_ALIGNMENT_TEXT_END:
21885                case TEXT_ALIGNMENT_CENTER:
21886                case TEXT_ALIGNMENT_VIEW_START:
21887                case TEXT_ALIGNMENT_VIEW_END:
21888                    // Resolved text alignment is the same as text alignment
21889                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21890                    break;
21891                default:
21892                    // Use default resolved text alignment
21893                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21894            }
21895        } else {
21896            // Use default resolved text alignment
21897            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21898        }
21899
21900        // Set the resolved
21901        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21902        return true;
21903    }
21904
21905    /**
21906     * Check if text alignment resolution can be done.
21907     *
21908     * @return true if text alignment resolution can be done otherwise return false.
21909     */
21910    public boolean canResolveTextAlignment() {
21911        switch (getRawTextAlignment()) {
21912            case TEXT_DIRECTION_INHERIT:
21913                if (mParent != null) {
21914                    try {
21915                        return mParent.canResolveTextAlignment();
21916                    } catch (AbstractMethodError e) {
21917                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21918                                " does not fully implement ViewParent", e);
21919                    }
21920                }
21921                return false;
21922
21923            default:
21924                return true;
21925        }
21926    }
21927
21928    /**
21929     * Reset resolved text alignment. Text alignment will be resolved during a call to
21930     * {@link #onMeasure(int, int)}.
21931     *
21932     * @hide
21933     */
21934    public void resetResolvedTextAlignment() {
21935        // Reset any previous text alignment resolution
21936        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21937        // Set to default
21938        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21939    }
21940
21941    /**
21942     * @return true if text alignment is inherited.
21943     *
21944     * @hide
21945     */
21946    public boolean isTextAlignmentInherited() {
21947        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
21948    }
21949
21950    /**
21951     * @return true if text alignment is resolved.
21952     */
21953    public boolean isTextAlignmentResolved() {
21954        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21955    }
21956
21957    /**
21958     * Generate a value suitable for use in {@link #setId(int)}.
21959     * This value will not collide with ID values generated at build time by aapt for R.id.
21960     *
21961     * @return a generated ID value
21962     */
21963    public static int generateViewId() {
21964        for (;;) {
21965            final int result = sNextGeneratedId.get();
21966            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
21967            int newValue = result + 1;
21968            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
21969            if (sNextGeneratedId.compareAndSet(result, newValue)) {
21970                return result;
21971            }
21972        }
21973    }
21974
21975    /**
21976     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
21977     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
21978     *                           a normal View or a ViewGroup with
21979     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
21980     * @hide
21981     */
21982    public void captureTransitioningViews(List<View> transitioningViews) {
21983        if (getVisibility() == View.VISIBLE) {
21984            transitioningViews.add(this);
21985        }
21986    }
21987
21988    /**
21989     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
21990     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
21991     * @hide
21992     */
21993    public void findNamedViews(Map<String, View> namedElements) {
21994        if (getVisibility() == VISIBLE || mGhostView != null) {
21995            String transitionName = getTransitionName();
21996            if (transitionName != null) {
21997                namedElements.put(transitionName, this);
21998            }
21999        }
22000    }
22001
22002    /**
22003     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
22004     * The default implementation does not care the location or event types, but some subclasses
22005     * may use it (such as WebViews).
22006     * @param event The MotionEvent from a mouse
22007     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
22008     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
22009     * @see PointerIcon
22010     */
22011    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
22012        final float x = event.getX(pointerIndex);
22013        final float y = event.getY(pointerIndex);
22014        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
22015            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
22016        }
22017        return mPointerIcon;
22018    }
22019
22020    /**
22021     * Set the pointer icon for the current view.
22022     * Passing {@code null} will restore the pointer icon to its default value.
22023     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
22024     */
22025    public void setPointerIcon(PointerIcon pointerIcon) {
22026        mPointerIcon = pointerIcon;
22027        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
22028            return;
22029        }
22030        try {
22031            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
22032        } catch (RemoteException e) {
22033        }
22034    }
22035
22036    /**
22037     * Gets the pointer icon for the current view.
22038     */
22039    public PointerIcon getPointerIcon() {
22040        return mPointerIcon;
22041    }
22042
22043    //
22044    // Properties
22045    //
22046    /**
22047     * A Property wrapper around the <code>alpha</code> functionality handled by the
22048     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
22049     */
22050    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
22051        @Override
22052        public void setValue(View object, float value) {
22053            object.setAlpha(value);
22054        }
22055
22056        @Override
22057        public Float get(View object) {
22058            return object.getAlpha();
22059        }
22060    };
22061
22062    /**
22063     * A Property wrapper around the <code>translationX</code> functionality handled by the
22064     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
22065     */
22066    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
22067        @Override
22068        public void setValue(View object, float value) {
22069            object.setTranslationX(value);
22070        }
22071
22072                @Override
22073        public Float get(View object) {
22074            return object.getTranslationX();
22075        }
22076    };
22077
22078    /**
22079     * A Property wrapper around the <code>translationY</code> functionality handled by the
22080     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
22081     */
22082    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
22083        @Override
22084        public void setValue(View object, float value) {
22085            object.setTranslationY(value);
22086        }
22087
22088        @Override
22089        public Float get(View object) {
22090            return object.getTranslationY();
22091        }
22092    };
22093
22094    /**
22095     * A Property wrapper around the <code>translationZ</code> functionality handled by the
22096     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
22097     */
22098    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
22099        @Override
22100        public void setValue(View object, float value) {
22101            object.setTranslationZ(value);
22102        }
22103
22104        @Override
22105        public Float get(View object) {
22106            return object.getTranslationZ();
22107        }
22108    };
22109
22110    /**
22111     * A Property wrapper around the <code>x</code> functionality handled by the
22112     * {@link View#setX(float)} and {@link View#getX()} methods.
22113     */
22114    public static final Property<View, Float> X = new FloatProperty<View>("x") {
22115        @Override
22116        public void setValue(View object, float value) {
22117            object.setX(value);
22118        }
22119
22120        @Override
22121        public Float get(View object) {
22122            return object.getX();
22123        }
22124    };
22125
22126    /**
22127     * A Property wrapper around the <code>y</code> functionality handled by the
22128     * {@link View#setY(float)} and {@link View#getY()} methods.
22129     */
22130    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
22131        @Override
22132        public void setValue(View object, float value) {
22133            object.setY(value);
22134        }
22135
22136        @Override
22137        public Float get(View object) {
22138            return object.getY();
22139        }
22140    };
22141
22142    /**
22143     * A Property wrapper around the <code>z</code> functionality handled by the
22144     * {@link View#setZ(float)} and {@link View#getZ()} methods.
22145     */
22146    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
22147        @Override
22148        public void setValue(View object, float value) {
22149            object.setZ(value);
22150        }
22151
22152        @Override
22153        public Float get(View object) {
22154            return object.getZ();
22155        }
22156    };
22157
22158    /**
22159     * A Property wrapper around the <code>rotation</code> functionality handled by the
22160     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
22161     */
22162    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
22163        @Override
22164        public void setValue(View object, float value) {
22165            object.setRotation(value);
22166        }
22167
22168        @Override
22169        public Float get(View object) {
22170            return object.getRotation();
22171        }
22172    };
22173
22174    /**
22175     * A Property wrapper around the <code>rotationX</code> functionality handled by the
22176     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
22177     */
22178    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
22179        @Override
22180        public void setValue(View object, float value) {
22181            object.setRotationX(value);
22182        }
22183
22184        @Override
22185        public Float get(View object) {
22186            return object.getRotationX();
22187        }
22188    };
22189
22190    /**
22191     * A Property wrapper around the <code>rotationY</code> functionality handled by the
22192     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
22193     */
22194    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
22195        @Override
22196        public void setValue(View object, float value) {
22197            object.setRotationY(value);
22198        }
22199
22200        @Override
22201        public Float get(View object) {
22202            return object.getRotationY();
22203        }
22204    };
22205
22206    /**
22207     * A Property wrapper around the <code>scaleX</code> functionality handled by the
22208     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
22209     */
22210    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
22211        @Override
22212        public void setValue(View object, float value) {
22213            object.setScaleX(value);
22214        }
22215
22216        @Override
22217        public Float get(View object) {
22218            return object.getScaleX();
22219        }
22220    };
22221
22222    /**
22223     * A Property wrapper around the <code>scaleY</code> functionality handled by the
22224     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
22225     */
22226    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
22227        @Override
22228        public void setValue(View object, float value) {
22229            object.setScaleY(value);
22230        }
22231
22232        @Override
22233        public Float get(View object) {
22234            return object.getScaleY();
22235        }
22236    };
22237
22238    /**
22239     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
22240     * Each MeasureSpec represents a requirement for either the width or the height.
22241     * A MeasureSpec is comprised of a size and a mode. There are three possible
22242     * modes:
22243     * <dl>
22244     * <dt>UNSPECIFIED</dt>
22245     * <dd>
22246     * The parent has not imposed any constraint on the child. It can be whatever size
22247     * it wants.
22248     * </dd>
22249     *
22250     * <dt>EXACTLY</dt>
22251     * <dd>
22252     * The parent has determined an exact size for the child. The child is going to be
22253     * given those bounds regardless of how big it wants to be.
22254     * </dd>
22255     *
22256     * <dt>AT_MOST</dt>
22257     * <dd>
22258     * The child can be as large as it wants up to the specified size.
22259     * </dd>
22260     * </dl>
22261     *
22262     * MeasureSpecs are implemented as ints to reduce object allocation. This class
22263     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
22264     */
22265    public static class MeasureSpec {
22266        private static final int MODE_SHIFT = 30;
22267        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
22268
22269        /** @hide */
22270        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
22271        @Retention(RetentionPolicy.SOURCE)
22272        public @interface MeasureSpecMode {}
22273
22274        /**
22275         * Measure specification mode: The parent has not imposed any constraint
22276         * on the child. It can be whatever size it wants.
22277         */
22278        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
22279
22280        /**
22281         * Measure specification mode: The parent has determined an exact size
22282         * for the child. The child is going to be given those bounds regardless
22283         * of how big it wants to be.
22284         */
22285        public static final int EXACTLY     = 1 << MODE_SHIFT;
22286
22287        /**
22288         * Measure specification mode: The child can be as large as it wants up
22289         * to the specified size.
22290         */
22291        public static final int AT_MOST     = 2 << MODE_SHIFT;
22292
22293        /**
22294         * Creates a measure specification based on the supplied size and mode.
22295         *
22296         * The mode must always be one of the following:
22297         * <ul>
22298         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
22299         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
22300         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
22301         * </ul>
22302         *
22303         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
22304         * implementation was such that the order of arguments did not matter
22305         * and overflow in either value could impact the resulting MeasureSpec.
22306         * {@link android.widget.RelativeLayout} was affected by this bug.
22307         * Apps targeting API levels greater than 17 will get the fixed, more strict
22308         * behavior.</p>
22309         *
22310         * @param size the size of the measure specification
22311         * @param mode the mode of the measure specification
22312         * @return the measure specification based on size and mode
22313         */
22314        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
22315                                          @MeasureSpecMode int mode) {
22316            if (sUseBrokenMakeMeasureSpec) {
22317                return size + mode;
22318            } else {
22319                return (size & ~MODE_MASK) | (mode & MODE_MASK);
22320            }
22321        }
22322
22323        /**
22324         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
22325         * will automatically get a size of 0. Older apps expect this.
22326         *
22327         * @hide internal use only for compatibility with system widgets and older apps
22328         */
22329        public static int makeSafeMeasureSpec(int size, int mode) {
22330            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
22331                return 0;
22332            }
22333            return makeMeasureSpec(size, mode);
22334        }
22335
22336        /**
22337         * Extracts the mode from the supplied measure specification.
22338         *
22339         * @param measureSpec the measure specification to extract the mode from
22340         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
22341         *         {@link android.view.View.MeasureSpec#AT_MOST} or
22342         *         {@link android.view.View.MeasureSpec#EXACTLY}
22343         */
22344        @MeasureSpecMode
22345        public static int getMode(int measureSpec) {
22346            //noinspection ResourceType
22347            return (measureSpec & MODE_MASK);
22348        }
22349
22350        /**
22351         * Extracts the size from the supplied measure specification.
22352         *
22353         * @param measureSpec the measure specification to extract the size from
22354         * @return the size in pixels defined in the supplied measure specification
22355         */
22356        public static int getSize(int measureSpec) {
22357            return (measureSpec & ~MODE_MASK);
22358        }
22359
22360        static int adjust(int measureSpec, int delta) {
22361            final int mode = getMode(measureSpec);
22362            int size = getSize(measureSpec);
22363            if (mode == UNSPECIFIED) {
22364                // No need to adjust size for UNSPECIFIED mode.
22365                return makeMeasureSpec(size, UNSPECIFIED);
22366            }
22367            size += delta;
22368            if (size < 0) {
22369                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
22370                        ") spec: " + toString(measureSpec) + " delta: " + delta);
22371                size = 0;
22372            }
22373            return makeMeasureSpec(size, mode);
22374        }
22375
22376        /**
22377         * Returns a String representation of the specified measure
22378         * specification.
22379         *
22380         * @param measureSpec the measure specification to convert to a String
22381         * @return a String with the following format: "MeasureSpec: MODE SIZE"
22382         */
22383        public static String toString(int measureSpec) {
22384            int mode = getMode(measureSpec);
22385            int size = getSize(measureSpec);
22386
22387            StringBuilder sb = new StringBuilder("MeasureSpec: ");
22388
22389            if (mode == UNSPECIFIED)
22390                sb.append("UNSPECIFIED ");
22391            else if (mode == EXACTLY)
22392                sb.append("EXACTLY ");
22393            else if (mode == AT_MOST)
22394                sb.append("AT_MOST ");
22395            else
22396                sb.append(mode).append(" ");
22397
22398            sb.append(size);
22399            return sb.toString();
22400        }
22401    }
22402
22403    private final class CheckForLongPress implements Runnable {
22404        private int mOriginalWindowAttachCount;
22405        private float mX;
22406        private float mY;
22407
22408        @Override
22409        public void run() {
22410            if (isPressed() && (mParent != null)
22411                    && mOriginalWindowAttachCount == mWindowAttachCount) {
22412                if (performLongClick(mX, mY)) {
22413                    mHasPerformedLongPress = true;
22414                }
22415            }
22416        }
22417
22418        public void setAnchor(float x, float y) {
22419            mX = x;
22420            mY = y;
22421        }
22422
22423        public void rememberWindowAttachCount() {
22424            mOriginalWindowAttachCount = mWindowAttachCount;
22425        }
22426    }
22427
22428    private final class CheckForTap implements Runnable {
22429        public float x;
22430        public float y;
22431
22432        @Override
22433        public void run() {
22434            mPrivateFlags &= ~PFLAG_PREPRESSED;
22435            setPressed(true, x, y);
22436            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
22437        }
22438    }
22439
22440    private final class PerformClick implements Runnable {
22441        @Override
22442        public void run() {
22443            performClick();
22444        }
22445    }
22446
22447    /**
22448     * This method returns a ViewPropertyAnimator object, which can be used to animate
22449     * specific properties on this View.
22450     *
22451     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
22452     */
22453    public ViewPropertyAnimator animate() {
22454        if (mAnimator == null) {
22455            mAnimator = new ViewPropertyAnimator(this);
22456        }
22457        return mAnimator;
22458    }
22459
22460    /**
22461     * Sets the name of the View to be used to identify Views in Transitions.
22462     * Names should be unique in the View hierarchy.
22463     *
22464     * @param transitionName The name of the View to uniquely identify it for Transitions.
22465     */
22466    public final void setTransitionName(String transitionName) {
22467        mTransitionName = transitionName;
22468    }
22469
22470    /**
22471     * Returns the name of the View to be used to identify Views in Transitions.
22472     * Names should be unique in the View hierarchy.
22473     *
22474     * <p>This returns null if the View has not been given a name.</p>
22475     *
22476     * @return The name used of the View to be used to identify Views in Transitions or null
22477     * if no name has been given.
22478     */
22479    @ViewDebug.ExportedProperty
22480    public String getTransitionName() {
22481        return mTransitionName;
22482    }
22483
22484    /**
22485     * @hide
22486     */
22487    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
22488        // Do nothing.
22489    }
22490
22491    /**
22492     * Interface definition for a callback to be invoked when a hardware key event is
22493     * dispatched to this view. The callback will be invoked before the key event is
22494     * given to the view. This is only useful for hardware keyboards; a software input
22495     * method has no obligation to trigger this listener.
22496     */
22497    public interface OnKeyListener {
22498        /**
22499         * Called when a hardware key is dispatched to a view. This allows listeners to
22500         * get a chance to respond before the target view.
22501         * <p>Key presses in software keyboards will generally NOT trigger this method,
22502         * although some may elect to do so in some situations. Do not assume a
22503         * software input method has to be key-based; even if it is, it may use key presses
22504         * in a different way than you expect, so there is no way to reliably catch soft
22505         * input key presses.
22506         *
22507         * @param v The view the key has been dispatched to.
22508         * @param keyCode The code for the physical key that was pressed
22509         * @param event The KeyEvent object containing full information about
22510         *        the event.
22511         * @return True if the listener has consumed the event, false otherwise.
22512         */
22513        boolean onKey(View v, int keyCode, KeyEvent event);
22514    }
22515
22516    /**
22517     * Interface definition for a callback to be invoked when a touch event is
22518     * dispatched to this view. The callback will be invoked before the touch
22519     * event is given to the view.
22520     */
22521    public interface OnTouchListener {
22522        /**
22523         * Called when a touch event is dispatched to a view. This allows listeners to
22524         * get a chance to respond before the target view.
22525         *
22526         * @param v The view the touch event has been dispatched to.
22527         * @param event The MotionEvent object containing full information about
22528         *        the event.
22529         * @return True if the listener has consumed the event, false otherwise.
22530         */
22531        boolean onTouch(View v, MotionEvent event);
22532    }
22533
22534    /**
22535     * Interface definition for a callback to be invoked when a hover event is
22536     * dispatched to this view. The callback will be invoked before the hover
22537     * event is given to the view.
22538     */
22539    public interface OnHoverListener {
22540        /**
22541         * Called when a hover event is dispatched to a view. This allows listeners to
22542         * get a chance to respond before the target view.
22543         *
22544         * @param v The view the hover event has been dispatched to.
22545         * @param event The MotionEvent object containing full information about
22546         *        the event.
22547         * @return True if the listener has consumed the event, false otherwise.
22548         */
22549        boolean onHover(View v, MotionEvent event);
22550    }
22551
22552    /**
22553     * Interface definition for a callback to be invoked when a generic motion event is
22554     * dispatched to this view. The callback will be invoked before the generic motion
22555     * event is given to the view.
22556     */
22557    public interface OnGenericMotionListener {
22558        /**
22559         * Called when a generic motion event is dispatched to a view. This allows listeners to
22560         * get a chance to respond before the target view.
22561         *
22562         * @param v The view the generic motion event has been dispatched to.
22563         * @param event The MotionEvent object containing full information about
22564         *        the event.
22565         * @return True if the listener has consumed the event, false otherwise.
22566         */
22567        boolean onGenericMotion(View v, MotionEvent event);
22568    }
22569
22570    /**
22571     * Interface definition for a callback to be invoked when a view has been clicked and held.
22572     */
22573    public interface OnLongClickListener {
22574        /**
22575         * Called when a view has been clicked and held.
22576         *
22577         * @param v The view that was clicked and held.
22578         *
22579         * @return true if the callback consumed the long click, false otherwise.
22580         */
22581        boolean onLongClick(View v);
22582    }
22583
22584    /**
22585     * Interface definition for a callback to be invoked when a drag is being dispatched
22586     * to this view.  The callback will be invoked before the hosting view's own
22587     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
22588     * onDrag(event) behavior, it should return 'false' from this callback.
22589     *
22590     * <div class="special reference">
22591     * <h3>Developer Guides</h3>
22592     * <p>For a guide to implementing drag and drop features, read the
22593     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22594     * </div>
22595     */
22596    public interface OnDragListener {
22597        /**
22598         * Called when a drag event is dispatched to a view. This allows listeners
22599         * to get a chance to override base View behavior.
22600         *
22601         * @param v The View that received the drag event.
22602         * @param event The {@link android.view.DragEvent} object for the drag event.
22603         * @return {@code true} if the drag event was handled successfully, or {@code false}
22604         * if the drag event was not handled. Note that {@code false} will trigger the View
22605         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
22606         */
22607        boolean onDrag(View v, DragEvent event);
22608    }
22609
22610    /**
22611     * Interface definition for a callback to be invoked when the focus state of
22612     * a view changed.
22613     */
22614    public interface OnFocusChangeListener {
22615        /**
22616         * Called when the focus state of a view has changed.
22617         *
22618         * @param v The view whose state has changed.
22619         * @param hasFocus The new focus state of v.
22620         */
22621        void onFocusChange(View v, boolean hasFocus);
22622    }
22623
22624    /**
22625     * Interface definition for a callback to be invoked when a view is clicked.
22626     */
22627    public interface OnClickListener {
22628        /**
22629         * Called when a view has been clicked.
22630         *
22631         * @param v The view that was clicked.
22632         */
22633        void onClick(View v);
22634    }
22635
22636    /**
22637     * Interface definition for a callback to be invoked when a view is context clicked.
22638     */
22639    public interface OnContextClickListener {
22640        /**
22641         * Called when a view is context clicked.
22642         *
22643         * @param v The view that has been context clicked.
22644         * @return true if the callback consumed the context click, false otherwise.
22645         */
22646        boolean onContextClick(View v);
22647    }
22648
22649    /**
22650     * Interface definition for a callback to be invoked when the context menu
22651     * for this view is being built.
22652     */
22653    public interface OnCreateContextMenuListener {
22654        /**
22655         * Called when the context menu for this view is being built. It is not
22656         * safe to hold onto the menu after this method returns.
22657         *
22658         * @param menu The context menu that is being built
22659         * @param v The view for which the context menu is being built
22660         * @param menuInfo Extra information about the item for which the
22661         *            context menu should be shown. This information will vary
22662         *            depending on the class of v.
22663         */
22664        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
22665    }
22666
22667    /**
22668     * Interface definition for a callback to be invoked when the status bar changes
22669     * visibility.  This reports <strong>global</strong> changes to the system UI
22670     * state, not what the application is requesting.
22671     *
22672     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
22673     */
22674    public interface OnSystemUiVisibilityChangeListener {
22675        /**
22676         * Called when the status bar changes visibility because of a call to
22677         * {@link View#setSystemUiVisibility(int)}.
22678         *
22679         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22680         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
22681         * This tells you the <strong>global</strong> state of these UI visibility
22682         * flags, not what your app is currently applying.
22683         */
22684        public void onSystemUiVisibilityChange(int visibility);
22685    }
22686
22687    /**
22688     * Interface definition for a callback to be invoked when this view is attached
22689     * or detached from its window.
22690     */
22691    public interface OnAttachStateChangeListener {
22692        /**
22693         * Called when the view is attached to a window.
22694         * @param v The view that was attached
22695         */
22696        public void onViewAttachedToWindow(View v);
22697        /**
22698         * Called when the view is detached from a window.
22699         * @param v The view that was detached
22700         */
22701        public void onViewDetachedFromWindow(View v);
22702    }
22703
22704    /**
22705     * Listener for applying window insets on a view in a custom way.
22706     *
22707     * <p>Apps may choose to implement this interface if they want to apply custom policy
22708     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
22709     * is set, its
22710     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
22711     * method will be called instead of the View's own
22712     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
22713     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
22714     * the View's normal behavior as part of its own.</p>
22715     */
22716    public interface OnApplyWindowInsetsListener {
22717        /**
22718         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
22719         * on a View, this listener method will be called instead of the view's own
22720         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
22721         *
22722         * @param v The view applying window insets
22723         * @param insets The insets to apply
22724         * @return The insets supplied, minus any insets that were consumed
22725         */
22726        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
22727    }
22728
22729    private final class UnsetPressedState implements Runnable {
22730        @Override
22731        public void run() {
22732            setPressed(false);
22733        }
22734    }
22735
22736    /**
22737     * Base class for derived classes that want to save and restore their own
22738     * state in {@link android.view.View#onSaveInstanceState()}.
22739     */
22740    public static class BaseSavedState extends AbsSavedState {
22741        String mStartActivityRequestWhoSaved;
22742
22743        /**
22744         * Constructor used when reading from a parcel. Reads the state of the superclass.
22745         *
22746         * @param source parcel to read from
22747         */
22748        public BaseSavedState(Parcel source) {
22749            this(source, null);
22750        }
22751
22752        /**
22753         * Constructor used when reading from a parcel using a given class loader.
22754         * Reads the state of the superclass.
22755         *
22756         * @param source parcel to read from
22757         * @param loader ClassLoader to use for reading
22758         */
22759        public BaseSavedState(Parcel source, ClassLoader loader) {
22760            super(source, loader);
22761            mStartActivityRequestWhoSaved = source.readString();
22762        }
22763
22764        /**
22765         * Constructor called by derived classes when creating their SavedState objects
22766         *
22767         * @param superState The state of the superclass of this view
22768         */
22769        public BaseSavedState(Parcelable superState) {
22770            super(superState);
22771        }
22772
22773        @Override
22774        public void writeToParcel(Parcel out, int flags) {
22775            super.writeToParcel(out, flags);
22776            out.writeString(mStartActivityRequestWhoSaved);
22777        }
22778
22779        public static final Parcelable.Creator<BaseSavedState> CREATOR
22780                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
22781            @Override
22782            public BaseSavedState createFromParcel(Parcel in) {
22783                return new BaseSavedState(in);
22784            }
22785
22786            @Override
22787            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
22788                return new BaseSavedState(in, loader);
22789            }
22790
22791            @Override
22792            public BaseSavedState[] newArray(int size) {
22793                return new BaseSavedState[size];
22794            }
22795        };
22796    }
22797
22798    /**
22799     * A set of information given to a view when it is attached to its parent
22800     * window.
22801     */
22802    final static class AttachInfo {
22803        interface Callbacks {
22804            void playSoundEffect(int effectId);
22805            boolean performHapticFeedback(int effectId, boolean always);
22806        }
22807
22808        /**
22809         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
22810         * to a Handler. This class contains the target (View) to invalidate and
22811         * the coordinates of the dirty rectangle.
22812         *
22813         * For performance purposes, this class also implements a pool of up to
22814         * POOL_LIMIT objects that get reused. This reduces memory allocations
22815         * whenever possible.
22816         */
22817        static class InvalidateInfo {
22818            private static final int POOL_LIMIT = 10;
22819
22820            private static final SynchronizedPool<InvalidateInfo> sPool =
22821                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
22822
22823            View target;
22824
22825            int left;
22826            int top;
22827            int right;
22828            int bottom;
22829
22830            public static InvalidateInfo obtain() {
22831                InvalidateInfo instance = sPool.acquire();
22832                return (instance != null) ? instance : new InvalidateInfo();
22833            }
22834
22835            public void recycle() {
22836                target = null;
22837                sPool.release(this);
22838            }
22839        }
22840
22841        final IWindowSession mSession;
22842
22843        final IWindow mWindow;
22844
22845        final IBinder mWindowToken;
22846
22847        final Display mDisplay;
22848
22849        final Callbacks mRootCallbacks;
22850
22851        IWindowId mIWindowId;
22852        WindowId mWindowId;
22853
22854        /**
22855         * The top view of the hierarchy.
22856         */
22857        View mRootView;
22858
22859        IBinder mPanelParentWindowToken;
22860
22861        boolean mHardwareAccelerated;
22862        boolean mHardwareAccelerationRequested;
22863        ThreadedRenderer mHardwareRenderer;
22864        List<RenderNode> mPendingAnimatingRenderNodes;
22865
22866        /**
22867         * The state of the display to which the window is attached, as reported
22868         * by {@link Display#getState()}.  Note that the display state constants
22869         * declared by {@link Display} do not exactly line up with the screen state
22870         * constants declared by {@link View} (there are more display states than
22871         * screen states).
22872         */
22873        int mDisplayState = Display.STATE_UNKNOWN;
22874
22875        /**
22876         * Scale factor used by the compatibility mode
22877         */
22878        float mApplicationScale;
22879
22880        /**
22881         * Indicates whether the application is in compatibility mode
22882         */
22883        boolean mScalingRequired;
22884
22885        /**
22886         * Left position of this view's window
22887         */
22888        int mWindowLeft;
22889
22890        /**
22891         * Top position of this view's window
22892         */
22893        int mWindowTop;
22894
22895        /**
22896         * Indicates whether views need to use 32-bit drawing caches
22897         */
22898        boolean mUse32BitDrawingCache;
22899
22900        /**
22901         * For windows that are full-screen but using insets to layout inside
22902         * of the screen areas, these are the current insets to appear inside
22903         * the overscan area of the display.
22904         */
22905        final Rect mOverscanInsets = new Rect();
22906
22907        /**
22908         * For windows that are full-screen but using insets to layout inside
22909         * of the screen decorations, these are the current insets for the
22910         * content of the window.
22911         */
22912        final Rect mContentInsets = new Rect();
22913
22914        /**
22915         * For windows that are full-screen but using insets to layout inside
22916         * of the screen decorations, these are the current insets for the
22917         * actual visible parts of the window.
22918         */
22919        final Rect mVisibleInsets = new Rect();
22920
22921        /**
22922         * For windows that are full-screen but using insets to layout inside
22923         * of the screen decorations, these are the current insets for the
22924         * stable system windows.
22925         */
22926        final Rect mStableInsets = new Rect();
22927
22928        /**
22929         * For windows that include areas that are not covered by real surface these are the outsets
22930         * for real surface.
22931         */
22932        final Rect mOutsets = new Rect();
22933
22934        /**
22935         * In multi-window we force show the navigation bar. Because we don't want that the surface
22936         * size changes in this mode, we instead have a flag whether the navigation bar size should
22937         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
22938         */
22939        boolean mAlwaysConsumeNavBar;
22940
22941        /**
22942         * The internal insets given by this window.  This value is
22943         * supplied by the client (through
22944         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
22945         * be given to the window manager when changed to be used in laying
22946         * out windows behind it.
22947         */
22948        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
22949                = new ViewTreeObserver.InternalInsetsInfo();
22950
22951        /**
22952         * Set to true when mGivenInternalInsets is non-empty.
22953         */
22954        boolean mHasNonEmptyGivenInternalInsets;
22955
22956        /**
22957         * All views in the window's hierarchy that serve as scroll containers,
22958         * used to determine if the window can be resized or must be panned
22959         * to adjust for a soft input area.
22960         */
22961        final ArrayList<View> mScrollContainers = new ArrayList<View>();
22962
22963        final KeyEvent.DispatcherState mKeyDispatchState
22964                = new KeyEvent.DispatcherState();
22965
22966        /**
22967         * Indicates whether the view's window currently has the focus.
22968         */
22969        boolean mHasWindowFocus;
22970
22971        /**
22972         * The current visibility of the window.
22973         */
22974        int mWindowVisibility;
22975
22976        /**
22977         * Indicates the time at which drawing started to occur.
22978         */
22979        long mDrawingTime;
22980
22981        /**
22982         * Indicates whether or not ignoring the DIRTY_MASK flags.
22983         */
22984        boolean mIgnoreDirtyState;
22985
22986        /**
22987         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
22988         * to avoid clearing that flag prematurely.
22989         */
22990        boolean mSetIgnoreDirtyState = false;
22991
22992        /**
22993         * Indicates whether the view's window is currently in touch mode.
22994         */
22995        boolean mInTouchMode;
22996
22997        /**
22998         * Indicates whether the view has requested unbuffered input dispatching for the current
22999         * event stream.
23000         */
23001        boolean mUnbufferedDispatchRequested;
23002
23003        /**
23004         * Indicates that ViewAncestor should trigger a global layout change
23005         * the next time it performs a traversal
23006         */
23007        boolean mRecomputeGlobalAttributes;
23008
23009        /**
23010         * Always report new attributes at next traversal.
23011         */
23012        boolean mForceReportNewAttributes;
23013
23014        /**
23015         * Set during a traveral if any views want to keep the screen on.
23016         */
23017        boolean mKeepScreenOn;
23018
23019        /**
23020         * Set during a traveral if the light center needs to be updated.
23021         */
23022        boolean mNeedsUpdateLightCenter;
23023
23024        /**
23025         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
23026         */
23027        int mSystemUiVisibility;
23028
23029        /**
23030         * Hack to force certain system UI visibility flags to be cleared.
23031         */
23032        int mDisabledSystemUiVisibility;
23033
23034        /**
23035         * Last global system UI visibility reported by the window manager.
23036         */
23037        int mGlobalSystemUiVisibility = -1;
23038
23039        /**
23040         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
23041         * attached.
23042         */
23043        boolean mHasSystemUiListeners;
23044
23045        /**
23046         * Set if the window has requested to extend into the overscan region
23047         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
23048         */
23049        boolean mOverscanRequested;
23050
23051        /**
23052         * Set if the visibility of any views has changed.
23053         */
23054        boolean mViewVisibilityChanged;
23055
23056        /**
23057         * Set to true if a view has been scrolled.
23058         */
23059        boolean mViewScrollChanged;
23060
23061        /**
23062         * Set to true if high contrast mode enabled
23063         */
23064        boolean mHighContrastText;
23065
23066        /**
23067         * Set to true if a pointer event is currently being handled.
23068         */
23069        boolean mHandlingPointerEvent;
23070
23071        /**
23072         * Global to the view hierarchy used as a temporary for dealing with
23073         * x/y points in the transparent region computations.
23074         */
23075        final int[] mTransparentLocation = new int[2];
23076
23077        /**
23078         * Global to the view hierarchy used as a temporary for dealing with
23079         * x/y points in the ViewGroup.invalidateChild implementation.
23080         */
23081        final int[] mInvalidateChildLocation = new int[2];
23082
23083        /**
23084         * Global to the view hierarchy used as a temporary for dealing with
23085         * computing absolute on-screen location.
23086         */
23087        final int[] mTmpLocation = new int[2];
23088
23089        /**
23090         * Global to the view hierarchy used as a temporary for dealing with
23091         * x/y location when view is transformed.
23092         */
23093        final float[] mTmpTransformLocation = new float[2];
23094
23095        /**
23096         * The view tree observer used to dispatch global events like
23097         * layout, pre-draw, touch mode change, etc.
23098         */
23099        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
23100
23101        /**
23102         * A Canvas used by the view hierarchy to perform bitmap caching.
23103         */
23104        Canvas mCanvas;
23105
23106        /**
23107         * The view root impl.
23108         */
23109        final ViewRootImpl mViewRootImpl;
23110
23111        /**
23112         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
23113         * handler can be used to pump events in the UI events queue.
23114         */
23115        final Handler mHandler;
23116
23117        /**
23118         * Temporary for use in computing invalidate rectangles while
23119         * calling up the hierarchy.
23120         */
23121        final Rect mTmpInvalRect = new Rect();
23122
23123        /**
23124         * Temporary for use in computing hit areas with transformed views
23125         */
23126        final RectF mTmpTransformRect = new RectF();
23127
23128        /**
23129         * Temporary for use in computing hit areas with transformed views
23130         */
23131        final RectF mTmpTransformRect1 = new RectF();
23132
23133        /**
23134         * Temporary list of rectanges.
23135         */
23136        final List<RectF> mTmpRectList = new ArrayList<>();
23137
23138        /**
23139         * Temporary for use in transforming invalidation rect
23140         */
23141        final Matrix mTmpMatrix = new Matrix();
23142
23143        /**
23144         * Temporary for use in transforming invalidation rect
23145         */
23146        final Transformation mTmpTransformation = new Transformation();
23147
23148        /**
23149         * Temporary for use in querying outlines from OutlineProviders
23150         */
23151        final Outline mTmpOutline = new Outline();
23152
23153        /**
23154         * Temporary list for use in collecting focusable descendents of a view.
23155         */
23156        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
23157
23158        /**
23159         * The id of the window for accessibility purposes.
23160         */
23161        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
23162
23163        /**
23164         * Flags related to accessibility processing.
23165         *
23166         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
23167         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
23168         */
23169        int mAccessibilityFetchFlags;
23170
23171        /**
23172         * The drawable for highlighting accessibility focus.
23173         */
23174        Drawable mAccessibilityFocusDrawable;
23175
23176        /**
23177         * Show where the margins, bounds and layout bounds are for each view.
23178         */
23179        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
23180
23181        /**
23182         * Point used to compute visible regions.
23183         */
23184        final Point mPoint = new Point();
23185
23186        /**
23187         * Used to track which View originated a requestLayout() call, used when
23188         * requestLayout() is called during layout.
23189         */
23190        View mViewRequestingLayout;
23191
23192        /**
23193         * Used to track views that need (at least) a partial relayout at their current size
23194         * during the next traversal.
23195         */
23196        List<View> mPartialLayoutViews = new ArrayList<>();
23197
23198        /**
23199         * Swapped with mPartialLayoutViews during layout to avoid concurrent
23200         * modification. Lazily assigned during ViewRootImpl layout.
23201         */
23202        List<View> mEmptyPartialLayoutViews;
23203
23204        /**
23205         * Used to track the identity of the current drag operation.
23206         */
23207        IBinder mDragToken;
23208
23209        /**
23210         * The drag shadow surface for the current drag operation.
23211         */
23212        public Surface mDragSurface;
23213
23214        /**
23215         * Creates a new set of attachment information with the specified
23216         * events handler and thread.
23217         *
23218         * @param handler the events handler the view must use
23219         */
23220        AttachInfo(IWindowSession session, IWindow window, Display display,
23221                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
23222            mSession = session;
23223            mWindow = window;
23224            mWindowToken = window.asBinder();
23225            mDisplay = display;
23226            mViewRootImpl = viewRootImpl;
23227            mHandler = handler;
23228            mRootCallbacks = effectPlayer;
23229        }
23230    }
23231
23232    /**
23233     * <p>ScrollabilityCache holds various fields used by a View when scrolling
23234     * is supported. This avoids keeping too many unused fields in most
23235     * instances of View.</p>
23236     */
23237    private static class ScrollabilityCache implements Runnable {
23238
23239        /**
23240         * Scrollbars are not visible
23241         */
23242        public static final int OFF = 0;
23243
23244        /**
23245         * Scrollbars are visible
23246         */
23247        public static final int ON = 1;
23248
23249        /**
23250         * Scrollbars are fading away
23251         */
23252        public static final int FADING = 2;
23253
23254        public boolean fadeScrollBars;
23255
23256        public int fadingEdgeLength;
23257        public int scrollBarDefaultDelayBeforeFade;
23258        public int scrollBarFadeDuration;
23259
23260        public int scrollBarSize;
23261        public ScrollBarDrawable scrollBar;
23262        public float[] interpolatorValues;
23263        public View host;
23264
23265        public final Paint paint;
23266        public final Matrix matrix;
23267        public Shader shader;
23268
23269        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
23270
23271        private static final float[] OPAQUE = { 255 };
23272        private static final float[] TRANSPARENT = { 0.0f };
23273
23274        /**
23275         * When fading should start. This time moves into the future every time
23276         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
23277         */
23278        public long fadeStartTime;
23279
23280
23281        /**
23282         * The current state of the scrollbars: ON, OFF, or FADING
23283         */
23284        public int state = OFF;
23285
23286        private int mLastColor;
23287
23288        public final Rect mScrollBarBounds = new Rect();
23289
23290        public static final int NOT_DRAGGING = 0;
23291        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
23292        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
23293        public int mScrollBarDraggingState = NOT_DRAGGING;
23294
23295        public float mScrollBarDraggingPos = 0;
23296
23297        public ScrollabilityCache(ViewConfiguration configuration, View host) {
23298            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
23299            scrollBarSize = configuration.getScaledScrollBarSize();
23300            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
23301            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
23302
23303            paint = new Paint();
23304            matrix = new Matrix();
23305            // use use a height of 1, and then wack the matrix each time we
23306            // actually use it.
23307            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23308            paint.setShader(shader);
23309            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23310
23311            this.host = host;
23312        }
23313
23314        public void setFadeColor(int color) {
23315            if (color != mLastColor) {
23316                mLastColor = color;
23317
23318                if (color != 0) {
23319                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
23320                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
23321                    paint.setShader(shader);
23322                    // Restore the default transfer mode (src_over)
23323                    paint.setXfermode(null);
23324                } else {
23325                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23326                    paint.setShader(shader);
23327                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23328                }
23329            }
23330        }
23331
23332        public void run() {
23333            long now = AnimationUtils.currentAnimationTimeMillis();
23334            if (now >= fadeStartTime) {
23335
23336                // the animation fades the scrollbars out by changing
23337                // the opacity (alpha) from fully opaque to fully
23338                // transparent
23339                int nextFrame = (int) now;
23340                int framesCount = 0;
23341
23342                Interpolator interpolator = scrollBarInterpolator;
23343
23344                // Start opaque
23345                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
23346
23347                // End transparent
23348                nextFrame += scrollBarFadeDuration;
23349                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
23350
23351                state = FADING;
23352
23353                // Kick off the fade animation
23354                host.invalidate(true);
23355            }
23356        }
23357    }
23358
23359    /**
23360     * Resuable callback for sending
23361     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
23362     */
23363    private class SendViewScrolledAccessibilityEvent implements Runnable {
23364        public volatile boolean mIsPending;
23365
23366        public void run() {
23367            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
23368            mIsPending = false;
23369        }
23370    }
23371
23372    /**
23373     * <p>
23374     * This class represents a delegate that can be registered in a {@link View}
23375     * to enhance accessibility support via composition rather via inheritance.
23376     * It is specifically targeted to widget developers that extend basic View
23377     * classes i.e. classes in package android.view, that would like their
23378     * applications to be backwards compatible.
23379     * </p>
23380     * <div class="special reference">
23381     * <h3>Developer Guides</h3>
23382     * <p>For more information about making applications accessible, read the
23383     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
23384     * developer guide.</p>
23385     * </div>
23386     * <p>
23387     * A scenario in which a developer would like to use an accessibility delegate
23388     * is overriding a method introduced in a later API version then the minimal API
23389     * version supported by the application. For example, the method
23390     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
23391     * in API version 4 when the accessibility APIs were first introduced. If a
23392     * developer would like his application to run on API version 4 devices (assuming
23393     * all other APIs used by the application are version 4 or lower) and take advantage
23394     * of this method, instead of overriding the method which would break the application's
23395     * backwards compatibility, he can override the corresponding method in this
23396     * delegate and register the delegate in the target View if the API version of
23397     * the system is high enough i.e. the API version is same or higher to the API
23398     * version that introduced
23399     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
23400     * </p>
23401     * <p>
23402     * Here is an example implementation:
23403     * </p>
23404     * <code><pre><p>
23405     * if (Build.VERSION.SDK_INT >= 14) {
23406     *     // If the API version is equal of higher than the version in
23407     *     // which onInitializeAccessibilityNodeInfo was introduced we
23408     *     // register a delegate with a customized implementation.
23409     *     View view = findViewById(R.id.view_id);
23410     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
23411     *         public void onInitializeAccessibilityNodeInfo(View host,
23412     *                 AccessibilityNodeInfo info) {
23413     *             // Let the default implementation populate the info.
23414     *             super.onInitializeAccessibilityNodeInfo(host, info);
23415     *             // Set some other information.
23416     *             info.setEnabled(host.isEnabled());
23417     *         }
23418     *     });
23419     * }
23420     * </code></pre></p>
23421     * <p>
23422     * This delegate contains methods that correspond to the accessibility methods
23423     * in View. If a delegate has been specified the implementation in View hands
23424     * off handling to the corresponding method in this delegate. The default
23425     * implementation the delegate methods behaves exactly as the corresponding
23426     * method in View for the case of no accessibility delegate been set. Hence,
23427     * to customize the behavior of a View method, clients can override only the
23428     * corresponding delegate method without altering the behavior of the rest
23429     * accessibility related methods of the host view.
23430     * </p>
23431     * <p>
23432     * <strong>Note:</strong> On platform versions prior to
23433     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
23434     * views in the {@code android.widget.*} package are called <i>before</i>
23435     * host methods. This prevents certain properties such as class name from
23436     * being modified by overriding
23437     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
23438     * as any changes will be overwritten by the host class.
23439     * <p>
23440     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
23441     * methods are called <i>after</i> host methods, which all properties to be
23442     * modified without being overwritten by the host class.
23443     */
23444    public static class AccessibilityDelegate {
23445
23446        /**
23447         * Sends an accessibility event of the given type. If accessibility is not
23448         * enabled this method has no effect.
23449         * <p>
23450         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
23451         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
23452         * been set.
23453         * </p>
23454         *
23455         * @param host The View hosting the delegate.
23456         * @param eventType The type of the event to send.
23457         *
23458         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
23459         */
23460        public void sendAccessibilityEvent(View host, int eventType) {
23461            host.sendAccessibilityEventInternal(eventType);
23462        }
23463
23464        /**
23465         * Performs the specified accessibility action on the view. For
23466         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
23467         * <p>
23468         * The default implementation behaves as
23469         * {@link View#performAccessibilityAction(int, Bundle)
23470         *  View#performAccessibilityAction(int, Bundle)} for the case of
23471         *  no accessibility delegate been set.
23472         * </p>
23473         *
23474         * @param action The action to perform.
23475         * @return Whether the action was performed.
23476         *
23477         * @see View#performAccessibilityAction(int, Bundle)
23478         *      View#performAccessibilityAction(int, Bundle)
23479         */
23480        public boolean performAccessibilityAction(View host, int action, Bundle args) {
23481            return host.performAccessibilityActionInternal(action, args);
23482        }
23483
23484        /**
23485         * Sends an accessibility event. This method behaves exactly as
23486         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
23487         * empty {@link AccessibilityEvent} and does not perform a check whether
23488         * accessibility is enabled.
23489         * <p>
23490         * The default implementation behaves as
23491         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23492         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
23493         * the case of no accessibility delegate been set.
23494         * </p>
23495         *
23496         * @param host The View hosting the delegate.
23497         * @param event The event to send.
23498         *
23499         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23500         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23501         */
23502        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
23503            host.sendAccessibilityEventUncheckedInternal(event);
23504        }
23505
23506        /**
23507         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
23508         * to its children for adding their text content to the event.
23509         * <p>
23510         * The default implementation behaves as
23511         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23512         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
23513         * the case of no accessibility delegate been set.
23514         * </p>
23515         *
23516         * @param host The View hosting the delegate.
23517         * @param event The event.
23518         * @return True if the event population was completed.
23519         *
23520         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23521         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23522         */
23523        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23524            return host.dispatchPopulateAccessibilityEventInternal(event);
23525        }
23526
23527        /**
23528         * Gives a chance to the host View to populate the accessibility event with its
23529         * text content.
23530         * <p>
23531         * The default implementation behaves as
23532         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
23533         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
23534         * the case of no accessibility delegate been set.
23535         * </p>
23536         *
23537         * @param host The View hosting the delegate.
23538         * @param event The accessibility event which to populate.
23539         *
23540         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
23541         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
23542         */
23543        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23544            host.onPopulateAccessibilityEventInternal(event);
23545        }
23546
23547        /**
23548         * Initializes an {@link AccessibilityEvent} with information about the
23549         * the host View which is the event source.
23550         * <p>
23551         * The default implementation behaves as
23552         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
23553         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
23554         * the case of no accessibility delegate been set.
23555         * </p>
23556         *
23557         * @param host The View hosting the delegate.
23558         * @param event The event to initialize.
23559         *
23560         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
23561         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
23562         */
23563        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
23564            host.onInitializeAccessibilityEventInternal(event);
23565        }
23566
23567        /**
23568         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
23569         * <p>
23570         * The default implementation behaves as
23571         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23572         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
23573         * the case of no accessibility delegate been set.
23574         * </p>
23575         *
23576         * @param host The View hosting the delegate.
23577         * @param info The instance to initialize.
23578         *
23579         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23580         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23581         */
23582        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
23583            host.onInitializeAccessibilityNodeInfoInternal(info);
23584        }
23585
23586        /**
23587         * Called when a child of the host View has requested sending an
23588         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
23589         * to augment the event.
23590         * <p>
23591         * The default implementation behaves as
23592         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23593         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
23594         * the case of no accessibility delegate been set.
23595         * </p>
23596         *
23597         * @param host The View hosting the delegate.
23598         * @param child The child which requests sending the event.
23599         * @param event The event to be sent.
23600         * @return True if the event should be sent
23601         *
23602         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23603         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23604         */
23605        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
23606                AccessibilityEvent event) {
23607            return host.onRequestSendAccessibilityEventInternal(child, event);
23608        }
23609
23610        /**
23611         * Gets the provider for managing a virtual view hierarchy rooted at this View
23612         * and reported to {@link android.accessibilityservice.AccessibilityService}s
23613         * that explore the window content.
23614         * <p>
23615         * The default implementation behaves as
23616         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
23617         * the case of no accessibility delegate been set.
23618         * </p>
23619         *
23620         * @return The provider.
23621         *
23622         * @see AccessibilityNodeProvider
23623         */
23624        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
23625            return null;
23626        }
23627
23628        /**
23629         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
23630         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
23631         * This method is responsible for obtaining an accessibility node info from a
23632         * pool of reusable instances and calling
23633         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
23634         * view to initialize the former.
23635         * <p>
23636         * <strong>Note:</strong> The client is responsible for recycling the obtained
23637         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
23638         * creation.
23639         * </p>
23640         * <p>
23641         * The default implementation behaves as
23642         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
23643         * the case of no accessibility delegate been set.
23644         * </p>
23645         * @return A populated {@link AccessibilityNodeInfo}.
23646         *
23647         * @see AccessibilityNodeInfo
23648         *
23649         * @hide
23650         */
23651        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
23652            return host.createAccessibilityNodeInfoInternal();
23653        }
23654    }
23655
23656    private class MatchIdPredicate implements Predicate<View> {
23657        public int mId;
23658
23659        @Override
23660        public boolean apply(View view) {
23661            return (view.mID == mId);
23662        }
23663    }
23664
23665    private class MatchLabelForPredicate implements Predicate<View> {
23666        private int mLabeledId;
23667
23668        @Override
23669        public boolean apply(View view) {
23670            return (view.mLabelForId == mLabeledId);
23671        }
23672    }
23673
23674    private class SendViewStateChangedAccessibilityEvent implements Runnable {
23675        private int mChangeTypes = 0;
23676        private boolean mPosted;
23677        private boolean mPostedWithDelay;
23678        private long mLastEventTimeMillis;
23679
23680        @Override
23681        public void run() {
23682            mPosted = false;
23683            mPostedWithDelay = false;
23684            mLastEventTimeMillis = SystemClock.uptimeMillis();
23685            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
23686                final AccessibilityEvent event = AccessibilityEvent.obtain();
23687                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
23688                event.setContentChangeTypes(mChangeTypes);
23689                sendAccessibilityEventUnchecked(event);
23690            }
23691            mChangeTypes = 0;
23692        }
23693
23694        public void runOrPost(int changeType) {
23695            mChangeTypes |= changeType;
23696
23697            // If this is a live region or the child of a live region, collect
23698            // all events from this frame and send them on the next frame.
23699            if (inLiveRegion()) {
23700                // If we're already posted with a delay, remove that.
23701                if (mPostedWithDelay) {
23702                    removeCallbacks(this);
23703                    mPostedWithDelay = false;
23704                }
23705                // Only post if we're not already posted.
23706                if (!mPosted) {
23707                    post(this);
23708                    mPosted = true;
23709                }
23710                return;
23711            }
23712
23713            if (mPosted) {
23714                return;
23715            }
23716
23717            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
23718            final long minEventIntevalMillis =
23719                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
23720            if (timeSinceLastMillis >= minEventIntevalMillis) {
23721                removeCallbacks(this);
23722                run();
23723            } else {
23724                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
23725                mPostedWithDelay = true;
23726            }
23727        }
23728    }
23729
23730    private boolean inLiveRegion() {
23731        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23732            return true;
23733        }
23734
23735        ViewParent parent = getParent();
23736        while (parent instanceof View) {
23737            if (((View) parent).getAccessibilityLiveRegion()
23738                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23739                return true;
23740            }
23741            parent = parent.getParent();
23742        }
23743
23744        return false;
23745    }
23746
23747    /**
23748     * Dump all private flags in readable format, useful for documentation and
23749     * sanity checking.
23750     */
23751    private static void dumpFlags() {
23752        final HashMap<String, String> found = Maps.newHashMap();
23753        try {
23754            for (Field field : View.class.getDeclaredFields()) {
23755                final int modifiers = field.getModifiers();
23756                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
23757                    if (field.getType().equals(int.class)) {
23758                        final int value = field.getInt(null);
23759                        dumpFlag(found, field.getName(), value);
23760                    } else if (field.getType().equals(int[].class)) {
23761                        final int[] values = (int[]) field.get(null);
23762                        for (int i = 0; i < values.length; i++) {
23763                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
23764                        }
23765                    }
23766                }
23767            }
23768        } catch (IllegalAccessException e) {
23769            throw new RuntimeException(e);
23770        }
23771
23772        final ArrayList<String> keys = Lists.newArrayList();
23773        keys.addAll(found.keySet());
23774        Collections.sort(keys);
23775        for (String key : keys) {
23776            Log.d(VIEW_LOG_TAG, found.get(key));
23777        }
23778    }
23779
23780    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
23781        // Sort flags by prefix, then by bits, always keeping unique keys
23782        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
23783        final int prefix = name.indexOf('_');
23784        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
23785        final String output = bits + " " + name;
23786        found.put(key, output);
23787    }
23788
23789    /** {@hide} */
23790    public void encode(@NonNull ViewHierarchyEncoder stream) {
23791        stream.beginObject(this);
23792        encodeProperties(stream);
23793        stream.endObject();
23794    }
23795
23796    /** {@hide} */
23797    @CallSuper
23798    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
23799        Object resolveId = ViewDebug.resolveId(getContext(), mID);
23800        if (resolveId instanceof String) {
23801            stream.addProperty("id", (String) resolveId);
23802        } else {
23803            stream.addProperty("id", mID);
23804        }
23805
23806        stream.addProperty("misc:transformation.alpha",
23807                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
23808        stream.addProperty("misc:transitionName", getTransitionName());
23809
23810        // layout
23811        stream.addProperty("layout:left", mLeft);
23812        stream.addProperty("layout:right", mRight);
23813        stream.addProperty("layout:top", mTop);
23814        stream.addProperty("layout:bottom", mBottom);
23815        stream.addProperty("layout:width", getWidth());
23816        stream.addProperty("layout:height", getHeight());
23817        stream.addProperty("layout:layoutDirection", getLayoutDirection());
23818        stream.addProperty("layout:layoutRtl", isLayoutRtl());
23819        stream.addProperty("layout:hasTransientState", hasTransientState());
23820        stream.addProperty("layout:baseline", getBaseline());
23821
23822        // layout params
23823        ViewGroup.LayoutParams layoutParams = getLayoutParams();
23824        if (layoutParams != null) {
23825            stream.addPropertyKey("layoutParams");
23826            layoutParams.encode(stream);
23827        }
23828
23829        // scrolling
23830        stream.addProperty("scrolling:scrollX", mScrollX);
23831        stream.addProperty("scrolling:scrollY", mScrollY);
23832
23833        // padding
23834        stream.addProperty("padding:paddingLeft", mPaddingLeft);
23835        stream.addProperty("padding:paddingRight", mPaddingRight);
23836        stream.addProperty("padding:paddingTop", mPaddingTop);
23837        stream.addProperty("padding:paddingBottom", mPaddingBottom);
23838        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
23839        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
23840        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
23841        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
23842        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
23843
23844        // measurement
23845        stream.addProperty("measurement:minHeight", mMinHeight);
23846        stream.addProperty("measurement:minWidth", mMinWidth);
23847        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
23848        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
23849
23850        // drawing
23851        stream.addProperty("drawing:elevation", getElevation());
23852        stream.addProperty("drawing:translationX", getTranslationX());
23853        stream.addProperty("drawing:translationY", getTranslationY());
23854        stream.addProperty("drawing:translationZ", getTranslationZ());
23855        stream.addProperty("drawing:rotation", getRotation());
23856        stream.addProperty("drawing:rotationX", getRotationX());
23857        stream.addProperty("drawing:rotationY", getRotationY());
23858        stream.addProperty("drawing:scaleX", getScaleX());
23859        stream.addProperty("drawing:scaleY", getScaleY());
23860        stream.addProperty("drawing:pivotX", getPivotX());
23861        stream.addProperty("drawing:pivotY", getPivotY());
23862        stream.addProperty("drawing:opaque", isOpaque());
23863        stream.addProperty("drawing:alpha", getAlpha());
23864        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
23865        stream.addProperty("drawing:shadow", hasShadow());
23866        stream.addProperty("drawing:solidColor", getSolidColor());
23867        stream.addProperty("drawing:layerType", mLayerType);
23868        stream.addProperty("drawing:willNotDraw", willNotDraw());
23869        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
23870        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
23871        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
23872        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
23873
23874        // focus
23875        stream.addProperty("focus:hasFocus", hasFocus());
23876        stream.addProperty("focus:isFocused", isFocused());
23877        stream.addProperty("focus:isFocusable", isFocusable());
23878        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
23879
23880        stream.addProperty("misc:clickable", isClickable());
23881        stream.addProperty("misc:pressed", isPressed());
23882        stream.addProperty("misc:selected", isSelected());
23883        stream.addProperty("misc:touchMode", isInTouchMode());
23884        stream.addProperty("misc:hovered", isHovered());
23885        stream.addProperty("misc:activated", isActivated());
23886
23887        stream.addProperty("misc:visibility", getVisibility());
23888        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
23889        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
23890
23891        stream.addProperty("misc:enabled", isEnabled());
23892        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
23893        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
23894
23895        // theme attributes
23896        Resources.Theme theme = getContext().getTheme();
23897        if (theme != null) {
23898            stream.addPropertyKey("theme");
23899            theme.encode(stream);
23900        }
23901
23902        // view attribute information
23903        int n = mAttributes != null ? mAttributes.length : 0;
23904        stream.addProperty("meta:__attrCount__", n/2);
23905        for (int i = 0; i < n; i += 2) {
23906            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
23907        }
23908
23909        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
23910
23911        // text
23912        stream.addProperty("text:textDirection", getTextDirection());
23913        stream.addProperty("text:textAlignment", getTextAlignment());
23914
23915        // accessibility
23916        CharSequence contentDescription = getContentDescription();
23917        stream.addProperty("accessibility:contentDescription",
23918                contentDescription == null ? "" : contentDescription.toString());
23919        stream.addProperty("accessibility:labelFor", getLabelFor());
23920        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
23921    }
23922
23923    /**
23924     * Determine if this view is rendered on a round wearable device and is the main view
23925     * on the screen.
23926     */
23927    private boolean shouldDrawRoundScrollbar() {
23928        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
23929            return false;
23930        }
23931
23932        final View rootView = getRootView();
23933        final WindowInsets insets = getRootWindowInsets();
23934
23935        int height = getHeight();
23936        int width = getWidth();
23937        int displayHeight = rootView.getHeight();
23938        int displayWidth = rootView.getWidth();
23939
23940        if (height != displayHeight || width != displayWidth) {
23941            return false;
23942        }
23943
23944        getLocationOnScreen(mAttachInfo.mTmpLocation);
23945        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
23946                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
23947    }
23948}
23949