View.java revision 2dd20a61e959f9a0acb0639664e063101b6e3bac
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.animation.AnimatorInflater;
20import android.animation.StateListAnimator;
21import android.annotation.CallSuper;
22import android.annotation.ColorInt;
23import android.annotation.DrawableRes;
24import android.annotation.FloatRange;
25import android.annotation.IdRes;
26import android.annotation.IntDef;
27import android.annotation.IntRange;
28import android.annotation.LayoutRes;
29import android.annotation.NonNull;
30import android.annotation.Nullable;
31import android.annotation.Size;
32import android.annotation.UiThread;
33import android.content.ClipData;
34import android.content.Context;
35import android.content.ContextWrapper;
36import android.content.Intent;
37import android.content.res.ColorStateList;
38import android.content.res.Configuration;
39import android.content.res.Resources;
40import android.content.res.TypedArray;
41import android.graphics.Bitmap;
42import android.graphics.Canvas;
43import android.graphics.Color;
44import android.graphics.Insets;
45import android.graphics.Interpolator;
46import android.graphics.LinearGradient;
47import android.graphics.Matrix;
48import android.graphics.Outline;
49import android.graphics.Paint;
50import android.graphics.PixelFormat;
51import android.graphics.Point;
52import android.graphics.PorterDuff;
53import android.graphics.PorterDuffXfermode;
54import android.graphics.Rect;
55import android.graphics.RectF;
56import android.graphics.Region;
57import android.graphics.Shader;
58import android.graphics.drawable.ColorDrawable;
59import android.graphics.drawable.Drawable;
60import android.hardware.display.DisplayManagerGlobal;
61import android.os.Build.VERSION_CODES;
62import android.os.Bundle;
63import android.os.Handler;
64import android.os.IBinder;
65import android.os.Parcel;
66import android.os.Parcelable;
67import android.os.RemoteException;
68import android.os.SystemClock;
69import android.os.SystemProperties;
70import android.os.Trace;
71import android.text.TextUtils;
72import android.util.AttributeSet;
73import android.util.FloatProperty;
74import android.util.LayoutDirection;
75import android.util.Log;
76import android.util.LongSparseLongArray;
77import android.util.Pools.SynchronizedPool;
78import android.util.Property;
79import android.util.SparseArray;
80import android.util.StateSet;
81import android.util.SuperNotCalledException;
82import android.util.TypedValue;
83import android.view.ContextMenu.ContextMenuInfo;
84import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
85import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
86import android.view.AccessibilityIterators.TextSegmentIterator;
87import android.view.AccessibilityIterators.WordTextSegmentIterator;
88import android.view.accessibility.AccessibilityEvent;
89import android.view.accessibility.AccessibilityEventSource;
90import android.view.accessibility.AccessibilityManager;
91import android.view.accessibility.AccessibilityNodeInfo;
92import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
93import android.view.accessibility.AccessibilityNodeProvider;
94import android.view.animation.Animation;
95import android.view.animation.AnimationUtils;
96import android.view.animation.Transformation;
97import android.view.inputmethod.EditorInfo;
98import android.view.inputmethod.InputConnection;
99import android.view.inputmethod.InputMethodManager;
100import android.widget.Checkable;
101import android.widget.FrameLayout;
102import android.widget.ScrollBarDrawable;
103import static android.os.Build.VERSION_CODES.*;
104import static java.lang.Math.max;
105
106import com.android.internal.R;
107import com.android.internal.util.Predicate;
108import com.android.internal.view.menu.MenuBuilder;
109import com.android.internal.widget.ScrollBarUtils;
110import com.google.android.collect.Lists;
111import com.google.android.collect.Maps;
112
113import java.lang.NullPointerException;
114import java.lang.annotation.Retention;
115import java.lang.annotation.RetentionPolicy;
116import java.lang.ref.WeakReference;
117import java.lang.reflect.Field;
118import java.lang.reflect.InvocationTargetException;
119import java.lang.reflect.Method;
120import java.lang.reflect.Modifier;
121import java.util.ArrayList;
122import java.util.Arrays;
123import java.util.Collections;
124import java.util.HashMap;
125import java.util.List;
126import java.util.Locale;
127import java.util.Map;
128import java.util.concurrent.CopyOnWriteArrayList;
129import java.util.concurrent.atomic.AtomicInteger;
130
131/**
132 * <p>
133 * This class represents the basic building block for user interface components. A View
134 * occupies a rectangular area on the screen and is responsible for drawing and
135 * event handling. View is the base class for <em>widgets</em>, which are
136 * used to create interactive UI components (buttons, text fields, etc.). The
137 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
138 * are invisible containers that hold other Views (or other ViewGroups) and define
139 * their layout properties.
140 * </p>
141 *
142 * <div class="special reference">
143 * <h3>Developer Guides</h3>
144 * <p>For information about using this class to develop your application's user interface,
145 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
146 * </div>
147 *
148 * <a name="Using"></a>
149 * <h3>Using Views</h3>
150 * <p>
151 * All of the views in a window are arranged in a single tree. You can add views
152 * either from code or by specifying a tree of views in one or more XML layout
153 * files. There are many specialized subclasses of views that act as controls or
154 * are capable of displaying text, images, or other content.
155 * </p>
156 * <p>
157 * Once you have created a tree of views, there are typically a few types of
158 * common operations you may wish to perform:
159 * <ul>
160 * <li><strong>Set properties:</strong> for example setting the text of a
161 * {@link android.widget.TextView}. The available properties and the methods
162 * that set them will vary among the different subclasses of views. Note that
163 * properties that are known at build time can be set in the XML layout
164 * files.</li>
165 * <li><strong>Set focus:</strong> The framework will handle moving focus in
166 * response to user input. To force focus to a specific view, call
167 * {@link #requestFocus}.</li>
168 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
169 * that will be notified when something interesting happens to the view. For
170 * example, all views will let you set a listener to be notified when the view
171 * gains or loses focus. You can register such a listener using
172 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
173 * Other view subclasses offer more specialized listeners. For example, a Button
174 * exposes a listener to notify clients when the button is clicked.</li>
175 * <li><strong>Set visibility:</strong> You can hide or show views using
176 * {@link #setVisibility(int)}.</li>
177 * </ul>
178 * </p>
179 * <p><em>
180 * Note: The Android framework is responsible for measuring, laying out and
181 * drawing views. You should not call methods that perform these actions on
182 * views yourself unless you are actually implementing a
183 * {@link android.view.ViewGroup}.
184 * </em></p>
185 *
186 * <a name="Lifecycle"></a>
187 * <h3>Implementing a Custom View</h3>
188 *
189 * <p>
190 * To implement a custom view, you will usually begin by providing overrides for
191 * some of the standard methods that the framework calls on all views. You do
192 * not need to override all of these methods. In fact, you can start by just
193 * overriding {@link #onDraw(android.graphics.Canvas)}.
194 * <table border="2" width="85%" align="center" cellpadding="5">
195 *     <thead>
196 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
197 *     </thead>
198 *
199 *     <tbody>
200 *     <tr>
201 *         <td rowspan="2">Creation</td>
202 *         <td>Constructors</td>
203 *         <td>There is a form of the constructor that are called when the view
204 *         is created from code and a form that is called when the view is
205 *         inflated from a layout file. The second form should parse and apply
206 *         any attributes defined in the layout file.
207 *         </td>
208 *     </tr>
209 *     <tr>
210 *         <td><code>{@link #onFinishInflate()}</code></td>
211 *         <td>Called after a view and all of its children has been inflated
212 *         from XML.</td>
213 *     </tr>
214 *
215 *     <tr>
216 *         <td rowspan="3">Layout</td>
217 *         <td><code>{@link #onMeasure(int, int)}</code></td>
218 *         <td>Called to determine the size requirements for this view and all
219 *         of its children.
220 *         </td>
221 *     </tr>
222 *     <tr>
223 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
224 *         <td>Called when this view should assign a size and position to all
225 *         of its children.
226 *         </td>
227 *     </tr>
228 *     <tr>
229 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
230 *         <td>Called when the size of this view has changed.
231 *         </td>
232 *     </tr>
233 *
234 *     <tr>
235 *         <td>Drawing</td>
236 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
237 *         <td>Called when the view should render its content.
238 *         </td>
239 *     </tr>
240 *
241 *     <tr>
242 *         <td rowspan="4">Event processing</td>
243 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
244 *         <td>Called when a new hardware key event occurs.
245 *         </td>
246 *     </tr>
247 *     <tr>
248 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
249 *         <td>Called when a hardware key up event occurs.
250 *         </td>
251 *     </tr>
252 *     <tr>
253 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
254 *         <td>Called when a trackball motion event occurs.
255 *         </td>
256 *     </tr>
257 *     <tr>
258 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
259 *         <td>Called when a touch screen motion event occurs.
260 *         </td>
261 *     </tr>
262 *
263 *     <tr>
264 *         <td rowspan="2">Focus</td>
265 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
266 *         <td>Called when the view gains or loses focus.
267 *         </td>
268 *     </tr>
269 *
270 *     <tr>
271 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
272 *         <td>Called when the window containing the view gains or loses focus.
273 *         </td>
274 *     </tr>
275 *
276 *     <tr>
277 *         <td rowspan="3">Attaching</td>
278 *         <td><code>{@link #onAttachedToWindow()}</code></td>
279 *         <td>Called when the view is attached to a window.
280 *         </td>
281 *     </tr>
282 *
283 *     <tr>
284 *         <td><code>{@link #onDetachedFromWindow}</code></td>
285 *         <td>Called when the view is detached from its window.
286 *         </td>
287 *     </tr>
288 *
289 *     <tr>
290 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
291 *         <td>Called when the visibility of the window containing the view
292 *         has changed.
293 *         </td>
294 *     </tr>
295 *     </tbody>
296 *
297 * </table>
298 * </p>
299 *
300 * <a name="IDs"></a>
301 * <h3>IDs</h3>
302 * Views may have an integer id associated with them. These ids are typically
303 * assigned in the layout XML files, and are used to find specific views within
304 * the view tree. A common pattern is to:
305 * <ul>
306 * <li>Define a Button in the layout file and assign it a unique ID.
307 * <pre>
308 * &lt;Button
309 *     android:id="@+id/my_button"
310 *     android:layout_width="wrap_content"
311 *     android:layout_height="wrap_content"
312 *     android:text="@string/my_button_text"/&gt;
313 * </pre></li>
314 * <li>From the onCreate method of an Activity, find the Button
315 * <pre class="prettyprint">
316 *      Button myButton = (Button) findViewById(R.id.my_button);
317 * </pre></li>
318 * </ul>
319 * <p>
320 * View IDs need not be unique throughout the tree, but it is good practice to
321 * ensure that they are at least unique within the part of the tree you are
322 * searching.
323 * </p>
324 *
325 * <a name="Position"></a>
326 * <h3>Position</h3>
327 * <p>
328 * The geometry of a view is that of a rectangle. A view has a location,
329 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
330 * two dimensions, expressed as a width and a height. The unit for location
331 * and dimensions is the pixel.
332 * </p>
333 *
334 * <p>
335 * It is possible to retrieve the location of a view by invoking the methods
336 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
337 * coordinate of the rectangle representing the view. The latter returns the
338 * top, or Y, coordinate of the rectangle representing the view. These methods
339 * both return the location of the view relative to its parent. For instance,
340 * when getLeft() returns 20, that means the view is located 20 pixels to the
341 * right of the left edge of its direct parent.
342 * </p>
343 *
344 * <p>
345 * In addition, several convenience methods are offered to avoid unnecessary
346 * computations, namely {@link #getRight()} and {@link #getBottom()}.
347 * These methods return the coordinates of the right and bottom edges of the
348 * rectangle representing the view. For instance, calling {@link #getRight()}
349 * is similar to the following computation: <code>getLeft() + getWidth()</code>
350 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
351 * </p>
352 *
353 * <a name="SizePaddingMargins"></a>
354 * <h3>Size, padding and margins</h3>
355 * <p>
356 * The size of a view is expressed with a width and a height. A view actually
357 * possess two pairs of width and height values.
358 * </p>
359 *
360 * <p>
361 * The first pair is known as <em>measured width</em> and
362 * <em>measured height</em>. These dimensions define how big a view wants to be
363 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
364 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
365 * and {@link #getMeasuredHeight()}.
366 * </p>
367 *
368 * <p>
369 * The second pair is simply known as <em>width</em> and <em>height</em>, or
370 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
371 * dimensions define the actual size of the view on screen, at drawing time and
372 * after layout. These values may, but do not have to, be different from the
373 * measured width and height. The width and height can be obtained by calling
374 * {@link #getWidth()} and {@link #getHeight()}.
375 * </p>
376 *
377 * <p>
378 * To measure its dimensions, a view takes into account its padding. The padding
379 * is expressed in pixels for the left, top, right and bottom parts of the view.
380 * Padding can be used to offset the content of the view by a specific amount of
381 * pixels. For instance, a left padding of 2 will push the view's content by
382 * 2 pixels to the right of the left edge. Padding can be set using the
383 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
384 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
385 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
386 * {@link #getPaddingEnd()}.
387 * </p>
388 *
389 * <p>
390 * Even though a view can define a padding, it does not provide any support for
391 * margins. However, view groups provide such a support. Refer to
392 * {@link android.view.ViewGroup} and
393 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
394 * </p>
395 *
396 * <a name="Layout"></a>
397 * <h3>Layout</h3>
398 * <p>
399 * Layout is a two pass process: a measure pass and a layout pass. The measuring
400 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
401 * of the view tree. Each view pushes dimension specifications down the tree
402 * during the recursion. At the end of the measure pass, every view has stored
403 * its measurements. The second pass happens in
404 * {@link #layout(int,int,int,int)} and is also top-down. During
405 * this pass each parent is responsible for positioning all of its children
406 * using the sizes computed in the measure pass.
407 * </p>
408 *
409 * <p>
410 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
411 * {@link #getMeasuredHeight()} values must be set, along with those for all of
412 * that view's descendants. A view's measured width and measured height values
413 * must respect the constraints imposed by the view's parents. This guarantees
414 * that at the end of the measure pass, all parents accept all of their
415 * children's measurements. A parent view may call measure() more than once on
416 * its children. For example, the parent may measure each child once with
417 * unspecified dimensions to find out how big they want to be, then call
418 * measure() on them again with actual numbers if the sum of all the children's
419 * unconstrained sizes is too big or too small.
420 * </p>
421 *
422 * <p>
423 * The measure pass uses two classes to communicate dimensions. The
424 * {@link MeasureSpec} class is used by views to tell their parents how they
425 * want to be measured and positioned. The base LayoutParams class just
426 * describes how big the view wants to be for both width and height. For each
427 * dimension, it can specify one of:
428 * <ul>
429 * <li> an exact number
430 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
431 * (minus padding)
432 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
433 * enclose its content (plus padding).
434 * </ul>
435 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
436 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
437 * an X and Y value.
438 * </p>
439 *
440 * <p>
441 * MeasureSpecs are used to push requirements down the tree from parent to
442 * child. A MeasureSpec can be in one of three modes:
443 * <ul>
444 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
445 * of a child view. For example, a LinearLayout may call measure() on its child
446 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
447 * tall the child view wants to be given a width of 240 pixels.
448 * <li>EXACTLY: This is used by the parent to impose an exact size on the
449 * child. The child must use this size, and guarantee that all of its
450 * descendants will fit within this size.
451 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
452 * child. The child must guarantee that it and all of its descendants will fit
453 * within this size.
454 * </ul>
455 * </p>
456 *
457 * <p>
458 * To initiate a layout, call {@link #requestLayout}. This method is typically
459 * called by a view on itself when it believes that is can no longer fit within
460 * its current bounds.
461 * </p>
462 *
463 * <a name="Drawing"></a>
464 * <h3>Drawing</h3>
465 * <p>
466 * Drawing is handled by walking the tree and recording the drawing commands of
467 * any View that needs to update. After this, the drawing commands of the
468 * entire tree are issued to screen, clipped to the newly damaged area.
469 * </p>
470 *
471 * <p>
472 * The tree is largely recorded and drawn in order, with parents drawn before
473 * (i.e., behind) their children, with siblings drawn in the order they appear
474 * in the tree. If you set a background drawable for a View, then the View will
475 * draw it before calling back to its <code>onDraw()</code> method. The child
476 * drawing order can be overridden with
477 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
478 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
479 * </p>
480 *
481 * <p>
482 * To force a view to draw, call {@link #invalidate()}.
483 * </p>
484 *
485 * <a name="EventHandlingThreading"></a>
486 * <h3>Event Handling and Threading</h3>
487 * <p>
488 * The basic cycle of a view is as follows:
489 * <ol>
490 * <li>An event comes in and is dispatched to the appropriate view. The view
491 * handles the event and notifies any listeners.</li>
492 * <li>If in the course of processing the event, the view's bounds may need
493 * to be changed, the view will call {@link #requestLayout()}.</li>
494 * <li>Similarly, if in the course of processing the event the view's appearance
495 * may need to be changed, the view will call {@link #invalidate()}.</li>
496 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
497 * the framework will take care of measuring, laying out, and drawing the tree
498 * as appropriate.</li>
499 * </ol>
500 * </p>
501 *
502 * <p><em>Note: The entire view tree is single threaded. You must always be on
503 * the UI thread when calling any method on any view.</em>
504 * If you are doing work on other threads and want to update the state of a view
505 * from that thread, you should use a {@link Handler}.
506 * </p>
507 *
508 * <a name="FocusHandling"></a>
509 * <h3>Focus Handling</h3>
510 * <p>
511 * The framework will handle routine focus movement in response to user input.
512 * This includes changing the focus as views are removed or hidden, or as new
513 * views become available. Views indicate their willingness to take focus
514 * through the {@link #isFocusable} method. To change whether a view can take
515 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
516 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
517 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
518 * </p>
519 * <p>
520 * Focus movement is based on an algorithm which finds the nearest neighbor in a
521 * given direction. In rare cases, the default algorithm may not match the
522 * intended behavior of the developer. In these situations, you can provide
523 * explicit overrides by using these XML attributes in the layout file:
524 * <pre>
525 * nextFocusDown
526 * nextFocusLeft
527 * nextFocusRight
528 * nextFocusUp
529 * </pre>
530 * </p>
531 *
532 *
533 * <p>
534 * To get a particular view to take focus, call {@link #requestFocus()}.
535 * </p>
536 *
537 * <a name="TouchMode"></a>
538 * <h3>Touch Mode</h3>
539 * <p>
540 * When a user is navigating a user interface via directional keys such as a D-pad, it is
541 * necessary to give focus to actionable items such as buttons so the user can see
542 * what will take input.  If the device has touch capabilities, however, and the user
543 * begins interacting with the interface by touching it, it is no longer necessary to
544 * always highlight, or give focus to, a particular view.  This motivates a mode
545 * for interaction named 'touch mode'.
546 * </p>
547 * <p>
548 * For a touch capable device, once the user touches the screen, the device
549 * will enter touch mode.  From this point onward, only views for which
550 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
551 * Other views that are touchable, like buttons, will not take focus when touched; they will
552 * only fire the on click listeners.
553 * </p>
554 * <p>
555 * Any time a user hits a directional key, such as a D-pad direction, the view device will
556 * exit touch mode, and find a view to take focus, so that the user may resume interacting
557 * with the user interface without touching the screen again.
558 * </p>
559 * <p>
560 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
561 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
562 * </p>
563 *
564 * <a name="Scrolling"></a>
565 * <h3>Scrolling</h3>
566 * <p>
567 * The framework provides basic support for views that wish to internally
568 * scroll their content. This includes keeping track of the X and Y scroll
569 * offset as well as mechanisms for drawing scrollbars. See
570 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
571 * {@link #awakenScrollBars()} for more details.
572 * </p>
573 *
574 * <a name="Tags"></a>
575 * <h3>Tags</h3>
576 * <p>
577 * Unlike IDs, tags are not used to identify views. Tags are essentially an
578 * extra piece of information that can be associated with a view. They are most
579 * often used as a convenience to store data related to views in the views
580 * themselves rather than by putting them in a separate structure.
581 * </p>
582 * <p>
583 * Tags may be specified with character sequence values in layout XML as either
584 * a single tag using the {@link android.R.styleable#View_tag android:tag}
585 * attribute or multiple tags using the {@code <tag>} child element:
586 * <pre>
587 *     &ltView ...
588 *           android:tag="@string/mytag_value" /&gt;
589 *     &ltView ...&gt;
590 *         &lttag android:id="@+id/mytag"
591 *              android:value="@string/mytag_value" /&gt;
592 *     &lt/View>
593 * </pre>
594 * </p>
595 * <p>
596 * Tags may also be specified with arbitrary objects from code using
597 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
598 * </p>
599 *
600 * <a name="Themes"></a>
601 * <h3>Themes</h3>
602 * <p>
603 * By default, Views are created using the theme of the Context object supplied
604 * to their constructor; however, a different theme may be specified by using
605 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
606 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
607 * code.
608 * </p>
609 * <p>
610 * When the {@link android.R.styleable#View_theme android:theme} attribute is
611 * used in XML, the specified theme is applied on top of the inflation
612 * context's theme (see {@link LayoutInflater}) and used for the view itself as
613 * well as any child elements.
614 * </p>
615 * <p>
616 * In the following example, both views will be created using the Material dark
617 * color scheme; however, because an overlay theme is used which only defines a
618 * subset of attributes, the value of
619 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
620 * the inflation context's theme (e.g. the Activity theme) will be preserved.
621 * <pre>
622 *     &ltLinearLayout
623 *             ...
624 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
625 *         &ltView ...&gt;
626 *     &lt/LinearLayout&gt;
627 * </pre>
628 * </p>
629 *
630 * <a name="Properties"></a>
631 * <h3>Properties</h3>
632 * <p>
633 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
634 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
635 * available both in the {@link Property} form as well as in similarly-named setter/getter
636 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
637 * be used to set persistent state associated with these rendering-related properties on the view.
638 * The properties and methods can also be used in conjunction with
639 * {@link android.animation.Animator Animator}-based animations, described more in the
640 * <a href="#Animation">Animation</a> section.
641 * </p>
642 *
643 * <a name="Animation"></a>
644 * <h3>Animation</h3>
645 * <p>
646 * Starting with Android 3.0, the preferred way of animating views is to use the
647 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
648 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
649 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
650 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
651 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
652 * makes animating these View properties particularly easy and efficient.
653 * </p>
654 * <p>
655 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
656 * You can attach an {@link Animation} object to a view using
657 * {@link #setAnimation(Animation)} or
658 * {@link #startAnimation(Animation)}. The animation can alter the scale,
659 * rotation, translation and alpha of a view over time. If the animation is
660 * attached to a view that has children, the animation will affect the entire
661 * subtree rooted by that node. When an animation is started, the framework will
662 * take care of redrawing the appropriate views until the animation completes.
663 * </p>
664 *
665 * <a name="Security"></a>
666 * <h3>Security</h3>
667 * <p>
668 * Sometimes it is essential that an application be able to verify that an action
669 * is being performed with the full knowledge and consent of the user, such as
670 * granting a permission request, making a purchase or clicking on an advertisement.
671 * Unfortunately, a malicious application could try to spoof the user into
672 * performing these actions, unaware, by concealing the intended purpose of the view.
673 * As a remedy, the framework offers a touch filtering mechanism that can be used to
674 * improve the security of views that provide access to sensitive functionality.
675 * </p><p>
676 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
677 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
678 * will discard touches that are received whenever the view's window is obscured by
679 * another visible window.  As a result, the view will not receive touches whenever a
680 * toast, dialog or other window appears above the view's window.
681 * </p><p>
682 * For more fine-grained control over security, consider overriding the
683 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
684 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
685 * </p>
686 *
687 * @attr ref android.R.styleable#View_alpha
688 * @attr ref android.R.styleable#View_background
689 * @attr ref android.R.styleable#View_clickable
690 * @attr ref android.R.styleable#View_contentDescription
691 * @attr ref android.R.styleable#View_drawingCacheQuality
692 * @attr ref android.R.styleable#View_duplicateParentState
693 * @attr ref android.R.styleable#View_id
694 * @attr ref android.R.styleable#View_requiresFadingEdge
695 * @attr ref android.R.styleable#View_fadeScrollbars
696 * @attr ref android.R.styleable#View_fadingEdgeLength
697 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
698 * @attr ref android.R.styleable#View_fitsSystemWindows
699 * @attr ref android.R.styleable#View_isScrollContainer
700 * @attr ref android.R.styleable#View_focusable
701 * @attr ref android.R.styleable#View_focusableInTouchMode
702 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
703 * @attr ref android.R.styleable#View_keepScreenOn
704 * @attr ref android.R.styleable#View_layerType
705 * @attr ref android.R.styleable#View_layoutDirection
706 * @attr ref android.R.styleable#View_longClickable
707 * @attr ref android.R.styleable#View_minHeight
708 * @attr ref android.R.styleable#View_minWidth
709 * @attr ref android.R.styleable#View_nextFocusDown
710 * @attr ref android.R.styleable#View_nextFocusLeft
711 * @attr ref android.R.styleable#View_nextFocusRight
712 * @attr ref android.R.styleable#View_nextFocusUp
713 * @attr ref android.R.styleable#View_onClick
714 * @attr ref android.R.styleable#View_padding
715 * @attr ref android.R.styleable#View_paddingBottom
716 * @attr ref android.R.styleable#View_paddingLeft
717 * @attr ref android.R.styleable#View_paddingRight
718 * @attr ref android.R.styleable#View_paddingTop
719 * @attr ref android.R.styleable#View_paddingStart
720 * @attr ref android.R.styleable#View_paddingEnd
721 * @attr ref android.R.styleable#View_saveEnabled
722 * @attr ref android.R.styleable#View_rotation
723 * @attr ref android.R.styleable#View_rotationX
724 * @attr ref android.R.styleable#View_rotationY
725 * @attr ref android.R.styleable#View_scaleX
726 * @attr ref android.R.styleable#View_scaleY
727 * @attr ref android.R.styleable#View_scrollX
728 * @attr ref android.R.styleable#View_scrollY
729 * @attr ref android.R.styleable#View_scrollbarSize
730 * @attr ref android.R.styleable#View_scrollbarStyle
731 * @attr ref android.R.styleable#View_scrollbars
732 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
733 * @attr ref android.R.styleable#View_scrollbarFadeDuration
734 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
735 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
736 * @attr ref android.R.styleable#View_scrollbarThumbVertical
737 * @attr ref android.R.styleable#View_scrollbarTrackVertical
738 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
739 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
740 * @attr ref android.R.styleable#View_stateListAnimator
741 * @attr ref android.R.styleable#View_transitionName
742 * @attr ref android.R.styleable#View_soundEffectsEnabled
743 * @attr ref android.R.styleable#View_tag
744 * @attr ref android.R.styleable#View_textAlignment
745 * @attr ref android.R.styleable#View_textDirection
746 * @attr ref android.R.styleable#View_transformPivotX
747 * @attr ref android.R.styleable#View_transformPivotY
748 * @attr ref android.R.styleable#View_translationX
749 * @attr ref android.R.styleable#View_translationY
750 * @attr ref android.R.styleable#View_translationZ
751 * @attr ref android.R.styleable#View_visibility
752 * @attr ref android.R.styleable#View_theme
753 *
754 * @see android.view.ViewGroup
755 */
756@UiThread
757public class View implements Drawable.Callback, KeyEvent.Callback,
758        AccessibilityEventSource {
759    private static final boolean DBG = false;
760
761    /**
762     * The logging tag used by this class with android.util.Log.
763     */
764    protected static final String VIEW_LOG_TAG = "View";
765
766    /**
767     * When set to true, apps will draw debugging information about their layouts.
768     *
769     * @hide
770     */
771    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
772
773    /**
774     * When set to true, this view will save its attribute data.
775     *
776     * @hide
777     */
778    public static boolean mDebugViewAttributes = false;
779
780    /**
781     * Used to mark a View that has no ID.
782     */
783    public static final int NO_ID = -1;
784
785    /**
786     * Signals that compatibility booleans have been initialized according to
787     * target SDK versions.
788     */
789    private static boolean sCompatibilityDone = false;
790
791    /**
792     * Use the old (broken) way of building MeasureSpecs.
793     */
794    private static boolean sUseBrokenMakeMeasureSpec = false;
795
796    /**
797     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
798     */
799    static boolean sUseZeroUnspecifiedMeasureSpec = false;
800
801    /**
802     * Ignore any optimizations using the measure cache.
803     */
804    private static boolean sIgnoreMeasureCache = false;
805
806    /**
807     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
808     */
809    private static boolean sAlwaysRemeasureExactly = false;
810
811    /**
812     * Relax constraints around whether setLayoutParams() must be called after
813     * modifying the layout params.
814     */
815    private static boolean sLayoutParamsAlwaysChanged = false;
816
817    /**
818     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
819     * without throwing
820     */
821    static boolean sTextureViewIgnoresDrawableSetters = false;
822
823    /**
824     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
825     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
826     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
827     * check is implemented for backwards compatibility.
828     *
829     * {@hide}
830     */
831    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
832
833
834    /**
835     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
836     * calling setFlags.
837     */
838    private static final int NOT_FOCUSABLE = 0x00000000;
839
840    /**
841     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
842     * setFlags.
843     */
844    private static final int FOCUSABLE = 0x00000001;
845
846    /**
847     * Mask for use with setFlags indicating bits used for focus.
848     */
849    private static final int FOCUSABLE_MASK = 0x00000001;
850
851    /**
852     * This view will adjust its padding to fit sytem windows (e.g. status bar)
853     */
854    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
855
856    /** @hide */
857    @IntDef({VISIBLE, INVISIBLE, GONE})
858    @Retention(RetentionPolicy.SOURCE)
859    public @interface Visibility {}
860
861    /**
862     * This view is visible.
863     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
864     * android:visibility}.
865     */
866    public static final int VISIBLE = 0x00000000;
867
868    /**
869     * This view is invisible, but it still takes up space for layout purposes.
870     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
871     * android:visibility}.
872     */
873    public static final int INVISIBLE = 0x00000004;
874
875    /**
876     * This view is invisible, and it doesn't take any space for layout
877     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
878     * android:visibility}.
879     */
880    public static final int GONE = 0x00000008;
881
882    /**
883     * Mask for use with setFlags indicating bits used for visibility.
884     * {@hide}
885     */
886    static final int VISIBILITY_MASK = 0x0000000C;
887
888    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
889
890    /**
891     * This view is enabled. Interpretation varies by subclass.
892     * Use with ENABLED_MASK when calling setFlags.
893     * {@hide}
894     */
895    static final int ENABLED = 0x00000000;
896
897    /**
898     * This view is disabled. Interpretation varies by subclass.
899     * Use with ENABLED_MASK when calling setFlags.
900     * {@hide}
901     */
902    static final int DISABLED = 0x00000020;
903
904   /**
905    * Mask for use with setFlags indicating bits used for indicating whether
906    * this view is enabled
907    * {@hide}
908    */
909    static final int ENABLED_MASK = 0x00000020;
910
911    /**
912     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
913     * called and further optimizations will be performed. It is okay to have
914     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
915     * {@hide}
916     */
917    static final int WILL_NOT_DRAW = 0x00000080;
918
919    /**
920     * Mask for use with setFlags indicating bits used for indicating whether
921     * this view is will draw
922     * {@hide}
923     */
924    static final int DRAW_MASK = 0x00000080;
925
926    /**
927     * <p>This view doesn't show scrollbars.</p>
928     * {@hide}
929     */
930    static final int SCROLLBARS_NONE = 0x00000000;
931
932    /**
933     * <p>This view shows horizontal scrollbars.</p>
934     * {@hide}
935     */
936    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
937
938    /**
939     * <p>This view shows vertical scrollbars.</p>
940     * {@hide}
941     */
942    static final int SCROLLBARS_VERTICAL = 0x00000200;
943
944    /**
945     * <p>Mask for use with setFlags indicating bits used for indicating which
946     * scrollbars are enabled.</p>
947     * {@hide}
948     */
949    static final int SCROLLBARS_MASK = 0x00000300;
950
951    /**
952     * Indicates that the view should filter touches when its window is obscured.
953     * Refer to the class comments for more information about this security feature.
954     * {@hide}
955     */
956    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
957
958    /**
959     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
960     * that they are optional and should be skipped if the window has
961     * requested system UI flags that ignore those insets for layout.
962     */
963    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
964
965    /**
966     * <p>This view doesn't show fading edges.</p>
967     * {@hide}
968     */
969    static final int FADING_EDGE_NONE = 0x00000000;
970
971    /**
972     * <p>This view shows horizontal fading edges.</p>
973     * {@hide}
974     */
975    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
976
977    /**
978     * <p>This view shows vertical fading edges.</p>
979     * {@hide}
980     */
981    static final int FADING_EDGE_VERTICAL = 0x00002000;
982
983    /**
984     * <p>Mask for use with setFlags indicating bits used for indicating which
985     * fading edges are enabled.</p>
986     * {@hide}
987     */
988    static final int FADING_EDGE_MASK = 0x00003000;
989
990    /**
991     * <p>Indicates this view can be clicked. When clickable, a View reacts
992     * to clicks by notifying the OnClickListener.<p>
993     * {@hide}
994     */
995    static final int CLICKABLE = 0x00004000;
996
997    /**
998     * <p>Indicates this view is caching its drawing into a bitmap.</p>
999     * {@hide}
1000     */
1001    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1002
1003    /**
1004     * <p>Indicates that no icicle should be saved for this view.<p>
1005     * {@hide}
1006     */
1007    static final int SAVE_DISABLED = 0x000010000;
1008
1009    /**
1010     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1011     * property.</p>
1012     * {@hide}
1013     */
1014    static final int SAVE_DISABLED_MASK = 0x000010000;
1015
1016    /**
1017     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1018     * {@hide}
1019     */
1020    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1021
1022    /**
1023     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1024     * {@hide}
1025     */
1026    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1027
1028    /** @hide */
1029    @Retention(RetentionPolicy.SOURCE)
1030    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1031    public @interface DrawingCacheQuality {}
1032
1033    /**
1034     * <p>Enables low quality mode for the drawing cache.</p>
1035     */
1036    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1037
1038    /**
1039     * <p>Enables high quality mode for the drawing cache.</p>
1040     */
1041    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1042
1043    /**
1044     * <p>Enables automatic quality mode for the drawing cache.</p>
1045     */
1046    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1047
1048    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1049            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1050    };
1051
1052    /**
1053     * <p>Mask for use with setFlags indicating bits used for the cache
1054     * quality property.</p>
1055     * {@hide}
1056     */
1057    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1058
1059    /**
1060     * <p>
1061     * Indicates this view can be long clicked. When long clickable, a View
1062     * reacts to long clicks by notifying the OnLongClickListener or showing a
1063     * context menu.
1064     * </p>
1065     * {@hide}
1066     */
1067    static final int LONG_CLICKABLE = 0x00200000;
1068
1069    /**
1070     * <p>Indicates that this view gets its drawable states from its direct parent
1071     * and ignores its original internal states.</p>
1072     *
1073     * @hide
1074     */
1075    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1076
1077    /**
1078     * <p>
1079     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1080     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1081     * OnContextClickListener.
1082     * </p>
1083     * {@hide}
1084     */
1085    static final int CONTEXT_CLICKABLE = 0x00800000;
1086
1087
1088    /** @hide */
1089    @IntDef({
1090        SCROLLBARS_INSIDE_OVERLAY,
1091        SCROLLBARS_INSIDE_INSET,
1092        SCROLLBARS_OUTSIDE_OVERLAY,
1093        SCROLLBARS_OUTSIDE_INSET
1094    })
1095    @Retention(RetentionPolicy.SOURCE)
1096    public @interface ScrollBarStyle {}
1097
1098    /**
1099     * The scrollbar style to display the scrollbars inside the content area,
1100     * without increasing the padding. The scrollbars will be overlaid with
1101     * translucency on the view's content.
1102     */
1103    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1104
1105    /**
1106     * The scrollbar style to display the scrollbars inside the padded area,
1107     * increasing the padding of the view. The scrollbars will not overlap the
1108     * content area of the view.
1109     */
1110    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1111
1112    /**
1113     * The scrollbar style to display the scrollbars at the edge of the view,
1114     * without increasing the padding. The scrollbars will be overlaid with
1115     * translucency.
1116     */
1117    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1118
1119    /**
1120     * The scrollbar style to display the scrollbars at the edge of the view,
1121     * increasing the padding of the view. The scrollbars will only overlap the
1122     * background, if any.
1123     */
1124    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1125
1126    /**
1127     * Mask to check if the scrollbar style is overlay or inset.
1128     * {@hide}
1129     */
1130    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1131
1132    /**
1133     * Mask to check if the scrollbar style is inside or outside.
1134     * {@hide}
1135     */
1136    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1137
1138    /**
1139     * Mask for scrollbar style.
1140     * {@hide}
1141     */
1142    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1143
1144    /**
1145     * View flag indicating that the screen should remain on while the
1146     * window containing this view is visible to the user.  This effectively
1147     * takes care of automatically setting the WindowManager's
1148     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1149     */
1150    public static final int KEEP_SCREEN_ON = 0x04000000;
1151
1152    /**
1153     * View flag indicating whether this view should have sound effects enabled
1154     * for events such as clicking and touching.
1155     */
1156    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1157
1158    /**
1159     * View flag indicating whether this view should have haptic feedback
1160     * enabled for events such as long presses.
1161     */
1162    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1163
1164    /**
1165     * <p>Indicates that the view hierarchy should stop saving state when
1166     * it reaches this view.  If state saving is initiated immediately at
1167     * the view, it will be allowed.
1168     * {@hide}
1169     */
1170    static final int PARENT_SAVE_DISABLED = 0x20000000;
1171
1172    /**
1173     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1174     * {@hide}
1175     */
1176    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1177
1178    /** @hide */
1179    @IntDef(flag = true,
1180            value = {
1181                FOCUSABLES_ALL,
1182                FOCUSABLES_TOUCH_MODE
1183            })
1184    @Retention(RetentionPolicy.SOURCE)
1185    public @interface FocusableMode {}
1186
1187    /**
1188     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1189     * should add all focusable Views regardless if they are focusable in touch mode.
1190     */
1191    public static final int FOCUSABLES_ALL = 0x00000000;
1192
1193    /**
1194     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1195     * should add only Views focusable in touch mode.
1196     */
1197    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1198
1199    /** @hide */
1200    @IntDef({
1201            FOCUS_BACKWARD,
1202            FOCUS_FORWARD,
1203            FOCUS_LEFT,
1204            FOCUS_UP,
1205            FOCUS_RIGHT,
1206            FOCUS_DOWN
1207    })
1208    @Retention(RetentionPolicy.SOURCE)
1209    public @interface FocusDirection {}
1210
1211    /** @hide */
1212    @IntDef({
1213            FOCUS_LEFT,
1214            FOCUS_UP,
1215            FOCUS_RIGHT,
1216            FOCUS_DOWN
1217    })
1218    @Retention(RetentionPolicy.SOURCE)
1219    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1220
1221    /**
1222     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1223     * item.
1224     */
1225    public static final int FOCUS_BACKWARD = 0x00000001;
1226
1227    /**
1228     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1229     * item.
1230     */
1231    public static final int FOCUS_FORWARD = 0x00000002;
1232
1233    /**
1234     * Use with {@link #focusSearch(int)}. Move focus to the left.
1235     */
1236    public static final int FOCUS_LEFT = 0x00000011;
1237
1238    /**
1239     * Use with {@link #focusSearch(int)}. Move focus up.
1240     */
1241    public static final int FOCUS_UP = 0x00000021;
1242
1243    /**
1244     * Use with {@link #focusSearch(int)}. Move focus to the right.
1245     */
1246    public static final int FOCUS_RIGHT = 0x00000042;
1247
1248    /**
1249     * Use with {@link #focusSearch(int)}. Move focus down.
1250     */
1251    public static final int FOCUS_DOWN = 0x00000082;
1252
1253    /**
1254     * Bits of {@link #getMeasuredWidthAndState()} and
1255     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1256     */
1257    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1258
1259    /**
1260     * Bits of {@link #getMeasuredWidthAndState()} and
1261     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1262     */
1263    public static final int MEASURED_STATE_MASK = 0xff000000;
1264
1265    /**
1266     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1267     * for functions that combine both width and height into a single int,
1268     * such as {@link #getMeasuredState()} and the childState argument of
1269     * {@link #resolveSizeAndState(int, int, int)}.
1270     */
1271    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1272
1273    /**
1274     * Bit of {@link #getMeasuredWidthAndState()} and
1275     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1276     * is smaller that the space the view would like to have.
1277     */
1278    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1279
1280    /**
1281     * Base View state sets
1282     */
1283    // Singles
1284    /**
1285     * Indicates the view has no states set. States are used with
1286     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1287     * view depending on its state.
1288     *
1289     * @see android.graphics.drawable.Drawable
1290     * @see #getDrawableState()
1291     */
1292    protected static final int[] EMPTY_STATE_SET;
1293    /**
1294     * Indicates the view is enabled. 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[] ENABLED_STATE_SET;
1302    /**
1303     * Indicates the view is focused. 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[] FOCUSED_STATE_SET;
1311    /**
1312     * Indicates the view is selected. 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[] SELECTED_STATE_SET;
1320    /**
1321     * Indicates the view is pressed. 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[] PRESSED_STATE_SET;
1329    /**
1330     * Indicates the view's window has focus. 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[] WINDOW_FOCUSED_STATE_SET;
1338    // Doubles
1339    /**
1340     * Indicates the view is enabled and has the focus.
1341     *
1342     * @see #ENABLED_STATE_SET
1343     * @see #FOCUSED_STATE_SET
1344     */
1345    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1346    /**
1347     * Indicates the view is enabled and selected.
1348     *
1349     * @see #ENABLED_STATE_SET
1350     * @see #SELECTED_STATE_SET
1351     */
1352    protected static final int[] ENABLED_SELECTED_STATE_SET;
1353    /**
1354     * Indicates the view is enabled and that its window has focus.
1355     *
1356     * @see #ENABLED_STATE_SET
1357     * @see #WINDOW_FOCUSED_STATE_SET
1358     */
1359    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1360    /**
1361     * Indicates the view is focused and selected.
1362     *
1363     * @see #FOCUSED_STATE_SET
1364     * @see #SELECTED_STATE_SET
1365     */
1366    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1367    /**
1368     * Indicates the view has the focus and that its window has the focus.
1369     *
1370     * @see #FOCUSED_STATE_SET
1371     * @see #WINDOW_FOCUSED_STATE_SET
1372     */
1373    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1374    /**
1375     * Indicates the view is selected and that its window has the focus.
1376     *
1377     * @see #SELECTED_STATE_SET
1378     * @see #WINDOW_FOCUSED_STATE_SET
1379     */
1380    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1381    // Triples
1382    /**
1383     * Indicates the view is enabled, focused and selected.
1384     *
1385     * @see #ENABLED_STATE_SET
1386     * @see #FOCUSED_STATE_SET
1387     * @see #SELECTED_STATE_SET
1388     */
1389    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1390    /**
1391     * Indicates the view is enabled, focused and its window has the focus.
1392     *
1393     * @see #ENABLED_STATE_SET
1394     * @see #FOCUSED_STATE_SET
1395     * @see #WINDOW_FOCUSED_STATE_SET
1396     */
1397    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1398    /**
1399     * Indicates the view is enabled, selected and its window has the focus.
1400     *
1401     * @see #ENABLED_STATE_SET
1402     * @see #SELECTED_STATE_SET
1403     * @see #WINDOW_FOCUSED_STATE_SET
1404     */
1405    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1406    /**
1407     * Indicates the view is focused, selected and its window has the focus.
1408     *
1409     * @see #FOCUSED_STATE_SET
1410     * @see #SELECTED_STATE_SET
1411     * @see #WINDOW_FOCUSED_STATE_SET
1412     */
1413    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1414    /**
1415     * Indicates the view is enabled, focused, selected and its window
1416     * has the focus.
1417     *
1418     * @see #ENABLED_STATE_SET
1419     * @see #FOCUSED_STATE_SET
1420     * @see #SELECTED_STATE_SET
1421     * @see #WINDOW_FOCUSED_STATE_SET
1422     */
1423    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1424    /**
1425     * Indicates the view is pressed and its window has the focus.
1426     *
1427     * @see #PRESSED_STATE_SET
1428     * @see #WINDOW_FOCUSED_STATE_SET
1429     */
1430    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1431    /**
1432     * Indicates the view is pressed and selected.
1433     *
1434     * @see #PRESSED_STATE_SET
1435     * @see #SELECTED_STATE_SET
1436     */
1437    protected static final int[] PRESSED_SELECTED_STATE_SET;
1438    /**
1439     * Indicates the view is pressed, selected and its window has the focus.
1440     *
1441     * @see #PRESSED_STATE_SET
1442     * @see #SELECTED_STATE_SET
1443     * @see #WINDOW_FOCUSED_STATE_SET
1444     */
1445    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1446    /**
1447     * Indicates the view is pressed and focused.
1448     *
1449     * @see #PRESSED_STATE_SET
1450     * @see #FOCUSED_STATE_SET
1451     */
1452    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1453    /**
1454     * Indicates the view is pressed, focused and its window has the focus.
1455     *
1456     * @see #PRESSED_STATE_SET
1457     * @see #FOCUSED_STATE_SET
1458     * @see #WINDOW_FOCUSED_STATE_SET
1459     */
1460    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1461    /**
1462     * Indicates the view is pressed, focused and selected.
1463     *
1464     * @see #PRESSED_STATE_SET
1465     * @see #SELECTED_STATE_SET
1466     * @see #FOCUSED_STATE_SET
1467     */
1468    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1469    /**
1470     * Indicates the view is pressed, focused, selected and its window has the focus.
1471     *
1472     * @see #PRESSED_STATE_SET
1473     * @see #FOCUSED_STATE_SET
1474     * @see #SELECTED_STATE_SET
1475     * @see #WINDOW_FOCUSED_STATE_SET
1476     */
1477    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1478    /**
1479     * Indicates the view is pressed and enabled.
1480     *
1481     * @see #PRESSED_STATE_SET
1482     * @see #ENABLED_STATE_SET
1483     */
1484    protected static final int[] PRESSED_ENABLED_STATE_SET;
1485    /**
1486     * Indicates the view is pressed, enabled and its window has the focus.
1487     *
1488     * @see #PRESSED_STATE_SET
1489     * @see #ENABLED_STATE_SET
1490     * @see #WINDOW_FOCUSED_STATE_SET
1491     */
1492    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1493    /**
1494     * Indicates the view is pressed, enabled and selected.
1495     *
1496     * @see #PRESSED_STATE_SET
1497     * @see #ENABLED_STATE_SET
1498     * @see #SELECTED_STATE_SET
1499     */
1500    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1501    /**
1502     * Indicates the view is pressed, enabled, selected and its window has the
1503     * focus.
1504     *
1505     * @see #PRESSED_STATE_SET
1506     * @see #ENABLED_STATE_SET
1507     * @see #SELECTED_STATE_SET
1508     * @see #WINDOW_FOCUSED_STATE_SET
1509     */
1510    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1511    /**
1512     * Indicates the view is pressed, enabled and focused.
1513     *
1514     * @see #PRESSED_STATE_SET
1515     * @see #ENABLED_STATE_SET
1516     * @see #FOCUSED_STATE_SET
1517     */
1518    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1519    /**
1520     * Indicates the view is pressed, enabled, focused and its window has the
1521     * focus.
1522     *
1523     * @see #PRESSED_STATE_SET
1524     * @see #ENABLED_STATE_SET
1525     * @see #FOCUSED_STATE_SET
1526     * @see #WINDOW_FOCUSED_STATE_SET
1527     */
1528    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1529    /**
1530     * Indicates the view is pressed, enabled, focused and selected.
1531     *
1532     * @see #PRESSED_STATE_SET
1533     * @see #ENABLED_STATE_SET
1534     * @see #SELECTED_STATE_SET
1535     * @see #FOCUSED_STATE_SET
1536     */
1537    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1538    /**
1539     * Indicates the view is pressed, enabled, focused, selected and its window
1540     * has the focus.
1541     *
1542     * @see #PRESSED_STATE_SET
1543     * @see #ENABLED_STATE_SET
1544     * @see #SELECTED_STATE_SET
1545     * @see #FOCUSED_STATE_SET
1546     * @see #WINDOW_FOCUSED_STATE_SET
1547     */
1548    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1549
1550    static {
1551        EMPTY_STATE_SET = StateSet.get(0);
1552
1553        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1554
1555        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1556        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1557                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1558
1559        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1560        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1561                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1562        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1563                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1564        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1565                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1566                        | StateSet.VIEW_STATE_FOCUSED);
1567
1568        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1569        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1570                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1571        ENABLED_SELECTED_STATE_SET = StateSet.get(
1572                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1573        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1574                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1575                        | StateSet.VIEW_STATE_ENABLED);
1576        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1577                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1578        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1579                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1580                        | StateSet.VIEW_STATE_ENABLED);
1581        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1582                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1583                        | StateSet.VIEW_STATE_ENABLED);
1584        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1585                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1586                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1587
1588        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1589        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1590                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1591        PRESSED_SELECTED_STATE_SET = StateSet.get(
1592                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1593        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1594                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1595                        | StateSet.VIEW_STATE_PRESSED);
1596        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1597                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1598        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1599                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1600                        | StateSet.VIEW_STATE_PRESSED);
1601        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1602                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1603                        | StateSet.VIEW_STATE_PRESSED);
1604        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1605                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1606                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1607        PRESSED_ENABLED_STATE_SET = StateSet.get(
1608                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1609        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1610                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1611                        | StateSet.VIEW_STATE_PRESSED);
1612        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1613                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1614                        | StateSet.VIEW_STATE_PRESSED);
1615        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1616                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1617                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1618        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1619                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1620                        | StateSet.VIEW_STATE_PRESSED);
1621        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1622                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1623                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1624        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1625                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1626                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1627        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1628                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1629                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1630                        | StateSet.VIEW_STATE_PRESSED);
1631    }
1632
1633    /**
1634     * Accessibility event types that are dispatched for text population.
1635     */
1636    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1637            AccessibilityEvent.TYPE_VIEW_CLICKED
1638            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1639            | AccessibilityEvent.TYPE_VIEW_SELECTED
1640            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1641            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1642            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1643            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1644            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1645            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1646            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1647            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1648
1649    /**
1650     * Temporary Rect currently for use in setBackground().  This will probably
1651     * be extended in the future to hold our own class with more than just
1652     * a Rect. :)
1653     */
1654    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1655
1656    /**
1657     * Map used to store views' tags.
1658     */
1659    private SparseArray<Object> mKeyedTags;
1660
1661    /**
1662     * The next available accessibility id.
1663     */
1664    private static int sNextAccessibilityViewId;
1665
1666    /**
1667     * The animation currently associated with this view.
1668     * @hide
1669     */
1670    protected Animation mCurrentAnimation = null;
1671
1672    /**
1673     * Width as measured during measure pass.
1674     * {@hide}
1675     */
1676    @ViewDebug.ExportedProperty(category = "measurement")
1677    int mMeasuredWidth;
1678
1679    /**
1680     * Height as measured during measure pass.
1681     * {@hide}
1682     */
1683    @ViewDebug.ExportedProperty(category = "measurement")
1684    int mMeasuredHeight;
1685
1686    /**
1687     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1688     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1689     * its display list. This flag, used only when hw accelerated, allows us to clear the
1690     * flag while retaining this information until it's needed (at getDisplayList() time and
1691     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1692     *
1693     * {@hide}
1694     */
1695    boolean mRecreateDisplayList = false;
1696
1697    /**
1698     * The view's identifier.
1699     * {@hide}
1700     *
1701     * @see #setId(int)
1702     * @see #getId()
1703     */
1704    @IdRes
1705    @ViewDebug.ExportedProperty(resolveId = true)
1706    int mID = NO_ID;
1707
1708    /**
1709     * The stable ID of this view for accessibility purposes.
1710     */
1711    int mAccessibilityViewId = NO_ID;
1712
1713    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1714
1715    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1716
1717    /**
1718     * The view's tag.
1719     * {@hide}
1720     *
1721     * @see #setTag(Object)
1722     * @see #getTag()
1723     */
1724    protected Object mTag = null;
1725
1726    // for mPrivateFlags:
1727    /** {@hide} */
1728    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1729    /** {@hide} */
1730    static final int PFLAG_FOCUSED                     = 0x00000002;
1731    /** {@hide} */
1732    static final int PFLAG_SELECTED                    = 0x00000004;
1733    /** {@hide} */
1734    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1735    /** {@hide} */
1736    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1737    /** {@hide} */
1738    static final int PFLAG_DRAWN                       = 0x00000020;
1739    /**
1740     * When this flag is set, this view is running an animation on behalf of its
1741     * children and should therefore not cancel invalidate requests, even if they
1742     * lie outside of this view's bounds.
1743     *
1744     * {@hide}
1745     */
1746    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1747    /** {@hide} */
1748    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1749    /** {@hide} */
1750    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1751    /** {@hide} */
1752    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1753    /** {@hide} */
1754    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1755    /** {@hide} */
1756    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1757    /** {@hide} */
1758    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1759
1760    private static final int PFLAG_PRESSED             = 0x00004000;
1761
1762    /** {@hide} */
1763    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1764    /**
1765     * Flag used to indicate that this view should be drawn once more (and only once
1766     * more) after its animation has completed.
1767     * {@hide}
1768     */
1769    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1770
1771    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1772
1773    /**
1774     * Indicates that the View returned true when onSetAlpha() was called and that
1775     * the alpha must be restored.
1776     * {@hide}
1777     */
1778    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1779
1780    /**
1781     * Set by {@link #setScrollContainer(boolean)}.
1782     */
1783    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1784
1785    /**
1786     * Set by {@link #setScrollContainer(boolean)}.
1787     */
1788    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1789
1790    /**
1791     * View flag indicating whether this view was invalidated (fully or partially.)
1792     *
1793     * @hide
1794     */
1795    static final int PFLAG_DIRTY                       = 0x00200000;
1796
1797    /**
1798     * View flag indicating whether this view was invalidated by an opaque
1799     * invalidate request.
1800     *
1801     * @hide
1802     */
1803    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1804
1805    /**
1806     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1807     *
1808     * @hide
1809     */
1810    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1811
1812    /**
1813     * Indicates whether the background is opaque.
1814     *
1815     * @hide
1816     */
1817    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1818
1819    /**
1820     * Indicates whether the scrollbars are opaque.
1821     *
1822     * @hide
1823     */
1824    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1825
1826    /**
1827     * Indicates whether the view is opaque.
1828     *
1829     * @hide
1830     */
1831    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1832
1833    /**
1834     * Indicates a prepressed state;
1835     * the short time between ACTION_DOWN and recognizing
1836     * a 'real' press. Prepressed is used to recognize quick taps
1837     * even when they are shorter than ViewConfiguration.getTapTimeout().
1838     *
1839     * @hide
1840     */
1841    private static final int PFLAG_PREPRESSED          = 0x02000000;
1842
1843    /**
1844     * Indicates whether the view is temporarily detached.
1845     *
1846     * @hide
1847     */
1848    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1849
1850    /**
1851     * Indicates that we should awaken scroll bars once attached
1852     *
1853     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1854     * during window attachment and it is no longer needed. Feel free to repurpose it.
1855     *
1856     * @hide
1857     */
1858    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1859
1860    /**
1861     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1862     * @hide
1863     */
1864    private static final int PFLAG_HOVERED             = 0x10000000;
1865
1866    /**
1867     * no longer needed, should be reused
1868     */
1869    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1870
1871    /** {@hide} */
1872    static final int PFLAG_ACTIVATED                   = 0x40000000;
1873
1874    /**
1875     * Indicates that this view was specifically invalidated, not just dirtied because some
1876     * child view was invalidated. The flag is used to determine when we need to recreate
1877     * a view's display list (as opposed to just returning a reference to its existing
1878     * display list).
1879     *
1880     * @hide
1881     */
1882    static final int PFLAG_INVALIDATED                 = 0x80000000;
1883
1884    /**
1885     * Masks for mPrivateFlags2, as generated by dumpFlags():
1886     *
1887     * |-------|-------|-------|-------|
1888     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1889     *                                1  PFLAG2_DRAG_HOVERED
1890     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1891     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1892     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1893     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1894     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1895     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1896     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1897     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1898     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1899     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1900     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1901     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1902     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1903     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1904     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1905     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1906     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1907     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1908     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1909     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1910     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1911     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1912     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1913     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1914     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1915     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1916     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1917     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1918     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1919     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1920     *    1                              PFLAG2_PADDING_RESOLVED
1921     *   1                               PFLAG2_DRAWABLE_RESOLVED
1922     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1923     * |-------|-------|-------|-------|
1924     */
1925
1926    /**
1927     * Indicates that this view has reported that it can accept the current drag's content.
1928     * Cleared when the drag operation concludes.
1929     * @hide
1930     */
1931    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1932
1933    /**
1934     * Indicates that this view is currently directly under the drag location in a
1935     * drag-and-drop operation involving content that it can accept.  Cleared when
1936     * the drag exits the view, or when the drag operation concludes.
1937     * @hide
1938     */
1939    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1940
1941    /** @hide */
1942    @IntDef({
1943        LAYOUT_DIRECTION_LTR,
1944        LAYOUT_DIRECTION_RTL,
1945        LAYOUT_DIRECTION_INHERIT,
1946        LAYOUT_DIRECTION_LOCALE
1947    })
1948    @Retention(RetentionPolicy.SOURCE)
1949    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1950    public @interface LayoutDir {}
1951
1952    /** @hide */
1953    @IntDef({
1954        LAYOUT_DIRECTION_LTR,
1955        LAYOUT_DIRECTION_RTL
1956    })
1957    @Retention(RetentionPolicy.SOURCE)
1958    public @interface ResolvedLayoutDir {}
1959
1960    /**
1961     * A flag to indicate that the layout direction of this view has not been defined yet.
1962     * @hide
1963     */
1964    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1965
1966    /**
1967     * Horizontal layout direction of this view is from Left to Right.
1968     * Use with {@link #setLayoutDirection}.
1969     */
1970    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1971
1972    /**
1973     * Horizontal layout direction of this view is from Right to Left.
1974     * Use with {@link #setLayoutDirection}.
1975     */
1976    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1977
1978    /**
1979     * Horizontal layout direction of this view is inherited from its parent.
1980     * Use with {@link #setLayoutDirection}.
1981     */
1982    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1983
1984    /**
1985     * Horizontal layout direction of this view is from deduced from the default language
1986     * script for the locale. Use with {@link #setLayoutDirection}.
1987     */
1988    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1989
1990    /**
1991     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1992     * @hide
1993     */
1994    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1995
1996    /**
1997     * Mask for use with private flags indicating bits used for horizontal layout direction.
1998     * @hide
1999     */
2000    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2001
2002    /**
2003     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2004     * right-to-left direction.
2005     * @hide
2006     */
2007    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2008
2009    /**
2010     * Indicates whether the view horizontal layout direction has been resolved.
2011     * @hide
2012     */
2013    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2014
2015    /**
2016     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2017     * @hide
2018     */
2019    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2020            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2021
2022    /*
2023     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2024     * flag value.
2025     * @hide
2026     */
2027    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2028            LAYOUT_DIRECTION_LTR,
2029            LAYOUT_DIRECTION_RTL,
2030            LAYOUT_DIRECTION_INHERIT,
2031            LAYOUT_DIRECTION_LOCALE
2032    };
2033
2034    /**
2035     * Default horizontal layout direction.
2036     */
2037    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2038
2039    /**
2040     * Default horizontal layout direction.
2041     * @hide
2042     */
2043    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2044
2045    /**
2046     * Text direction is inherited through {@link ViewGroup}
2047     */
2048    public static final int TEXT_DIRECTION_INHERIT = 0;
2049
2050    /**
2051     * Text direction is using "first strong algorithm". The first strong directional character
2052     * determines the paragraph direction. If there is no strong directional character, the
2053     * paragraph direction is the view's resolved layout direction.
2054     */
2055    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2056
2057    /**
2058     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2059     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2060     * If there are neither, the paragraph direction is the view's resolved layout direction.
2061     */
2062    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2063
2064    /**
2065     * Text direction is forced to LTR.
2066     */
2067    public static final int TEXT_DIRECTION_LTR = 3;
2068
2069    /**
2070     * Text direction is forced to RTL.
2071     */
2072    public static final int TEXT_DIRECTION_RTL = 4;
2073
2074    /**
2075     * Text direction is coming from the system Locale.
2076     */
2077    public static final int TEXT_DIRECTION_LOCALE = 5;
2078
2079    /**
2080     * Text direction is using "first strong algorithm". The first strong directional character
2081     * determines the paragraph direction. If there is no strong directional character, the
2082     * paragraph direction is LTR.
2083     */
2084    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2085
2086    /**
2087     * Text direction is using "first strong algorithm". The first strong directional character
2088     * determines the paragraph direction. If there is no strong directional character, the
2089     * paragraph direction is RTL.
2090     */
2091    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2092
2093    /**
2094     * Default text direction is inherited
2095     */
2096    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2097
2098    /**
2099     * Default resolved text direction
2100     * @hide
2101     */
2102    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2103
2104    /**
2105     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2106     * @hide
2107     */
2108    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2109
2110    /**
2111     * Mask for use with private flags indicating bits used for text direction.
2112     * @hide
2113     */
2114    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2115            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2116
2117    /**
2118     * Array of text direction flags for mapping attribute "textDirection" to correct
2119     * flag value.
2120     * @hide
2121     */
2122    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2123            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2124            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2125            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2126            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2127            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2128            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2129            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2130            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2131    };
2132
2133    /**
2134     * Indicates whether the view text direction has been resolved.
2135     * @hide
2136     */
2137    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2138            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2139
2140    /**
2141     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2142     * @hide
2143     */
2144    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2145
2146    /**
2147     * Mask for use with private flags indicating bits used for resolved text direction.
2148     * @hide
2149     */
2150    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2151            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2152
2153    /**
2154     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2155     * @hide
2156     */
2157    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2158            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2159
2160    /** @hide */
2161    @IntDef({
2162        TEXT_ALIGNMENT_INHERIT,
2163        TEXT_ALIGNMENT_GRAVITY,
2164        TEXT_ALIGNMENT_CENTER,
2165        TEXT_ALIGNMENT_TEXT_START,
2166        TEXT_ALIGNMENT_TEXT_END,
2167        TEXT_ALIGNMENT_VIEW_START,
2168        TEXT_ALIGNMENT_VIEW_END
2169    })
2170    @Retention(RetentionPolicy.SOURCE)
2171    public @interface TextAlignment {}
2172
2173    /**
2174     * Default text alignment. The text alignment of this View is inherited from its parent.
2175     * Use with {@link #setTextAlignment(int)}
2176     */
2177    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2178
2179    /**
2180     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2181     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2182     *
2183     * Use with {@link #setTextAlignment(int)}
2184     */
2185    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2186
2187    /**
2188     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2189     *
2190     * Use with {@link #setTextAlignment(int)}
2191     */
2192    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2193
2194    /**
2195     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2196     *
2197     * Use with {@link #setTextAlignment(int)}
2198     */
2199    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2200
2201    /**
2202     * Center the paragraph, e.g. ALIGN_CENTER.
2203     *
2204     * Use with {@link #setTextAlignment(int)}
2205     */
2206    public static final int TEXT_ALIGNMENT_CENTER = 4;
2207
2208    /**
2209     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2210     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2211     *
2212     * Use with {@link #setTextAlignment(int)}
2213     */
2214    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2215
2216    /**
2217     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2218     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2219     *
2220     * Use with {@link #setTextAlignment(int)}
2221     */
2222    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2223
2224    /**
2225     * Default text alignment is inherited
2226     */
2227    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2228
2229    /**
2230     * Default resolved text alignment
2231     * @hide
2232     */
2233    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2234
2235    /**
2236      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2237      * @hide
2238      */
2239    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2240
2241    /**
2242      * Mask for use with private flags indicating bits used for text alignment.
2243      * @hide
2244      */
2245    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2246
2247    /**
2248     * Array of text direction flags for mapping attribute "textAlignment" to correct
2249     * flag value.
2250     * @hide
2251     */
2252    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2253            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2254            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2255            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2256            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2257            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2258            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2259            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2260    };
2261
2262    /**
2263     * Indicates whether the view text alignment has been resolved.
2264     * @hide
2265     */
2266    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2267
2268    /**
2269     * Bit shift to get the resolved text alignment.
2270     * @hide
2271     */
2272    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2273
2274    /**
2275     * Mask for use with private flags indicating bits used for text alignment.
2276     * @hide
2277     */
2278    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2279            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2280
2281    /**
2282     * Indicates whether if the view text alignment has been resolved to gravity
2283     */
2284    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2285            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2286
2287    // Accessiblity constants for mPrivateFlags2
2288
2289    /**
2290     * Shift for the bits in {@link #mPrivateFlags2} related to the
2291     * "importantForAccessibility" attribute.
2292     */
2293    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2294
2295    /**
2296     * Automatically determine whether a view is important for accessibility.
2297     */
2298    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2299
2300    /**
2301     * The view is important for accessibility.
2302     */
2303    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2304
2305    /**
2306     * The view is not important for accessibility.
2307     */
2308    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2309
2310    /**
2311     * The view is not important for accessibility, nor are any of its
2312     * descendant views.
2313     */
2314    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2315
2316    /**
2317     * The default whether the view is important for accessibility.
2318     */
2319    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2320
2321    /**
2322     * Mask for obtainig the bits which specify how to determine
2323     * whether a view is important for accessibility.
2324     */
2325    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2326        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2327        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2328        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2329
2330    /**
2331     * Shift for the bits in {@link #mPrivateFlags2} related to the
2332     * "accessibilityLiveRegion" attribute.
2333     */
2334    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2335
2336    /**
2337     * Live region mode specifying that accessibility services should not
2338     * automatically announce changes to this view. This is the default live
2339     * region mode for most views.
2340     * <p>
2341     * Use with {@link #setAccessibilityLiveRegion(int)}.
2342     */
2343    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2344
2345    /**
2346     * Live region mode specifying that accessibility services should announce
2347     * changes to this view.
2348     * <p>
2349     * Use with {@link #setAccessibilityLiveRegion(int)}.
2350     */
2351    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2352
2353    /**
2354     * Live region mode specifying that accessibility services should interrupt
2355     * ongoing speech to immediately announce changes to this view.
2356     * <p>
2357     * Use with {@link #setAccessibilityLiveRegion(int)}.
2358     */
2359    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2360
2361    /**
2362     * The default whether the view is important for accessibility.
2363     */
2364    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2365
2366    /**
2367     * Mask for obtaining the bits which specify a view's accessibility live
2368     * region mode.
2369     */
2370    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2371            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2372            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2373
2374    /**
2375     * Flag indicating whether a view has accessibility focus.
2376     */
2377    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2378
2379    /**
2380     * Flag whether the accessibility state of the subtree rooted at this view changed.
2381     */
2382    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2383
2384    /**
2385     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2386     * is used to check whether later changes to the view's transform should invalidate the
2387     * view to force the quickReject test to run again.
2388     */
2389    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2390
2391    /**
2392     * Flag indicating that start/end padding has been resolved into left/right padding
2393     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2394     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2395     * during measurement. In some special cases this is required such as when an adapter-based
2396     * view measures prospective children without attaching them to a window.
2397     */
2398    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2399
2400    /**
2401     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2402     */
2403    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2404
2405    /**
2406     * Indicates that the view is tracking some sort of transient state
2407     * that the app should not need to be aware of, but that the framework
2408     * should take special care to preserve.
2409     */
2410    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2411
2412    /**
2413     * Group of bits indicating that RTL properties resolution is done.
2414     */
2415    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2416            PFLAG2_TEXT_DIRECTION_RESOLVED |
2417            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2418            PFLAG2_PADDING_RESOLVED |
2419            PFLAG2_DRAWABLE_RESOLVED;
2420
2421    // There are a couple of flags left in mPrivateFlags2
2422
2423    /* End of masks for mPrivateFlags2 */
2424
2425    /**
2426     * Masks for mPrivateFlags3, as generated by dumpFlags():
2427     *
2428     * |-------|-------|-------|-------|
2429     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2430     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2431     *                               1   PFLAG3_IS_LAID_OUT
2432     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2433     *                             1     PFLAG3_CALLED_SUPER
2434     *                            1      PFLAG3_APPLYING_INSETS
2435     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2436     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2437     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2438     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2439     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2440     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2441     *                     1             PFLAG3_SCROLL_INDICATOR_START
2442     *                    1              PFLAG3_SCROLL_INDICATOR_END
2443     *                   1               PFLAG3_ASSIST_BLOCKED
2444     *                  1                PFLAG3_POINTER_ICON_NULL
2445     *                 1                 PFLAG3_POINTER_ICON_VALUE_START
2446     *           11111111                PFLAG3_POINTER_ICON_MASK
2447     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2448     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2449     *        1                          PFLAG3_TEMPORARY_DETACH
2450     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2451     * |-------|-------|-------|-------|
2452     */
2453
2454    /**
2455     * Flag indicating that view has a transform animation set on it. This is used to track whether
2456     * an animation is cleared between successive frames, in order to tell the associated
2457     * DisplayList to clear its animation matrix.
2458     */
2459    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2460
2461    /**
2462     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2463     * animation is cleared between successive frames, in order to tell the associated
2464     * DisplayList to restore its alpha value.
2465     */
2466    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2467
2468    /**
2469     * Flag indicating that the view has been through at least one layout since it
2470     * was last attached to a window.
2471     */
2472    static final int PFLAG3_IS_LAID_OUT = 0x4;
2473
2474    /**
2475     * Flag indicating that a call to measure() was skipped and should be done
2476     * instead when layout() is invoked.
2477     */
2478    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2479
2480    /**
2481     * Flag indicating that an overridden method correctly called down to
2482     * the superclass implementation as required by the API spec.
2483     */
2484    static final int PFLAG3_CALLED_SUPER = 0x10;
2485
2486    /**
2487     * Flag indicating that we're in the process of applying window insets.
2488     */
2489    static final int PFLAG3_APPLYING_INSETS = 0x20;
2490
2491    /**
2492     * Flag indicating that we're in the process of fitting system windows using the old method.
2493     */
2494    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2495
2496    /**
2497     * Flag indicating that nested scrolling is enabled for this view.
2498     * The view will optionally cooperate with views up its parent chain to allow for
2499     * integrated nested scrolling along the same axis.
2500     */
2501    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2502
2503    /**
2504     * Flag indicating that the bottom scroll indicator should be displayed
2505     * when this view can scroll up.
2506     */
2507    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2508
2509    /**
2510     * Flag indicating that the bottom scroll indicator should be displayed
2511     * when this view can scroll down.
2512     */
2513    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2514
2515    /**
2516     * Flag indicating that the left scroll indicator should be displayed
2517     * when this view can scroll left.
2518     */
2519    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2520
2521    /**
2522     * Flag indicating that the right scroll indicator should be displayed
2523     * when this view can scroll right.
2524     */
2525    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2526
2527    /**
2528     * Flag indicating that the start scroll indicator should be displayed
2529     * when this view can scroll in the start direction.
2530     */
2531    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2532
2533    /**
2534     * Flag indicating that the end scroll indicator should be displayed
2535     * when this view can scroll in the end direction.
2536     */
2537    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2538
2539    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2540
2541    static final int SCROLL_INDICATORS_NONE = 0x0000;
2542
2543    /**
2544     * Mask for use with setFlags indicating bits used for indicating which
2545     * scroll indicators are enabled.
2546     */
2547    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2548            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2549            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2550            | PFLAG3_SCROLL_INDICATOR_END;
2551
2552    /**
2553     * Left-shift required to translate between public scroll indicator flags
2554     * and internal PFLAGS3 flags. When used as a right-shift, translates
2555     * PFLAGS3 flags to public flags.
2556     */
2557    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2558
2559    /** @hide */
2560    @Retention(RetentionPolicy.SOURCE)
2561    @IntDef(flag = true,
2562            value = {
2563                    SCROLL_INDICATOR_TOP,
2564                    SCROLL_INDICATOR_BOTTOM,
2565                    SCROLL_INDICATOR_LEFT,
2566                    SCROLL_INDICATOR_RIGHT,
2567                    SCROLL_INDICATOR_START,
2568                    SCROLL_INDICATOR_END,
2569            })
2570    public @interface ScrollIndicators {}
2571
2572    /**
2573     * Scroll indicator direction for the top edge of the view.
2574     *
2575     * @see #setScrollIndicators(int)
2576     * @see #setScrollIndicators(int, int)
2577     * @see #getScrollIndicators()
2578     */
2579    public static final int SCROLL_INDICATOR_TOP =
2580            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2581
2582    /**
2583     * Scroll indicator direction for the bottom edge of the view.
2584     *
2585     * @see #setScrollIndicators(int)
2586     * @see #setScrollIndicators(int, int)
2587     * @see #getScrollIndicators()
2588     */
2589    public static final int SCROLL_INDICATOR_BOTTOM =
2590            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2591
2592    /**
2593     * Scroll indicator direction for the left edge of the view.
2594     *
2595     * @see #setScrollIndicators(int)
2596     * @see #setScrollIndicators(int, int)
2597     * @see #getScrollIndicators()
2598     */
2599    public static final int SCROLL_INDICATOR_LEFT =
2600            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2601
2602    /**
2603     * Scroll indicator direction for the right edge of the view.
2604     *
2605     * @see #setScrollIndicators(int)
2606     * @see #setScrollIndicators(int, int)
2607     * @see #getScrollIndicators()
2608     */
2609    public static final int SCROLL_INDICATOR_RIGHT =
2610            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2611
2612    /**
2613     * Scroll indicator direction for the starting edge of the view.
2614     * <p>
2615     * Resolved according to the view's layout direction, see
2616     * {@link #getLayoutDirection()} for more information.
2617     *
2618     * @see #setScrollIndicators(int)
2619     * @see #setScrollIndicators(int, int)
2620     * @see #getScrollIndicators()
2621     */
2622    public static final int SCROLL_INDICATOR_START =
2623            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2624
2625    /**
2626     * Scroll indicator direction for the ending edge of the view.
2627     * <p>
2628     * Resolved according to the view's layout direction, see
2629     * {@link #getLayoutDirection()} for more information.
2630     *
2631     * @see #setScrollIndicators(int)
2632     * @see #setScrollIndicators(int, int)
2633     * @see #getScrollIndicators()
2634     */
2635    public static final int SCROLL_INDICATOR_END =
2636            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2637
2638    /**
2639     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2640     * into this view.<p>
2641     */
2642    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2643
2644    /**
2645     * The mask for use with private flags indicating bits used for pointer icon shapes.
2646     */
2647    static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
2648
2649    /**
2650     * Left-shift used for pointer icon shape values in private flags.
2651     */
2652    static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
2653
2654    /**
2655     * Value indicating no specific pointer icons.
2656     */
2657    private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
2658
2659    /**
2660     * Value indicating {@link PointerIcon.TYPE_NULL}.
2661     */
2662    private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
2663
2664    /**
2665     * The base value for other pointer icon shapes.
2666     */
2667    private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
2668
2669    /**
2670     * Whether this view has rendered elements that overlap (see {@link
2671     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2672     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2673     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2674     * determined by whatever {@link #hasOverlappingRendering()} returns.
2675     */
2676    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2677
2678    /**
2679     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2680     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2681     */
2682    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2683
2684    /**
2685     * Flag indicating that the view is temporarily detached from the parent view.
2686     *
2687     * @see #onStartTemporaryDetach()
2688     * @see #onFinishTemporaryDetach()
2689     */
2690    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
2691
2692    /**
2693     * Flag indicating that the view does not wish to be revealed within its parent
2694     * hierarchy when it gains focus. Expressed in the negative since the historical
2695     * default behavior is to reveal on focus; this flag suppresses that behavior.
2696     *
2697     * @see #setRevealOnFocusHint(boolean)
2698     * @see #getRevealOnFocusHint()
2699     */
2700    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
2701
2702    /* End of masks for mPrivateFlags3 */
2703
2704    /**
2705     * Always allow a user to over-scroll this view, provided it is a
2706     * view that can scroll.
2707     *
2708     * @see #getOverScrollMode()
2709     * @see #setOverScrollMode(int)
2710     */
2711    public static final int OVER_SCROLL_ALWAYS = 0;
2712
2713    /**
2714     * Allow a user to over-scroll this view only if the content is large
2715     * enough to meaningfully scroll, provided it is a view that can scroll.
2716     *
2717     * @see #getOverScrollMode()
2718     * @see #setOverScrollMode(int)
2719     */
2720    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2721
2722    /**
2723     * Never allow a user to over-scroll this view.
2724     *
2725     * @see #getOverScrollMode()
2726     * @see #setOverScrollMode(int)
2727     */
2728    public static final int OVER_SCROLL_NEVER = 2;
2729
2730    /**
2731     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2732     * requested the system UI (status bar) to be visible (the default).
2733     *
2734     * @see #setSystemUiVisibility(int)
2735     */
2736    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2737
2738    /**
2739     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2740     * system UI to enter an unobtrusive "low profile" mode.
2741     *
2742     * <p>This is for use in games, book readers, video players, or any other
2743     * "immersive" application where the usual system chrome is deemed too distracting.
2744     *
2745     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2746     *
2747     * @see #setSystemUiVisibility(int)
2748     */
2749    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2750
2751    /**
2752     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2753     * system navigation be temporarily hidden.
2754     *
2755     * <p>This is an even less obtrusive state than that called for by
2756     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2757     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2758     * those to disappear. This is useful (in conjunction with the
2759     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2760     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2761     * window flags) for displaying content using every last pixel on the display.
2762     *
2763     * <p>There is a limitation: because navigation controls are so important, the least user
2764     * interaction will cause them to reappear immediately.  When this happens, both
2765     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2766     * so that both elements reappear at the same time.
2767     *
2768     * @see #setSystemUiVisibility(int)
2769     */
2770    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2771
2772    /**
2773     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2774     * into the normal fullscreen mode so that its content can take over the screen
2775     * while still allowing the user to interact with the application.
2776     *
2777     * <p>This has the same visual effect as
2778     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2779     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2780     * meaning that non-critical screen decorations (such as the status bar) will be
2781     * hidden while the user is in the View's window, focusing the experience on
2782     * that content.  Unlike the window flag, if you are using ActionBar in
2783     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2784     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2785     * hide the action bar.
2786     *
2787     * <p>This approach to going fullscreen is best used over the window flag when
2788     * it is a transient state -- that is, the application does this at certain
2789     * points in its user interaction where it wants to allow the user to focus
2790     * on content, but not as a continuous state.  For situations where the application
2791     * would like to simply stay full screen the entire time (such as a game that
2792     * wants to take over the screen), the
2793     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2794     * is usually a better approach.  The state set here will be removed by the system
2795     * in various situations (such as the user moving to another application) like
2796     * the other system UI states.
2797     *
2798     * <p>When using this flag, the application should provide some easy facility
2799     * for the user to go out of it.  A common example would be in an e-book
2800     * reader, where tapping on the screen brings back whatever screen and UI
2801     * decorations that had been hidden while the user was immersed in reading
2802     * the book.
2803     *
2804     * @see #setSystemUiVisibility(int)
2805     */
2806    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2807
2808    /**
2809     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2810     * flags, we would like a stable view of the content insets given to
2811     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2812     * will always represent the worst case that the application can expect
2813     * as a continuous state.  In the stock Android UI this is the space for
2814     * the system bar, nav bar, and status bar, but not more transient elements
2815     * such as an input method.
2816     *
2817     * The stable layout your UI sees is based on the system UI modes you can
2818     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2819     * then you will get a stable layout for changes of the
2820     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2821     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2822     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2823     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2824     * with a stable layout.  (Note that you should avoid using
2825     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2826     *
2827     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2828     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2829     * then a hidden status bar will be considered a "stable" state for purposes
2830     * here.  This allows your UI to continually hide the status bar, while still
2831     * using the system UI flags to hide the action bar while still retaining
2832     * a stable layout.  Note that changing the window fullscreen flag will never
2833     * provide a stable layout for a clean transition.
2834     *
2835     * <p>If you are using ActionBar in
2836     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2837     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2838     * insets it adds to those given to the application.
2839     */
2840    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2841
2842    /**
2843     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2844     * to be laid out as if it has requested
2845     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2846     * allows it to avoid artifacts when switching in and out of that mode, at
2847     * the expense that some of its user interface may be covered by screen
2848     * decorations when they are shown.  You can perform layout of your inner
2849     * UI elements to account for the navigation system UI through the
2850     * {@link #fitSystemWindows(Rect)} method.
2851     */
2852    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2853
2854    /**
2855     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2856     * to be laid out as if it has requested
2857     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2858     * allows it to avoid artifacts when switching in and out of that mode, at
2859     * the expense that some of its user interface may be covered by screen
2860     * decorations when they are shown.  You can perform layout of your inner
2861     * UI elements to account for non-fullscreen system UI through the
2862     * {@link #fitSystemWindows(Rect)} method.
2863     */
2864    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2865
2866    /**
2867     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2868     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2869     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2870     * user interaction.
2871     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2872     * has an effect when used in combination with that flag.</p>
2873     */
2874    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2875
2876    /**
2877     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2878     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2879     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2880     * experience while also hiding the system bars.  If this flag is not set,
2881     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2882     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2883     * if the user swipes from the top of the screen.
2884     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2885     * system gestures, such as swiping from the top of the screen.  These transient system bars
2886     * will overlay app’s content, may have some degree of transparency, and will automatically
2887     * hide after a short timeout.
2888     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2889     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2890     * with one or both of those flags.</p>
2891     */
2892    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2893
2894    /**
2895     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2896     * is compatible with light status bar backgrounds.
2897     *
2898     * <p>For this to take effect, the window must request
2899     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2900     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2901     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2902     *         FLAG_TRANSLUCENT_STATUS}.
2903     *
2904     * @see android.R.attr#windowLightStatusBar
2905     */
2906    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2907
2908    /**
2909     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2910     */
2911    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2912
2913    /**
2914     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2915     */
2916    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2917
2918    /**
2919     * @hide
2920     *
2921     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2922     * out of the public fields to keep the undefined bits out of the developer's way.
2923     *
2924     * Flag to make the status bar not expandable.  Unless you also
2925     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2926     */
2927    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2928
2929    /**
2930     * @hide
2931     *
2932     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2933     * out of the public fields to keep the undefined bits out of the developer's way.
2934     *
2935     * Flag to hide notification icons and scrolling ticker text.
2936     */
2937    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2938
2939    /**
2940     * @hide
2941     *
2942     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2943     * out of the public fields to keep the undefined bits out of the developer's way.
2944     *
2945     * Flag to disable incoming notification alerts.  This will not block
2946     * icons, but it will block sound, vibrating and other visual or aural notifications.
2947     */
2948    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2949
2950    /**
2951     * @hide
2952     *
2953     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2954     * out of the public fields to keep the undefined bits out of the developer's way.
2955     *
2956     * Flag to hide only the scrolling ticker.  Note that
2957     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2958     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2959     */
2960    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2961
2962    /**
2963     * @hide
2964     *
2965     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2966     * out of the public fields to keep the undefined bits out of the developer's way.
2967     *
2968     * Flag to hide the center system info area.
2969     */
2970    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2971
2972    /**
2973     * @hide
2974     *
2975     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2976     * out of the public fields to keep the undefined bits out of the developer's way.
2977     *
2978     * Flag to hide only the home button.  Don't use this
2979     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2980     */
2981    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2982
2983    /**
2984     * @hide
2985     *
2986     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2987     * out of the public fields to keep the undefined bits out of the developer's way.
2988     *
2989     * Flag to hide only the back button. Don't use this
2990     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2991     */
2992    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2993
2994    /**
2995     * @hide
2996     *
2997     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2998     * out of the public fields to keep the undefined bits out of the developer's way.
2999     *
3000     * Flag to hide only the clock.  You might use this if your activity has
3001     * its own clock making the status bar's clock redundant.
3002     */
3003    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3004
3005    /**
3006     * @hide
3007     *
3008     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3009     * out of the public fields to keep the undefined bits out of the developer's way.
3010     *
3011     * Flag to hide only the recent apps button. Don't use this
3012     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3013     */
3014    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3015
3016    /**
3017     * @hide
3018     *
3019     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3020     * out of the public fields to keep the undefined bits out of the developer's way.
3021     *
3022     * Flag to disable the global search gesture. Don't use this
3023     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3024     */
3025    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3026
3027    /**
3028     * @hide
3029     *
3030     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3031     * out of the public fields to keep the undefined bits out of the developer's way.
3032     *
3033     * Flag to specify that the status bar is displayed in transient mode.
3034     */
3035    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3036
3037    /**
3038     * @hide
3039     *
3040     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3041     * out of the public fields to keep the undefined bits out of the developer's way.
3042     *
3043     * Flag to specify that the navigation bar is displayed in transient mode.
3044     */
3045    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3046
3047    /**
3048     * @hide
3049     *
3050     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3051     * out of the public fields to keep the undefined bits out of the developer's way.
3052     *
3053     * Flag to specify that the hidden status bar would like to be shown.
3054     */
3055    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3056
3057    /**
3058     * @hide
3059     *
3060     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3061     * out of the public fields to keep the undefined bits out of the developer's way.
3062     *
3063     * Flag to specify that the hidden navigation bar would like to be shown.
3064     */
3065    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3066
3067    /**
3068     * @hide
3069     *
3070     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3071     * out of the public fields to keep the undefined bits out of the developer's way.
3072     *
3073     * Flag to specify that the status bar is displayed in translucent mode.
3074     */
3075    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3076
3077    /**
3078     * @hide
3079     *
3080     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3081     * out of the public fields to keep the undefined bits out of the developer's way.
3082     *
3083     * Flag to specify that the navigation bar is displayed in translucent mode.
3084     */
3085    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3086
3087    /**
3088     * @hide
3089     *
3090     * Whether Recents is visible or not.
3091     */
3092    public static final int RECENT_APPS_VISIBLE = 0x00004000;
3093
3094    /**
3095     * @hide
3096     *
3097     * Whether the TV's picture-in-picture is visible or not.
3098     */
3099    public static final int TV_PICTURE_IN_PICTURE_VISIBLE = 0x00010000;
3100
3101    /**
3102     * @hide
3103     *
3104     * Makes navigation bar transparent (but not the status bar).
3105     */
3106    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3107
3108    /**
3109     * @hide
3110     *
3111     * Makes status bar transparent (but not the navigation bar).
3112     */
3113    public static final int STATUS_BAR_TRANSPARENT = 0x0000008;
3114
3115    /**
3116     * @hide
3117     *
3118     * Makes both status bar and navigation bar transparent.
3119     */
3120    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3121            | STATUS_BAR_TRANSPARENT;
3122
3123    /**
3124     * @hide
3125     */
3126    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3127
3128    /**
3129     * These are the system UI flags that can be cleared by events outside
3130     * of an application.  Currently this is just the ability to tap on the
3131     * screen while hiding the navigation bar to have it return.
3132     * @hide
3133     */
3134    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3135            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3136            | SYSTEM_UI_FLAG_FULLSCREEN;
3137
3138    /**
3139     * Flags that can impact the layout in relation to system UI.
3140     */
3141    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3142            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3143            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3144
3145    /** @hide */
3146    @IntDef(flag = true,
3147            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3148    @Retention(RetentionPolicy.SOURCE)
3149    public @interface FindViewFlags {}
3150
3151    /**
3152     * Find views that render the specified text.
3153     *
3154     * @see #findViewsWithText(ArrayList, CharSequence, int)
3155     */
3156    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3157
3158    /**
3159     * Find find views that contain the specified content description.
3160     *
3161     * @see #findViewsWithText(ArrayList, CharSequence, int)
3162     */
3163    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3164
3165    /**
3166     * Find views that contain {@link AccessibilityNodeProvider}. Such
3167     * a View is a root of virtual view hierarchy and may contain the searched
3168     * text. If this flag is set Views with providers are automatically
3169     * added and it is a responsibility of the client to call the APIs of
3170     * the provider to determine whether the virtual tree rooted at this View
3171     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3172     * representing the virtual views with this text.
3173     *
3174     * @see #findViewsWithText(ArrayList, CharSequence, int)
3175     *
3176     * @hide
3177     */
3178    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3179
3180    /**
3181     * The undefined cursor position.
3182     *
3183     * @hide
3184     */
3185    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3186
3187    /**
3188     * Indicates that the screen has changed state and is now off.
3189     *
3190     * @see #onScreenStateChanged(int)
3191     */
3192    public static final int SCREEN_STATE_OFF = 0x0;
3193
3194    /**
3195     * Indicates that the screen has changed state and is now on.
3196     *
3197     * @see #onScreenStateChanged(int)
3198     */
3199    public static final int SCREEN_STATE_ON = 0x1;
3200
3201    /**
3202     * Indicates no axis of view scrolling.
3203     */
3204    public static final int SCROLL_AXIS_NONE = 0;
3205
3206    /**
3207     * Indicates scrolling along the horizontal axis.
3208     */
3209    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3210
3211    /**
3212     * Indicates scrolling along the vertical axis.
3213     */
3214    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3215
3216    /**
3217     * Controls the over-scroll mode for this view.
3218     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3219     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3220     * and {@link #OVER_SCROLL_NEVER}.
3221     */
3222    private int mOverScrollMode;
3223
3224    /**
3225     * The parent this view is attached to.
3226     * {@hide}
3227     *
3228     * @see #getParent()
3229     */
3230    protected ViewParent mParent;
3231
3232    /**
3233     * {@hide}
3234     */
3235    AttachInfo mAttachInfo;
3236
3237    /**
3238     * {@hide}
3239     */
3240    @ViewDebug.ExportedProperty(flagMapping = {
3241        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3242                name = "FORCE_LAYOUT"),
3243        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3244                name = "LAYOUT_REQUIRED"),
3245        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3246            name = "DRAWING_CACHE_INVALID", outputIf = false),
3247        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3248        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3249        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3250        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3251    }, formatToHexString = true)
3252    int mPrivateFlags;
3253    int mPrivateFlags2;
3254    int mPrivateFlags3;
3255
3256    /**
3257     * This view's request for the visibility of the status bar.
3258     * @hide
3259     */
3260    @ViewDebug.ExportedProperty(flagMapping = {
3261        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3262                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3263                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3264        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3265                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3266                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3267        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3268                                equals = SYSTEM_UI_FLAG_VISIBLE,
3269                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3270    }, formatToHexString = true)
3271    int mSystemUiVisibility;
3272
3273    /**
3274     * Reference count for transient state.
3275     * @see #setHasTransientState(boolean)
3276     */
3277    int mTransientStateCount = 0;
3278
3279    /**
3280     * Count of how many windows this view has been attached to.
3281     */
3282    int mWindowAttachCount;
3283
3284    /**
3285     * The layout parameters associated with this view and used by the parent
3286     * {@link android.view.ViewGroup} to determine how this view should be
3287     * laid out.
3288     * {@hide}
3289     */
3290    protected ViewGroup.LayoutParams mLayoutParams;
3291
3292    /**
3293     * The view flags hold various views states.
3294     * {@hide}
3295     */
3296    @ViewDebug.ExportedProperty(formatToHexString = true)
3297    int mViewFlags;
3298
3299    static class TransformationInfo {
3300        /**
3301         * The transform matrix for the View. This transform is calculated internally
3302         * based on the translation, rotation, and scale properties.
3303         *
3304         * Do *not* use this variable directly; instead call getMatrix(), which will
3305         * load the value from the View's RenderNode.
3306         */
3307        private final Matrix mMatrix = new Matrix();
3308
3309        /**
3310         * The inverse transform matrix for the View. This transform is calculated
3311         * internally based on the translation, rotation, and scale properties.
3312         *
3313         * Do *not* use this variable directly; instead call getInverseMatrix(),
3314         * which will load the value from the View's RenderNode.
3315         */
3316        private Matrix mInverseMatrix;
3317
3318        /**
3319         * The opacity of the View. This is a value from 0 to 1, where 0 means
3320         * completely transparent and 1 means completely opaque.
3321         */
3322        @ViewDebug.ExportedProperty
3323        float mAlpha = 1f;
3324
3325        /**
3326         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3327         * property only used by transitions, which is composited with the other alpha
3328         * values to calculate the final visual alpha value.
3329         */
3330        float mTransitionAlpha = 1f;
3331    }
3332
3333    TransformationInfo mTransformationInfo;
3334
3335    /**
3336     * Current clip bounds. to which all drawing of this view are constrained.
3337     */
3338    Rect mClipBounds = null;
3339
3340    private boolean mLastIsOpaque;
3341
3342    /**
3343     * The distance in pixels from the left edge of this view's parent
3344     * to the left edge of this view.
3345     * {@hide}
3346     */
3347    @ViewDebug.ExportedProperty(category = "layout")
3348    protected int mLeft;
3349    /**
3350     * The distance in pixels from the left edge of this view's parent
3351     * to the right edge of this view.
3352     * {@hide}
3353     */
3354    @ViewDebug.ExportedProperty(category = "layout")
3355    protected int mRight;
3356    /**
3357     * The distance in pixels from the top edge of this view's parent
3358     * to the top edge of this view.
3359     * {@hide}
3360     */
3361    @ViewDebug.ExportedProperty(category = "layout")
3362    protected int mTop;
3363    /**
3364     * The distance in pixels from the top edge of this view's parent
3365     * to the bottom edge of this view.
3366     * {@hide}
3367     */
3368    @ViewDebug.ExportedProperty(category = "layout")
3369    protected int mBottom;
3370
3371    /**
3372     * The offset, in pixels, by which the content of this view is scrolled
3373     * horizontally.
3374     * {@hide}
3375     */
3376    @ViewDebug.ExportedProperty(category = "scrolling")
3377    protected int mScrollX;
3378    /**
3379     * The offset, in pixels, by which the content of this view is scrolled
3380     * vertically.
3381     * {@hide}
3382     */
3383    @ViewDebug.ExportedProperty(category = "scrolling")
3384    protected int mScrollY;
3385
3386    /**
3387     * The left padding in pixels, that is the distance in pixels between the
3388     * left edge of this view and the left edge of its content.
3389     * {@hide}
3390     */
3391    @ViewDebug.ExportedProperty(category = "padding")
3392    protected int mPaddingLeft = 0;
3393    /**
3394     * The right padding in pixels, that is the distance in pixels between the
3395     * right edge of this view and the right edge of its content.
3396     * {@hide}
3397     */
3398    @ViewDebug.ExportedProperty(category = "padding")
3399    protected int mPaddingRight = 0;
3400    /**
3401     * The top padding in pixels, that is the distance in pixels between the
3402     * top edge of this view and the top edge of its content.
3403     * {@hide}
3404     */
3405    @ViewDebug.ExportedProperty(category = "padding")
3406    protected int mPaddingTop;
3407    /**
3408     * The bottom padding in pixels, that is the distance in pixels between the
3409     * bottom edge of this view and the bottom edge of its content.
3410     * {@hide}
3411     */
3412    @ViewDebug.ExportedProperty(category = "padding")
3413    protected int mPaddingBottom;
3414
3415    /**
3416     * The layout insets in pixels, that is the distance in pixels between the
3417     * visible edges of this view its bounds.
3418     */
3419    private Insets mLayoutInsets;
3420
3421    /**
3422     * Briefly describes the view and is primarily used for accessibility support.
3423     */
3424    private CharSequence mContentDescription;
3425
3426    /**
3427     * Specifies the id of a view for which this view serves as a label for
3428     * accessibility purposes.
3429     */
3430    private int mLabelForId = View.NO_ID;
3431
3432    /**
3433     * Predicate for matching labeled view id with its label for
3434     * accessibility purposes.
3435     */
3436    private MatchLabelForPredicate mMatchLabelForPredicate;
3437
3438    /**
3439     * Specifies a view before which this one is visited in accessibility traversal.
3440     */
3441    private int mAccessibilityTraversalBeforeId = NO_ID;
3442
3443    /**
3444     * Specifies a view after which this one is visited in accessibility traversal.
3445     */
3446    private int mAccessibilityTraversalAfterId = NO_ID;
3447
3448    /**
3449     * Predicate for matching a view by its id.
3450     */
3451    private MatchIdPredicate mMatchIdPredicate;
3452
3453    /**
3454     * Cache the paddingRight set by the user to append to the scrollbar's size.
3455     *
3456     * @hide
3457     */
3458    @ViewDebug.ExportedProperty(category = "padding")
3459    protected int mUserPaddingRight;
3460
3461    /**
3462     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3463     *
3464     * @hide
3465     */
3466    @ViewDebug.ExportedProperty(category = "padding")
3467    protected int mUserPaddingBottom;
3468
3469    /**
3470     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3471     *
3472     * @hide
3473     */
3474    @ViewDebug.ExportedProperty(category = "padding")
3475    protected int mUserPaddingLeft;
3476
3477    /**
3478     * Cache the paddingStart set by the user to append to the scrollbar's size.
3479     *
3480     */
3481    @ViewDebug.ExportedProperty(category = "padding")
3482    int mUserPaddingStart;
3483
3484    /**
3485     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3486     *
3487     */
3488    @ViewDebug.ExportedProperty(category = "padding")
3489    int mUserPaddingEnd;
3490
3491    /**
3492     * Cache initial left padding.
3493     *
3494     * @hide
3495     */
3496    int mUserPaddingLeftInitial;
3497
3498    /**
3499     * Cache initial right padding.
3500     *
3501     * @hide
3502     */
3503    int mUserPaddingRightInitial;
3504
3505    /**
3506     * Default undefined padding
3507     */
3508    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3509
3510    /**
3511     * Cache if a left padding has been defined
3512     */
3513    private boolean mLeftPaddingDefined = false;
3514
3515    /**
3516     * Cache if a right padding has been defined
3517     */
3518    private boolean mRightPaddingDefined = false;
3519
3520    /**
3521     * @hide
3522     */
3523    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3524    /**
3525     * @hide
3526     */
3527    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3528
3529    private LongSparseLongArray mMeasureCache;
3530
3531    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3532    private Drawable mBackground;
3533    private TintInfo mBackgroundTint;
3534
3535    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3536    private ForegroundInfo mForegroundInfo;
3537
3538    private Drawable mScrollIndicatorDrawable;
3539
3540    /**
3541     * RenderNode used for backgrounds.
3542     * <p>
3543     * When non-null and valid, this is expected to contain an up-to-date copy
3544     * of the background drawable. It is cleared on temporary detach, and reset
3545     * on cleanup.
3546     */
3547    private RenderNode mBackgroundRenderNode;
3548
3549    private int mBackgroundResource;
3550    private boolean mBackgroundSizeChanged;
3551
3552    private String mTransitionName;
3553
3554    static class TintInfo {
3555        ColorStateList mTintList;
3556        PorterDuff.Mode mTintMode;
3557        boolean mHasTintMode;
3558        boolean mHasTintList;
3559    }
3560
3561    private static class ForegroundInfo {
3562        private Drawable mDrawable;
3563        private TintInfo mTintInfo;
3564        private int mGravity = Gravity.FILL;
3565        private boolean mInsidePadding = true;
3566        private boolean mBoundsChanged = true;
3567        private final Rect mSelfBounds = new Rect();
3568        private final Rect mOverlayBounds = new Rect();
3569    }
3570
3571    static class ListenerInfo {
3572        /**
3573         * Listener used to dispatch focus change events.
3574         * This field should be made private, so it is hidden from the SDK.
3575         * {@hide}
3576         */
3577        protected OnFocusChangeListener mOnFocusChangeListener;
3578
3579        /**
3580         * Listeners for layout change events.
3581         */
3582        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3583
3584        protected OnScrollChangeListener mOnScrollChangeListener;
3585
3586        /**
3587         * Listeners for attach events.
3588         */
3589        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3590
3591        /**
3592         * Listener used to dispatch click events.
3593         * This field should be made private, so it is hidden from the SDK.
3594         * {@hide}
3595         */
3596        public OnClickListener mOnClickListener;
3597
3598        /**
3599         * Listener used to dispatch long click events.
3600         * This field should be made private, so it is hidden from the SDK.
3601         * {@hide}
3602         */
3603        protected OnLongClickListener mOnLongClickListener;
3604
3605        /**
3606         * Listener used to dispatch context click events. This field should be made private, so it
3607         * is hidden from the SDK.
3608         * {@hide}
3609         */
3610        protected OnContextClickListener mOnContextClickListener;
3611
3612        /**
3613         * Listener used to build the context menu.
3614         * This field should be made private, so it is hidden from the SDK.
3615         * {@hide}
3616         */
3617        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3618
3619        private OnKeyListener mOnKeyListener;
3620
3621        private OnTouchListener mOnTouchListener;
3622
3623        private OnHoverListener mOnHoverListener;
3624
3625        private OnGenericMotionListener mOnGenericMotionListener;
3626
3627        private OnDragListener mOnDragListener;
3628
3629        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3630
3631        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3632    }
3633
3634    ListenerInfo mListenerInfo;
3635
3636    // Temporary values used to hold (x,y) coordinates when delegating from the
3637    // two-arg performLongClick() method to the legacy no-arg version.
3638    private float mLongClickX = Float.NaN;
3639    private float mLongClickY = Float.NaN;
3640
3641    /**
3642     * The application environment this view lives in.
3643     * This field should be made private, so it is hidden from the SDK.
3644     * {@hide}
3645     */
3646    @ViewDebug.ExportedProperty(deepExport = true)
3647    protected Context mContext;
3648
3649    private final Resources mResources;
3650
3651    private ScrollabilityCache mScrollCache;
3652
3653    private int[] mDrawableState = null;
3654
3655    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3656
3657    /**
3658     * Animator that automatically runs based on state changes.
3659     */
3660    private StateListAnimator mStateListAnimator;
3661
3662    /**
3663     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3664     * the user may specify which view to go to next.
3665     */
3666    private int mNextFocusLeftId = View.NO_ID;
3667
3668    /**
3669     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3670     * the user may specify which view to go to next.
3671     */
3672    private int mNextFocusRightId = View.NO_ID;
3673
3674    /**
3675     * When this view has focus and the next focus is {@link #FOCUS_UP},
3676     * the user may specify which view to go to next.
3677     */
3678    private int mNextFocusUpId = View.NO_ID;
3679
3680    /**
3681     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3682     * the user may specify which view to go to next.
3683     */
3684    private int mNextFocusDownId = View.NO_ID;
3685
3686    /**
3687     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3688     * the user may specify which view to go to next.
3689     */
3690    int mNextFocusForwardId = View.NO_ID;
3691
3692    private CheckForLongPress mPendingCheckForLongPress;
3693    private CheckForTap mPendingCheckForTap = null;
3694    private PerformClick mPerformClick;
3695    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3696
3697    private UnsetPressedState mUnsetPressedState;
3698
3699    /**
3700     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3701     * up event while a long press is invoked as soon as the long press duration is reached, so
3702     * a long press could be performed before the tap is checked, in which case the tap's action
3703     * should not be invoked.
3704     */
3705    private boolean mHasPerformedLongPress;
3706
3707    /**
3708     * Whether a context click button is currently pressed down. This is true when the stylus is
3709     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3710     * pressed. This is false once the button is released or if the stylus has been lifted.
3711     */
3712    private boolean mInContextButtonPress;
3713
3714    /**
3715     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3716     * true after a stylus button press has occured, when the next up event should not be recognized
3717     * as a tap.
3718     */
3719    private boolean mIgnoreNextUpEvent;
3720
3721    /**
3722     * The minimum height of the view. We'll try our best to have the height
3723     * of this view to at least this amount.
3724     */
3725    @ViewDebug.ExportedProperty(category = "measurement")
3726    private int mMinHeight;
3727
3728    /**
3729     * The minimum width of the view. We'll try our best to have the width
3730     * of this view to at least this amount.
3731     */
3732    @ViewDebug.ExportedProperty(category = "measurement")
3733    private int mMinWidth;
3734
3735    /**
3736     * The delegate to handle touch events that are physically in this view
3737     * but should be handled by another view.
3738     */
3739    private TouchDelegate mTouchDelegate = null;
3740
3741    /**
3742     * Solid color to use as a background when creating the drawing cache. Enables
3743     * the cache to use 16 bit bitmaps instead of 32 bit.
3744     */
3745    private int mDrawingCacheBackgroundColor = 0;
3746
3747    /**
3748     * Special tree observer used when mAttachInfo is null.
3749     */
3750    private ViewTreeObserver mFloatingTreeObserver;
3751
3752    /**
3753     * Cache the touch slop from the context that created the view.
3754     */
3755    private int mTouchSlop;
3756
3757    /**
3758     * Object that handles automatic animation of view properties.
3759     */
3760    private ViewPropertyAnimator mAnimator = null;
3761
3762    /**
3763     * List of registered FrameMetricsObservers.
3764     */
3765    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
3766
3767    /**
3768     * Flag indicating that a drag can cross window boundaries.  When
3769     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3770     * with this flag set, all visible applications with targetSdkVersion >=
3771     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
3772     * in the drag operation and receive the dragged content.
3773     *
3774     * If this is the only flag set, then the drag recipient will only have access to text data
3775     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3776     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags.
3777     */
3778    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3779
3780    /**
3781     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3782     * request read access to the content URI(s) contained in the {@link ClipData} object.
3783     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3784     */
3785    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3786
3787    /**
3788     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3789     * request write access to the content URI(s) contained in the {@link ClipData} object.
3790     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3791     */
3792    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3793
3794    /**
3795     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3796     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3797     * reboots until explicitly revoked with
3798     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3799     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3800     */
3801    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3802            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3803
3804    /**
3805     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3806     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3807     * match against the original granted URI.
3808     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3809     */
3810    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3811            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3812
3813    /**
3814     * Flag indicating that the drag shadow will be opaque.  When
3815     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3816     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3817     */
3818    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3819
3820    /**
3821     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3822     */
3823    private float mVerticalScrollFactor;
3824
3825    /**
3826     * Position of the vertical scroll bar.
3827     */
3828    private int mVerticalScrollbarPosition;
3829
3830    /**
3831     * Position the scroll bar at the default position as determined by the system.
3832     */
3833    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3834
3835    /**
3836     * Position the scroll bar along the left edge.
3837     */
3838    public static final int SCROLLBAR_POSITION_LEFT = 1;
3839
3840    /**
3841     * Position the scroll bar along the right edge.
3842     */
3843    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3844
3845    /**
3846     * Indicates that the view does not have a layer.
3847     *
3848     * @see #getLayerType()
3849     * @see #setLayerType(int, android.graphics.Paint)
3850     * @see #LAYER_TYPE_SOFTWARE
3851     * @see #LAYER_TYPE_HARDWARE
3852     */
3853    public static final int LAYER_TYPE_NONE = 0;
3854
3855    /**
3856     * <p>Indicates that the view has a software layer. A software layer is backed
3857     * by a bitmap and causes the view to be rendered using Android's software
3858     * rendering pipeline, even if hardware acceleration is enabled.</p>
3859     *
3860     * <p>Software layers have various usages:</p>
3861     * <p>When the application is not using hardware acceleration, a software layer
3862     * is useful to apply a specific color filter and/or blending mode and/or
3863     * translucency to a view and all its children.</p>
3864     * <p>When the application is using hardware acceleration, a software layer
3865     * is useful to render drawing primitives not supported by the hardware
3866     * accelerated pipeline. It can also be used to cache a complex view tree
3867     * into a texture and reduce the complexity of drawing operations. For instance,
3868     * when animating a complex view tree with a translation, a software layer can
3869     * be used to render the view tree only once.</p>
3870     * <p>Software layers should be avoided when the affected view tree updates
3871     * often. Every update will require to re-render the software layer, which can
3872     * potentially be slow (particularly when hardware acceleration is turned on
3873     * since the layer will have to be uploaded into a hardware texture after every
3874     * update.)</p>
3875     *
3876     * @see #getLayerType()
3877     * @see #setLayerType(int, android.graphics.Paint)
3878     * @see #LAYER_TYPE_NONE
3879     * @see #LAYER_TYPE_HARDWARE
3880     */
3881    public static final int LAYER_TYPE_SOFTWARE = 1;
3882
3883    /**
3884     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3885     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3886     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3887     * rendering pipeline, but only if hardware acceleration is turned on for the
3888     * view hierarchy. When hardware acceleration is turned off, hardware layers
3889     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3890     *
3891     * <p>A hardware layer is useful to apply a specific color filter and/or
3892     * blending mode and/or translucency to a view and all its children.</p>
3893     * <p>A hardware layer can be used to cache a complex view tree into a
3894     * texture and reduce the complexity of drawing operations. For instance,
3895     * when animating a complex view tree with a translation, a hardware layer can
3896     * be used to render the view tree only once.</p>
3897     * <p>A hardware layer can also be used to increase the rendering quality when
3898     * rotation transformations are applied on a view. It can also be used to
3899     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3900     *
3901     * @see #getLayerType()
3902     * @see #setLayerType(int, android.graphics.Paint)
3903     * @see #LAYER_TYPE_NONE
3904     * @see #LAYER_TYPE_SOFTWARE
3905     */
3906    public static final int LAYER_TYPE_HARDWARE = 2;
3907
3908    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3909            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3910            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3911            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3912    })
3913    int mLayerType = LAYER_TYPE_NONE;
3914    Paint mLayerPaint;
3915
3916    /**
3917     * Set to true when drawing cache is enabled and cannot be created.
3918     *
3919     * @hide
3920     */
3921    public boolean mCachingFailed;
3922    private Bitmap mDrawingCache;
3923    private Bitmap mUnscaledDrawingCache;
3924
3925    /**
3926     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3927     * <p>
3928     * When non-null and valid, this is expected to contain an up-to-date copy
3929     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3930     * cleanup.
3931     */
3932    final RenderNode mRenderNode;
3933
3934    /**
3935     * Set to true when the view is sending hover accessibility events because it
3936     * is the innermost hovered view.
3937     */
3938    private boolean mSendingHoverAccessibilityEvents;
3939
3940    /**
3941     * Delegate for injecting accessibility functionality.
3942     */
3943    AccessibilityDelegate mAccessibilityDelegate;
3944
3945    /**
3946     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3947     * and add/remove objects to/from the overlay directly through the Overlay methods.
3948     */
3949    ViewOverlay mOverlay;
3950
3951    /**
3952     * The currently active parent view for receiving delegated nested scrolling events.
3953     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3954     * by {@link #stopNestedScroll()} at the same point where we clear
3955     * requestDisallowInterceptTouchEvent.
3956     */
3957    private ViewParent mNestedScrollingParent;
3958
3959    /**
3960     * Consistency verifier for debugging purposes.
3961     * @hide
3962     */
3963    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3964            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3965                    new InputEventConsistencyVerifier(this, 0) : null;
3966
3967    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3968
3969    private int[] mTempNestedScrollConsumed;
3970
3971    /**
3972     * An overlay is going to draw this View instead of being drawn as part of this
3973     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3974     * when this view is invalidated.
3975     */
3976    GhostView mGhostView;
3977
3978    /**
3979     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3980     * @hide
3981     */
3982    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3983    public String[] mAttributes;
3984
3985    /**
3986     * Maps a Resource id to its name.
3987     */
3988    private static SparseArray<String> mAttributeMap;
3989
3990    /**
3991     * Queue of pending runnables. Used to postpone calls to post() until this
3992     * view is attached and has a handler.
3993     */
3994    private HandlerActionQueue mRunQueue;
3995
3996    /**
3997     * The pointer icon when the mouse hovers on this view. The default is null.
3998     */
3999    private PointerIcon mPointerIcon;
4000
4001    /**
4002     * @hide
4003     */
4004    String mStartActivityRequestWho;
4005
4006    @Nullable
4007    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4008
4009    /**
4010     * Simple constructor to use when creating a view from code.
4011     *
4012     * @param context The Context the view is running in, through which it can
4013     *        access the current theme, resources, etc.
4014     */
4015    public View(Context context) {
4016        mContext = context;
4017        mResources = context != null ? context.getResources() : null;
4018        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
4019        // Set some flags defaults
4020        mPrivateFlags2 =
4021                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4022                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4023                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4024                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4025                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4026                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4027        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4028        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4029        mUserPaddingStart = UNDEFINED_PADDING;
4030        mUserPaddingEnd = UNDEFINED_PADDING;
4031        mRenderNode = RenderNode.create(getClass().getName(), this);
4032
4033        if (!sCompatibilityDone && context != null) {
4034            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4035
4036            // Older apps may need this compatibility hack for measurement.
4037            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
4038
4039            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4040            // of whether a layout was requested on that View.
4041            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
4042
4043            Canvas.sCompatibilityRestore = targetSdkVersion < M;
4044
4045            // In M and newer, our widgets can pass a "hint" value in the size
4046            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4047            // know what the expected parent size is going to be, so e.g. list items can size
4048            // themselves at 1/3 the size of their container. It breaks older apps though,
4049            // specifically apps that use some popular open source libraries.
4050            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
4051
4052            // Old versions of the platform would give different results from
4053            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4054            // modes, so we always need to run an additional EXACTLY pass.
4055            sAlwaysRemeasureExactly = targetSdkVersion <= M;
4056
4057            // Prior to N, layout params could change without requiring a
4058            // subsequent call to setLayoutParams() and they would usually
4059            // work. Partial layout breaks this assumption.
4060            sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
4061
4062            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4063            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4064            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
4065
4066            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4067            // in apps so we target check it to avoid breaking existing apps.
4068            sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N;
4069
4070            sCompatibilityDone = true;
4071        }
4072    }
4073
4074    /**
4075     * Constructor that is called when inflating a view from XML. This is called
4076     * when a view is being constructed from an XML file, supplying attributes
4077     * that were specified in the XML file. This version uses a default style of
4078     * 0, so the only attribute values applied are those in the Context's Theme
4079     * and the given AttributeSet.
4080     *
4081     * <p>
4082     * The method onFinishInflate() will be called after all children have been
4083     * added.
4084     *
4085     * @param context The Context the view is running in, through which it can
4086     *        access the current theme, resources, etc.
4087     * @param attrs The attributes of the XML tag that is inflating the view.
4088     * @see #View(Context, AttributeSet, int)
4089     */
4090    public View(Context context, @Nullable AttributeSet attrs) {
4091        this(context, attrs, 0);
4092    }
4093
4094    /**
4095     * Perform inflation from XML and apply a class-specific base style from a
4096     * theme attribute. This constructor of View allows subclasses to use their
4097     * own base style when they are inflating. For example, a Button class's
4098     * constructor would call this version of the super class constructor and
4099     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4100     * allows the theme's button style to modify all of the base view attributes
4101     * (in particular its background) as well as the Button class's attributes.
4102     *
4103     * @param context The Context the view is running in, through which it can
4104     *        access the current theme, resources, etc.
4105     * @param attrs The attributes of the XML tag that is inflating the view.
4106     * @param defStyleAttr An attribute in the current theme that contains a
4107     *        reference to a style resource that supplies default values for
4108     *        the view. Can be 0 to not look for defaults.
4109     * @see #View(Context, AttributeSet)
4110     */
4111    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4112        this(context, attrs, defStyleAttr, 0);
4113    }
4114
4115    /**
4116     * Perform inflation from XML and apply a class-specific base style from a
4117     * theme attribute or style resource. This constructor of View allows
4118     * subclasses to use their own base style when they are inflating.
4119     * <p>
4120     * When determining the final value of a particular attribute, there are
4121     * four inputs that come into play:
4122     * <ol>
4123     * <li>Any attribute values in the given AttributeSet.
4124     * <li>The style resource specified in the AttributeSet (named "style").
4125     * <li>The default style specified by <var>defStyleAttr</var>.
4126     * <li>The default style specified by <var>defStyleRes</var>.
4127     * <li>The base values in this theme.
4128     * </ol>
4129     * <p>
4130     * Each of these inputs is considered in-order, with the first listed taking
4131     * precedence over the following ones. In other words, if in the
4132     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4133     * , then the button's text will <em>always</em> be black, regardless of
4134     * what is specified in any of the styles.
4135     *
4136     * @param context The Context the view is running in, through which it can
4137     *        access the current theme, resources, etc.
4138     * @param attrs The attributes of the XML tag that is inflating the view.
4139     * @param defStyleAttr An attribute in the current theme that contains a
4140     *        reference to a style resource that supplies default values for
4141     *        the view. Can be 0 to not look for defaults.
4142     * @param defStyleRes A resource identifier of a style resource that
4143     *        supplies default values for the view, used only if
4144     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4145     *        to not look for defaults.
4146     * @see #View(Context, AttributeSet, int)
4147     */
4148    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4149        this(context);
4150
4151        final TypedArray a = context.obtainStyledAttributes(
4152                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4153
4154        if (mDebugViewAttributes) {
4155            saveAttributeData(attrs, a);
4156        }
4157
4158        Drawable background = null;
4159
4160        int leftPadding = -1;
4161        int topPadding = -1;
4162        int rightPadding = -1;
4163        int bottomPadding = -1;
4164        int startPadding = UNDEFINED_PADDING;
4165        int endPadding = UNDEFINED_PADDING;
4166
4167        int padding = -1;
4168
4169        int viewFlagValues = 0;
4170        int viewFlagMasks = 0;
4171
4172        boolean setScrollContainer = false;
4173
4174        int x = 0;
4175        int y = 0;
4176
4177        float tx = 0;
4178        float ty = 0;
4179        float tz = 0;
4180        float elevation = 0;
4181        float rotation = 0;
4182        float rotationX = 0;
4183        float rotationY = 0;
4184        float sx = 1f;
4185        float sy = 1f;
4186        boolean transformSet = false;
4187
4188        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4189        int overScrollMode = mOverScrollMode;
4190        boolean initializeScrollbars = false;
4191        boolean initializeScrollIndicators = false;
4192
4193        boolean startPaddingDefined = false;
4194        boolean endPaddingDefined = false;
4195        boolean leftPaddingDefined = false;
4196        boolean rightPaddingDefined = false;
4197
4198        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4199
4200        final int N = a.getIndexCount();
4201        for (int i = 0; i < N; i++) {
4202            int attr = a.getIndex(i);
4203            switch (attr) {
4204                case com.android.internal.R.styleable.View_background:
4205                    background = a.getDrawable(attr);
4206                    break;
4207                case com.android.internal.R.styleable.View_padding:
4208                    padding = a.getDimensionPixelSize(attr, -1);
4209                    mUserPaddingLeftInitial = padding;
4210                    mUserPaddingRightInitial = padding;
4211                    leftPaddingDefined = true;
4212                    rightPaddingDefined = true;
4213                    break;
4214                 case com.android.internal.R.styleable.View_paddingLeft:
4215                    leftPadding = a.getDimensionPixelSize(attr, -1);
4216                    mUserPaddingLeftInitial = leftPadding;
4217                    leftPaddingDefined = true;
4218                    break;
4219                case com.android.internal.R.styleable.View_paddingTop:
4220                    topPadding = a.getDimensionPixelSize(attr, -1);
4221                    break;
4222                case com.android.internal.R.styleable.View_paddingRight:
4223                    rightPadding = a.getDimensionPixelSize(attr, -1);
4224                    mUserPaddingRightInitial = rightPadding;
4225                    rightPaddingDefined = true;
4226                    break;
4227                case com.android.internal.R.styleable.View_paddingBottom:
4228                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4229                    break;
4230                case com.android.internal.R.styleable.View_paddingStart:
4231                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4232                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4233                    break;
4234                case com.android.internal.R.styleable.View_paddingEnd:
4235                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4236                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4237                    break;
4238                case com.android.internal.R.styleable.View_scrollX:
4239                    x = a.getDimensionPixelOffset(attr, 0);
4240                    break;
4241                case com.android.internal.R.styleable.View_scrollY:
4242                    y = a.getDimensionPixelOffset(attr, 0);
4243                    break;
4244                case com.android.internal.R.styleable.View_alpha:
4245                    setAlpha(a.getFloat(attr, 1f));
4246                    break;
4247                case com.android.internal.R.styleable.View_transformPivotX:
4248                    setPivotX(a.getDimension(attr, 0));
4249                    break;
4250                case com.android.internal.R.styleable.View_transformPivotY:
4251                    setPivotY(a.getDimension(attr, 0));
4252                    break;
4253                case com.android.internal.R.styleable.View_translationX:
4254                    tx = a.getDimension(attr, 0);
4255                    transformSet = true;
4256                    break;
4257                case com.android.internal.R.styleable.View_translationY:
4258                    ty = a.getDimension(attr, 0);
4259                    transformSet = true;
4260                    break;
4261                case com.android.internal.R.styleable.View_translationZ:
4262                    tz = a.getDimension(attr, 0);
4263                    transformSet = true;
4264                    break;
4265                case com.android.internal.R.styleable.View_elevation:
4266                    elevation = a.getDimension(attr, 0);
4267                    transformSet = true;
4268                    break;
4269                case com.android.internal.R.styleable.View_rotation:
4270                    rotation = a.getFloat(attr, 0);
4271                    transformSet = true;
4272                    break;
4273                case com.android.internal.R.styleable.View_rotationX:
4274                    rotationX = a.getFloat(attr, 0);
4275                    transformSet = true;
4276                    break;
4277                case com.android.internal.R.styleable.View_rotationY:
4278                    rotationY = a.getFloat(attr, 0);
4279                    transformSet = true;
4280                    break;
4281                case com.android.internal.R.styleable.View_scaleX:
4282                    sx = a.getFloat(attr, 1f);
4283                    transformSet = true;
4284                    break;
4285                case com.android.internal.R.styleable.View_scaleY:
4286                    sy = a.getFloat(attr, 1f);
4287                    transformSet = true;
4288                    break;
4289                case com.android.internal.R.styleable.View_id:
4290                    mID = a.getResourceId(attr, NO_ID);
4291                    break;
4292                case com.android.internal.R.styleable.View_tag:
4293                    mTag = a.getText(attr);
4294                    break;
4295                case com.android.internal.R.styleable.View_fitsSystemWindows:
4296                    if (a.getBoolean(attr, false)) {
4297                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4298                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4299                    }
4300                    break;
4301                case com.android.internal.R.styleable.View_focusable:
4302                    if (a.getBoolean(attr, false)) {
4303                        viewFlagValues |= FOCUSABLE;
4304                        viewFlagMasks |= FOCUSABLE_MASK;
4305                    }
4306                    break;
4307                case com.android.internal.R.styleable.View_focusableInTouchMode:
4308                    if (a.getBoolean(attr, false)) {
4309                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4310                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4311                    }
4312                    break;
4313                case com.android.internal.R.styleable.View_clickable:
4314                    if (a.getBoolean(attr, false)) {
4315                        viewFlagValues |= CLICKABLE;
4316                        viewFlagMasks |= CLICKABLE;
4317                    }
4318                    break;
4319                case com.android.internal.R.styleable.View_longClickable:
4320                    if (a.getBoolean(attr, false)) {
4321                        viewFlagValues |= LONG_CLICKABLE;
4322                        viewFlagMasks |= LONG_CLICKABLE;
4323                    }
4324                    break;
4325                case com.android.internal.R.styleable.View_contextClickable:
4326                    if (a.getBoolean(attr, false)) {
4327                        viewFlagValues |= CONTEXT_CLICKABLE;
4328                        viewFlagMasks |= CONTEXT_CLICKABLE;
4329                    }
4330                    break;
4331                case com.android.internal.R.styleable.View_saveEnabled:
4332                    if (!a.getBoolean(attr, true)) {
4333                        viewFlagValues |= SAVE_DISABLED;
4334                        viewFlagMasks |= SAVE_DISABLED_MASK;
4335                    }
4336                    break;
4337                case com.android.internal.R.styleable.View_duplicateParentState:
4338                    if (a.getBoolean(attr, false)) {
4339                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4340                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4341                    }
4342                    break;
4343                case com.android.internal.R.styleable.View_visibility:
4344                    final int visibility = a.getInt(attr, 0);
4345                    if (visibility != 0) {
4346                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4347                        viewFlagMasks |= VISIBILITY_MASK;
4348                    }
4349                    break;
4350                case com.android.internal.R.styleable.View_layoutDirection:
4351                    // Clear any layout direction flags (included resolved bits) already set
4352                    mPrivateFlags2 &=
4353                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4354                    // Set the layout direction flags depending on the value of the attribute
4355                    final int layoutDirection = a.getInt(attr, -1);
4356                    final int value = (layoutDirection != -1) ?
4357                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4358                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4359                    break;
4360                case com.android.internal.R.styleable.View_drawingCacheQuality:
4361                    final int cacheQuality = a.getInt(attr, 0);
4362                    if (cacheQuality != 0) {
4363                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4364                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4365                    }
4366                    break;
4367                case com.android.internal.R.styleable.View_contentDescription:
4368                    setContentDescription(a.getString(attr));
4369                    break;
4370                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4371                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4372                    break;
4373                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4374                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4375                    break;
4376                case com.android.internal.R.styleable.View_labelFor:
4377                    setLabelFor(a.getResourceId(attr, NO_ID));
4378                    break;
4379                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4380                    if (!a.getBoolean(attr, true)) {
4381                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4382                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4383                    }
4384                    break;
4385                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4386                    if (!a.getBoolean(attr, true)) {
4387                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4388                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4389                    }
4390                    break;
4391                case R.styleable.View_scrollbars:
4392                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4393                    if (scrollbars != SCROLLBARS_NONE) {
4394                        viewFlagValues |= scrollbars;
4395                        viewFlagMasks |= SCROLLBARS_MASK;
4396                        initializeScrollbars = true;
4397                    }
4398                    break;
4399                //noinspection deprecation
4400                case R.styleable.View_fadingEdge:
4401                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4402                        // Ignore the attribute starting with ICS
4403                        break;
4404                    }
4405                    // With builds < ICS, fall through and apply fading edges
4406                case R.styleable.View_requiresFadingEdge:
4407                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4408                    if (fadingEdge != FADING_EDGE_NONE) {
4409                        viewFlagValues |= fadingEdge;
4410                        viewFlagMasks |= FADING_EDGE_MASK;
4411                        initializeFadingEdgeInternal(a);
4412                    }
4413                    break;
4414                case R.styleable.View_scrollbarStyle:
4415                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4416                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4417                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4418                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4419                    }
4420                    break;
4421                case R.styleable.View_isScrollContainer:
4422                    setScrollContainer = true;
4423                    if (a.getBoolean(attr, false)) {
4424                        setScrollContainer(true);
4425                    }
4426                    break;
4427                case com.android.internal.R.styleable.View_keepScreenOn:
4428                    if (a.getBoolean(attr, false)) {
4429                        viewFlagValues |= KEEP_SCREEN_ON;
4430                        viewFlagMasks |= KEEP_SCREEN_ON;
4431                    }
4432                    break;
4433                case R.styleable.View_filterTouchesWhenObscured:
4434                    if (a.getBoolean(attr, false)) {
4435                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4436                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4437                    }
4438                    break;
4439                case R.styleable.View_nextFocusLeft:
4440                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4441                    break;
4442                case R.styleable.View_nextFocusRight:
4443                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4444                    break;
4445                case R.styleable.View_nextFocusUp:
4446                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4447                    break;
4448                case R.styleable.View_nextFocusDown:
4449                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4450                    break;
4451                case R.styleable.View_nextFocusForward:
4452                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4453                    break;
4454                case R.styleable.View_minWidth:
4455                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4456                    break;
4457                case R.styleable.View_minHeight:
4458                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4459                    break;
4460                case R.styleable.View_onClick:
4461                    if (context.isRestricted()) {
4462                        throw new IllegalStateException("The android:onClick attribute cannot "
4463                                + "be used within a restricted context");
4464                    }
4465
4466                    final String handlerName = a.getString(attr);
4467                    if (handlerName != null) {
4468                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4469                    }
4470                    break;
4471                case R.styleable.View_overScrollMode:
4472                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4473                    break;
4474                case R.styleable.View_verticalScrollbarPosition:
4475                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4476                    break;
4477                case R.styleable.View_layerType:
4478                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4479                    break;
4480                case R.styleable.View_textDirection:
4481                    // Clear any text direction flag already set
4482                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4483                    // Set the text direction flags depending on the value of the attribute
4484                    final int textDirection = a.getInt(attr, -1);
4485                    if (textDirection != -1) {
4486                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4487                    }
4488                    break;
4489                case R.styleable.View_textAlignment:
4490                    // Clear any text alignment flag already set
4491                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4492                    // Set the text alignment flag depending on the value of the attribute
4493                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4494                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4495                    break;
4496                case R.styleable.View_importantForAccessibility:
4497                    setImportantForAccessibility(a.getInt(attr,
4498                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4499                    break;
4500                case R.styleable.View_accessibilityLiveRegion:
4501                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4502                    break;
4503                case R.styleable.View_transitionName:
4504                    setTransitionName(a.getString(attr));
4505                    break;
4506                case R.styleable.View_nestedScrollingEnabled:
4507                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4508                    break;
4509                case R.styleable.View_stateListAnimator:
4510                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4511                            a.getResourceId(attr, 0)));
4512                    break;
4513                case R.styleable.View_backgroundTint:
4514                    // This will get applied later during setBackground().
4515                    if (mBackgroundTint == null) {
4516                        mBackgroundTint = new TintInfo();
4517                    }
4518                    mBackgroundTint.mTintList = a.getColorStateList(
4519                            R.styleable.View_backgroundTint);
4520                    mBackgroundTint.mHasTintList = true;
4521                    break;
4522                case R.styleable.View_backgroundTintMode:
4523                    // This will get applied later during setBackground().
4524                    if (mBackgroundTint == null) {
4525                        mBackgroundTint = new TintInfo();
4526                    }
4527                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4528                            R.styleable.View_backgroundTintMode, -1), null);
4529                    mBackgroundTint.mHasTintMode = true;
4530                    break;
4531                case R.styleable.View_outlineProvider:
4532                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4533                            PROVIDER_BACKGROUND));
4534                    break;
4535                case R.styleable.View_foreground:
4536                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4537                        setForeground(a.getDrawable(attr));
4538                    }
4539                    break;
4540                case R.styleable.View_foregroundGravity:
4541                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4542                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4543                    }
4544                    break;
4545                case R.styleable.View_foregroundTintMode:
4546                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4547                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4548                    }
4549                    break;
4550                case R.styleable.View_foregroundTint:
4551                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4552                        setForegroundTintList(a.getColorStateList(attr));
4553                    }
4554                    break;
4555                case R.styleable.View_foregroundInsidePadding:
4556                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4557                        if (mForegroundInfo == null) {
4558                            mForegroundInfo = new ForegroundInfo();
4559                        }
4560                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4561                                mForegroundInfo.mInsidePadding);
4562                    }
4563                    break;
4564                case R.styleable.View_scrollIndicators:
4565                    final int scrollIndicators =
4566                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4567                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4568                    if (scrollIndicators != 0) {
4569                        mPrivateFlags3 |= scrollIndicators;
4570                        initializeScrollIndicators = true;
4571                    }
4572                    break;
4573                case R.styleable.View_pointerIcon:
4574                    final int resourceId = a.getResourceId(attr, 0);
4575                    if (resourceId != 0) {
4576                        setPointerIcon(PointerIcon.load(
4577                                context.getResources(), resourceId));
4578                    } else {
4579                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4580                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4581                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
4582                        }
4583                    }
4584                    break;
4585                case R.styleable.View_forceHasOverlappingRendering:
4586                    if (a.peekValue(attr) != null) {
4587                        forceHasOverlappingRendering(a.getBoolean(attr, true));
4588                    }
4589                    break;
4590
4591            }
4592        }
4593
4594        setOverScrollMode(overScrollMode);
4595
4596        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4597        // the resolved layout direction). Those cached values will be used later during padding
4598        // resolution.
4599        mUserPaddingStart = startPadding;
4600        mUserPaddingEnd = endPadding;
4601
4602        if (background != null) {
4603            setBackground(background);
4604        }
4605
4606        // setBackground above will record that padding is currently provided by the background.
4607        // If we have padding specified via xml, record that here instead and use it.
4608        mLeftPaddingDefined = leftPaddingDefined;
4609        mRightPaddingDefined = rightPaddingDefined;
4610
4611        if (padding >= 0) {
4612            leftPadding = padding;
4613            topPadding = padding;
4614            rightPadding = padding;
4615            bottomPadding = padding;
4616            mUserPaddingLeftInitial = padding;
4617            mUserPaddingRightInitial = padding;
4618        }
4619
4620        if (isRtlCompatibilityMode()) {
4621            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4622            // left / right padding are used if defined (meaning here nothing to do). If they are not
4623            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4624            // start / end and resolve them as left / right (layout direction is not taken into account).
4625            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4626            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4627            // defined.
4628            if (!mLeftPaddingDefined && startPaddingDefined) {
4629                leftPadding = startPadding;
4630            }
4631            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4632            if (!mRightPaddingDefined && endPaddingDefined) {
4633                rightPadding = endPadding;
4634            }
4635            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4636        } else {
4637            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4638            // values defined. Otherwise, left /right values are used.
4639            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4640            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4641            // defined.
4642            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4643
4644            if (mLeftPaddingDefined && !hasRelativePadding) {
4645                mUserPaddingLeftInitial = leftPadding;
4646            }
4647            if (mRightPaddingDefined && !hasRelativePadding) {
4648                mUserPaddingRightInitial = rightPadding;
4649            }
4650        }
4651
4652        internalSetPadding(
4653                mUserPaddingLeftInitial,
4654                topPadding >= 0 ? topPadding : mPaddingTop,
4655                mUserPaddingRightInitial,
4656                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4657
4658        if (viewFlagMasks != 0) {
4659            setFlags(viewFlagValues, viewFlagMasks);
4660        }
4661
4662        if (initializeScrollbars) {
4663            initializeScrollbarsInternal(a);
4664        }
4665
4666        if (initializeScrollIndicators) {
4667            initializeScrollIndicatorsInternal();
4668        }
4669
4670        a.recycle();
4671
4672        // Needs to be called after mViewFlags is set
4673        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4674            recomputePadding();
4675        }
4676
4677        if (x != 0 || y != 0) {
4678            scrollTo(x, y);
4679        }
4680
4681        if (transformSet) {
4682            setTranslationX(tx);
4683            setTranslationY(ty);
4684            setTranslationZ(tz);
4685            setElevation(elevation);
4686            setRotation(rotation);
4687            setRotationX(rotationX);
4688            setRotationY(rotationY);
4689            setScaleX(sx);
4690            setScaleY(sy);
4691        }
4692
4693        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4694            setScrollContainer(true);
4695        }
4696
4697        computeOpaqueFlags();
4698    }
4699
4700    /**
4701     * An implementation of OnClickListener that attempts to lazily load a
4702     * named click handling method from a parent or ancestor context.
4703     */
4704    private static class DeclaredOnClickListener implements OnClickListener {
4705        private final View mHostView;
4706        private final String mMethodName;
4707
4708        private Method mResolvedMethod;
4709        private Context mResolvedContext;
4710
4711        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4712            mHostView = hostView;
4713            mMethodName = methodName;
4714        }
4715
4716        @Override
4717        public void onClick(@NonNull View v) {
4718            if (mResolvedMethod == null) {
4719                resolveMethod(mHostView.getContext(), mMethodName);
4720            }
4721
4722            try {
4723                mResolvedMethod.invoke(mResolvedContext, v);
4724            } catch (IllegalAccessException e) {
4725                throw new IllegalStateException(
4726                        "Could not execute non-public method for android:onClick", e);
4727            } catch (InvocationTargetException e) {
4728                throw new IllegalStateException(
4729                        "Could not execute method for android:onClick", e);
4730            }
4731        }
4732
4733        @NonNull
4734        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4735            while (context != null) {
4736                try {
4737                    if (!context.isRestricted()) {
4738                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4739                        if (method != null) {
4740                            mResolvedMethod = method;
4741                            mResolvedContext = context;
4742                            return;
4743                        }
4744                    }
4745                } catch (NoSuchMethodException e) {
4746                    // Failed to find method, keep searching up the hierarchy.
4747                }
4748
4749                if (context instanceof ContextWrapper) {
4750                    context = ((ContextWrapper) context).getBaseContext();
4751                } else {
4752                    // Can't search up the hierarchy, null out and fail.
4753                    context = null;
4754                }
4755            }
4756
4757            final int id = mHostView.getId();
4758            final String idText = id == NO_ID ? "" : " with id '"
4759                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4760            throw new IllegalStateException("Could not find method " + mMethodName
4761                    + "(View) in a parent or ancestor Context for android:onClick "
4762                    + "attribute defined on view " + mHostView.getClass() + idText);
4763        }
4764    }
4765
4766    /**
4767     * Non-public constructor for use in testing
4768     */
4769    View() {
4770        mResources = null;
4771        mRenderNode = RenderNode.create(getClass().getName(), this);
4772    }
4773
4774    private static SparseArray<String> getAttributeMap() {
4775        if (mAttributeMap == null) {
4776            mAttributeMap = new SparseArray<>();
4777        }
4778        return mAttributeMap;
4779    }
4780
4781    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4782        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4783        final int indexCount = t.getIndexCount();
4784        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4785
4786        int i = 0;
4787
4788        // Store raw XML attributes.
4789        for (int j = 0; j < attrsCount; ++j) {
4790            attributes[i] = attrs.getAttributeName(j);
4791            attributes[i + 1] = attrs.getAttributeValue(j);
4792            i += 2;
4793        }
4794
4795        // Store resolved styleable attributes.
4796        final Resources res = t.getResources();
4797        final SparseArray<String> attributeMap = getAttributeMap();
4798        for (int j = 0; j < indexCount; ++j) {
4799            final int index = t.getIndex(j);
4800            if (!t.hasValueOrEmpty(index)) {
4801                // Value is undefined. Skip it.
4802                continue;
4803            }
4804
4805            final int resourceId = t.getResourceId(index, 0);
4806            if (resourceId == 0) {
4807                // Value is not a reference. Skip it.
4808                continue;
4809            }
4810
4811            String resourceName = attributeMap.get(resourceId);
4812            if (resourceName == null) {
4813                try {
4814                    resourceName = res.getResourceName(resourceId);
4815                } catch (Resources.NotFoundException e) {
4816                    resourceName = "0x" + Integer.toHexString(resourceId);
4817                }
4818                attributeMap.put(resourceId, resourceName);
4819            }
4820
4821            attributes[i] = resourceName;
4822            attributes[i + 1] = t.getString(index);
4823            i += 2;
4824        }
4825
4826        // Trim to fit contents.
4827        final String[] trimmed = new String[i];
4828        System.arraycopy(attributes, 0, trimmed, 0, i);
4829        mAttributes = trimmed;
4830    }
4831
4832    public String toString() {
4833        StringBuilder out = new StringBuilder(128);
4834        out.append(getClass().getName());
4835        out.append('{');
4836        out.append(Integer.toHexString(System.identityHashCode(this)));
4837        out.append(' ');
4838        switch (mViewFlags&VISIBILITY_MASK) {
4839            case VISIBLE: out.append('V'); break;
4840            case INVISIBLE: out.append('I'); break;
4841            case GONE: out.append('G'); break;
4842            default: out.append('.'); break;
4843        }
4844        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4845        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4846        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4847        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4848        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4849        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4850        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4851        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4852        out.append(' ');
4853        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4854        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4855        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4856        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4857            out.append('p');
4858        } else {
4859            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4860        }
4861        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4862        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4863        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4864        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4865        out.append(' ');
4866        out.append(mLeft);
4867        out.append(',');
4868        out.append(mTop);
4869        out.append('-');
4870        out.append(mRight);
4871        out.append(',');
4872        out.append(mBottom);
4873        final int id = getId();
4874        if (id != NO_ID) {
4875            out.append(" #");
4876            out.append(Integer.toHexString(id));
4877            final Resources r = mResources;
4878            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4879                try {
4880                    String pkgname;
4881                    switch (id&0xff000000) {
4882                        case 0x7f000000:
4883                            pkgname="app";
4884                            break;
4885                        case 0x01000000:
4886                            pkgname="android";
4887                            break;
4888                        default:
4889                            pkgname = r.getResourcePackageName(id);
4890                            break;
4891                    }
4892                    String typename = r.getResourceTypeName(id);
4893                    String entryname = r.getResourceEntryName(id);
4894                    out.append(" ");
4895                    out.append(pkgname);
4896                    out.append(":");
4897                    out.append(typename);
4898                    out.append("/");
4899                    out.append(entryname);
4900                } catch (Resources.NotFoundException e) {
4901                }
4902            }
4903        }
4904        out.append("}");
4905        return out.toString();
4906    }
4907
4908    /**
4909     * <p>
4910     * Initializes the fading edges from a given set of styled attributes. This
4911     * method should be called by subclasses that need fading edges and when an
4912     * instance of these subclasses is created programmatically rather than
4913     * being inflated from XML. This method is automatically called when the XML
4914     * is inflated.
4915     * </p>
4916     *
4917     * @param a the styled attributes set to initialize the fading edges from
4918     *
4919     * @removed
4920     */
4921    protected void initializeFadingEdge(TypedArray a) {
4922        // This method probably shouldn't have been included in the SDK to begin with.
4923        // It relies on 'a' having been initialized using an attribute filter array that is
4924        // not publicly available to the SDK. The old method has been renamed
4925        // to initializeFadingEdgeInternal and hidden for framework use only;
4926        // this one initializes using defaults to make it safe to call for apps.
4927
4928        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4929
4930        initializeFadingEdgeInternal(arr);
4931
4932        arr.recycle();
4933    }
4934
4935    /**
4936     * <p>
4937     * Initializes the fading edges from a given set of styled attributes. This
4938     * method should be called by subclasses that need fading edges and when an
4939     * instance of these subclasses is created programmatically rather than
4940     * being inflated from XML. This method is automatically called when the XML
4941     * is inflated.
4942     * </p>
4943     *
4944     * @param a the styled attributes set to initialize the fading edges from
4945     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4946     */
4947    protected void initializeFadingEdgeInternal(TypedArray a) {
4948        initScrollCache();
4949
4950        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4951                R.styleable.View_fadingEdgeLength,
4952                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4953    }
4954
4955    /**
4956     * Returns the size of the vertical faded edges used to indicate that more
4957     * content in this view is visible.
4958     *
4959     * @return The size in pixels of the vertical faded edge or 0 if vertical
4960     *         faded edges are not enabled for this view.
4961     * @attr ref android.R.styleable#View_fadingEdgeLength
4962     */
4963    public int getVerticalFadingEdgeLength() {
4964        if (isVerticalFadingEdgeEnabled()) {
4965            ScrollabilityCache cache = mScrollCache;
4966            if (cache != null) {
4967                return cache.fadingEdgeLength;
4968            }
4969        }
4970        return 0;
4971    }
4972
4973    /**
4974     * Set the size of the faded edge used to indicate that more content in this
4975     * view is available.  Will not change whether the fading edge is enabled; use
4976     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4977     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4978     * for the vertical or horizontal fading edges.
4979     *
4980     * @param length The size in pixels of the faded edge used to indicate that more
4981     *        content in this view is visible.
4982     */
4983    public void setFadingEdgeLength(int length) {
4984        initScrollCache();
4985        mScrollCache.fadingEdgeLength = length;
4986    }
4987
4988    /**
4989     * Returns the size of the horizontal faded edges used to indicate that more
4990     * content in this view is visible.
4991     *
4992     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4993     *         faded edges are not enabled for this view.
4994     * @attr ref android.R.styleable#View_fadingEdgeLength
4995     */
4996    public int getHorizontalFadingEdgeLength() {
4997        if (isHorizontalFadingEdgeEnabled()) {
4998            ScrollabilityCache cache = mScrollCache;
4999            if (cache != null) {
5000                return cache.fadingEdgeLength;
5001            }
5002        }
5003        return 0;
5004    }
5005
5006    /**
5007     * Returns the width of the vertical scrollbar.
5008     *
5009     * @return The width in pixels of the vertical scrollbar or 0 if there
5010     *         is no vertical scrollbar.
5011     */
5012    public int getVerticalScrollbarWidth() {
5013        ScrollabilityCache cache = mScrollCache;
5014        if (cache != null) {
5015            ScrollBarDrawable scrollBar = cache.scrollBar;
5016            if (scrollBar != null) {
5017                int size = scrollBar.getSize(true);
5018                if (size <= 0) {
5019                    size = cache.scrollBarSize;
5020                }
5021                return size;
5022            }
5023            return 0;
5024        }
5025        return 0;
5026    }
5027
5028    /**
5029     * Returns the height of the horizontal scrollbar.
5030     *
5031     * @return The height in pixels of the horizontal scrollbar or 0 if
5032     *         there is no horizontal scrollbar.
5033     */
5034    protected int getHorizontalScrollbarHeight() {
5035        ScrollabilityCache cache = mScrollCache;
5036        if (cache != null) {
5037            ScrollBarDrawable scrollBar = cache.scrollBar;
5038            if (scrollBar != null) {
5039                int size = scrollBar.getSize(false);
5040                if (size <= 0) {
5041                    size = cache.scrollBarSize;
5042                }
5043                return size;
5044            }
5045            return 0;
5046        }
5047        return 0;
5048    }
5049
5050    /**
5051     * <p>
5052     * Initializes the scrollbars from a given set of styled attributes. This
5053     * method should be called by subclasses that need scrollbars and when an
5054     * instance of these subclasses is created programmatically rather than
5055     * being inflated from XML. This method is automatically called when the XML
5056     * is inflated.
5057     * </p>
5058     *
5059     * @param a the styled attributes set to initialize the scrollbars from
5060     *
5061     * @removed
5062     */
5063    protected void initializeScrollbars(TypedArray a) {
5064        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5065        // using the View filter array which is not available to the SDK. As such, internal
5066        // framework usage now uses initializeScrollbarsInternal and we grab a default
5067        // TypedArray with the right filter instead here.
5068        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5069
5070        initializeScrollbarsInternal(arr);
5071
5072        // We ignored the method parameter. Recycle the one we actually did use.
5073        arr.recycle();
5074    }
5075
5076    /**
5077     * <p>
5078     * Initializes the scrollbars from a given set of styled attributes. This
5079     * method should be called by subclasses that need scrollbars and when an
5080     * instance of these subclasses is created programmatically rather than
5081     * being inflated from XML. This method is automatically called when the XML
5082     * is inflated.
5083     * </p>
5084     *
5085     * @param a the styled attributes set to initialize the scrollbars from
5086     * @hide
5087     */
5088    protected void initializeScrollbarsInternal(TypedArray a) {
5089        initScrollCache();
5090
5091        final ScrollabilityCache scrollabilityCache = mScrollCache;
5092
5093        if (scrollabilityCache.scrollBar == null) {
5094            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5095            scrollabilityCache.scrollBar.setState(getDrawableState());
5096            scrollabilityCache.scrollBar.setCallback(this);
5097        }
5098
5099        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5100
5101        if (!fadeScrollbars) {
5102            scrollabilityCache.state = ScrollabilityCache.ON;
5103        }
5104        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5105
5106
5107        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5108                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5109                        .getScrollBarFadeDuration());
5110        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5111                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5112                ViewConfiguration.getScrollDefaultDelay());
5113
5114
5115        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5116                com.android.internal.R.styleable.View_scrollbarSize,
5117                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5118
5119        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5120        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5121
5122        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5123        if (thumb != null) {
5124            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5125        }
5126
5127        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5128                false);
5129        if (alwaysDraw) {
5130            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5131        }
5132
5133        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5134        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5135
5136        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5137        if (thumb != null) {
5138            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5139        }
5140
5141        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5142                false);
5143        if (alwaysDraw) {
5144            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5145        }
5146
5147        // Apply layout direction to the new Drawables if needed
5148        final int layoutDirection = getLayoutDirection();
5149        if (track != null) {
5150            track.setLayoutDirection(layoutDirection);
5151        }
5152        if (thumb != null) {
5153            thumb.setLayoutDirection(layoutDirection);
5154        }
5155
5156        // Re-apply user/background padding so that scrollbar(s) get added
5157        resolvePadding();
5158    }
5159
5160    private void initializeScrollIndicatorsInternal() {
5161        // Some day maybe we'll break this into top/left/start/etc. and let the
5162        // client control it. Until then, you can have any scroll indicator you
5163        // want as long as it's a 1dp foreground-colored rectangle.
5164        if (mScrollIndicatorDrawable == null) {
5165            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5166        }
5167    }
5168
5169    /**
5170     * <p>
5171     * Initalizes the scrollability cache if necessary.
5172     * </p>
5173     */
5174    private void initScrollCache() {
5175        if (mScrollCache == null) {
5176            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5177        }
5178    }
5179
5180    private ScrollabilityCache getScrollCache() {
5181        initScrollCache();
5182        return mScrollCache;
5183    }
5184
5185    /**
5186     * Set the position of the vertical scroll bar. Should be one of
5187     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5188     * {@link #SCROLLBAR_POSITION_RIGHT}.
5189     *
5190     * @param position Where the vertical scroll bar should be positioned.
5191     */
5192    public void setVerticalScrollbarPosition(int position) {
5193        if (mVerticalScrollbarPosition != position) {
5194            mVerticalScrollbarPosition = position;
5195            computeOpaqueFlags();
5196            resolvePadding();
5197        }
5198    }
5199
5200    /**
5201     * @return The position where the vertical scroll bar will show, if applicable.
5202     * @see #setVerticalScrollbarPosition(int)
5203     */
5204    public int getVerticalScrollbarPosition() {
5205        return mVerticalScrollbarPosition;
5206    }
5207
5208    boolean isOnScrollbar(float x, float y) {
5209        if (mScrollCache == null) {
5210            return false;
5211        }
5212        x += getScrollX();
5213        y += getScrollY();
5214        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5215            final Rect bounds = mScrollCache.mScrollBarBounds;
5216            getVerticalScrollBarBounds(bounds);
5217            if (bounds.contains((int)x, (int)y)) {
5218                return true;
5219            }
5220        }
5221        if (isHorizontalScrollBarEnabled()) {
5222            final Rect bounds = mScrollCache.mScrollBarBounds;
5223            getHorizontalScrollBarBounds(bounds);
5224            if (bounds.contains((int)x, (int)y)) {
5225                return true;
5226            }
5227        }
5228        return false;
5229    }
5230
5231    boolean isOnScrollbarThumb(float x, float y) {
5232        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5233    }
5234
5235    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5236        if (mScrollCache == null) {
5237            return false;
5238        }
5239        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5240            x += getScrollX();
5241            y += getScrollY();
5242            final Rect bounds = mScrollCache.mScrollBarBounds;
5243            getVerticalScrollBarBounds(bounds);
5244            final int range = computeVerticalScrollRange();
5245            final int offset = computeVerticalScrollOffset();
5246            final int extent = computeVerticalScrollExtent();
5247            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5248                    extent, range);
5249            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5250                    extent, range, offset);
5251            final int thumbTop = bounds.top + thumbOffset;
5252            if (x >= bounds.left && x <= bounds.right && y >= thumbTop
5253                    && y <= thumbTop + thumbLength) {
5254                return true;
5255            }
5256        }
5257        return false;
5258    }
5259
5260    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5261        if (mScrollCache == null) {
5262            return false;
5263        }
5264        if (isHorizontalScrollBarEnabled()) {
5265            x += getScrollX();
5266            y += getScrollY();
5267            final Rect bounds = mScrollCache.mScrollBarBounds;
5268            getHorizontalScrollBarBounds(bounds);
5269            final int range = computeHorizontalScrollRange();
5270            final int offset = computeHorizontalScrollOffset();
5271            final int extent = computeHorizontalScrollExtent();
5272            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5273                    extent, range);
5274            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5275                    extent, range, offset);
5276            final int thumbLeft = bounds.left + thumbOffset;
5277            if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
5278                    && y <= bounds.bottom) {
5279                return true;
5280            }
5281        }
5282        return false;
5283    }
5284
5285    boolean isDraggingScrollBar() {
5286        return mScrollCache != null
5287                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5288    }
5289
5290    /**
5291     * Sets the state of all scroll indicators.
5292     * <p>
5293     * See {@link #setScrollIndicators(int, int)} for usage information.
5294     *
5295     * @param indicators a bitmask of indicators that should be enabled, or
5296     *                   {@code 0} to disable all indicators
5297     * @see #setScrollIndicators(int, int)
5298     * @see #getScrollIndicators()
5299     * @attr ref android.R.styleable#View_scrollIndicators
5300     */
5301    public void setScrollIndicators(@ScrollIndicators int indicators) {
5302        setScrollIndicators(indicators,
5303                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5304    }
5305
5306    /**
5307     * Sets the state of the scroll indicators specified by the mask. To change
5308     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5309     * <p>
5310     * When a scroll indicator is enabled, it will be displayed if the view
5311     * can scroll in the direction of the indicator.
5312     * <p>
5313     * Multiple indicator types may be enabled or disabled by passing the
5314     * logical OR of the desired types. If multiple types are specified, they
5315     * will all be set to the same enabled state.
5316     * <p>
5317     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5318     *
5319     * @param indicators the indicator direction, or the logical OR of multiple
5320     *             indicator directions. One or more of:
5321     *             <ul>
5322     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5323     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5324     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5325     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5326     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5327     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5328     *             </ul>
5329     * @see #setScrollIndicators(int)
5330     * @see #getScrollIndicators()
5331     * @attr ref android.R.styleable#View_scrollIndicators
5332     */
5333    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5334        // Shift and sanitize mask.
5335        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5336        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5337
5338        // Shift and mask indicators.
5339        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5340        indicators &= mask;
5341
5342        // Merge with non-masked flags.
5343        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5344
5345        if (mPrivateFlags3 != updatedFlags) {
5346            mPrivateFlags3 = updatedFlags;
5347
5348            if (indicators != 0) {
5349                initializeScrollIndicatorsInternal();
5350            }
5351            invalidate();
5352        }
5353    }
5354
5355    /**
5356     * Returns a bitmask representing the enabled scroll indicators.
5357     * <p>
5358     * For example, if the top and left scroll indicators are enabled and all
5359     * other indicators are disabled, the return value will be
5360     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5361     * <p>
5362     * To check whether the bottom scroll indicator is enabled, use the value
5363     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5364     *
5365     * @return a bitmask representing the enabled scroll indicators
5366     */
5367    @ScrollIndicators
5368    public int getScrollIndicators() {
5369        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5370                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5371    }
5372
5373    ListenerInfo getListenerInfo() {
5374        if (mListenerInfo != null) {
5375            return mListenerInfo;
5376        }
5377        mListenerInfo = new ListenerInfo();
5378        return mListenerInfo;
5379    }
5380
5381    /**
5382     * Register a callback to be invoked when the scroll X or Y positions of
5383     * this view change.
5384     * <p>
5385     * <b>Note:</b> Some views handle scrolling independently from View and may
5386     * have their own separate listeners for scroll-type events. For example,
5387     * {@link android.widget.ListView ListView} allows clients to register an
5388     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5389     * to listen for changes in list scroll position.
5390     *
5391     * @param l The listener to notify when the scroll X or Y position changes.
5392     * @see android.view.View#getScrollX()
5393     * @see android.view.View#getScrollY()
5394     */
5395    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5396        getListenerInfo().mOnScrollChangeListener = l;
5397    }
5398
5399    /**
5400     * Register a callback to be invoked when focus of this view changed.
5401     *
5402     * @param l The callback that will run.
5403     */
5404    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5405        getListenerInfo().mOnFocusChangeListener = l;
5406    }
5407
5408    /**
5409     * Add a listener that will be called when the bounds of the view change due to
5410     * layout processing.
5411     *
5412     * @param listener The listener that will be called when layout bounds change.
5413     */
5414    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5415        ListenerInfo li = getListenerInfo();
5416        if (li.mOnLayoutChangeListeners == null) {
5417            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5418        }
5419        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5420            li.mOnLayoutChangeListeners.add(listener);
5421        }
5422    }
5423
5424    /**
5425     * Remove a listener for layout changes.
5426     *
5427     * @param listener The listener for layout bounds change.
5428     */
5429    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5430        ListenerInfo li = mListenerInfo;
5431        if (li == null || li.mOnLayoutChangeListeners == null) {
5432            return;
5433        }
5434        li.mOnLayoutChangeListeners.remove(listener);
5435    }
5436
5437    /**
5438     * Add a listener for attach state changes.
5439     *
5440     * This listener will be called whenever this view is attached or detached
5441     * from a window. Remove the listener using
5442     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5443     *
5444     * @param listener Listener to attach
5445     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5446     */
5447    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5448        ListenerInfo li = getListenerInfo();
5449        if (li.mOnAttachStateChangeListeners == null) {
5450            li.mOnAttachStateChangeListeners
5451                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5452        }
5453        li.mOnAttachStateChangeListeners.add(listener);
5454    }
5455
5456    /**
5457     * Remove a listener for attach state changes. The listener will receive no further
5458     * notification of window attach/detach events.
5459     *
5460     * @param listener Listener to remove
5461     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5462     */
5463    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5464        ListenerInfo li = mListenerInfo;
5465        if (li == null || li.mOnAttachStateChangeListeners == null) {
5466            return;
5467        }
5468        li.mOnAttachStateChangeListeners.remove(listener);
5469    }
5470
5471    /**
5472     * Returns the focus-change callback registered for this view.
5473     *
5474     * @return The callback, or null if one is not registered.
5475     */
5476    public OnFocusChangeListener getOnFocusChangeListener() {
5477        ListenerInfo li = mListenerInfo;
5478        return li != null ? li.mOnFocusChangeListener : null;
5479    }
5480
5481    /**
5482     * Register a callback to be invoked when this view is clicked. If this view is not
5483     * clickable, it becomes clickable.
5484     *
5485     * @param l The callback that will run
5486     *
5487     * @see #setClickable(boolean)
5488     */
5489    public void setOnClickListener(@Nullable OnClickListener l) {
5490        if (!isClickable()) {
5491            setClickable(true);
5492        }
5493        getListenerInfo().mOnClickListener = l;
5494    }
5495
5496    /**
5497     * Return whether this view has an attached OnClickListener.  Returns
5498     * true if there is a listener, false if there is none.
5499     */
5500    public boolean hasOnClickListeners() {
5501        ListenerInfo li = mListenerInfo;
5502        return (li != null && li.mOnClickListener != null);
5503    }
5504
5505    /**
5506     * Register a callback to be invoked when this view is clicked and held. If this view is not
5507     * long clickable, it becomes long clickable.
5508     *
5509     * @param l The callback that will run
5510     *
5511     * @see #setLongClickable(boolean)
5512     */
5513    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5514        if (!isLongClickable()) {
5515            setLongClickable(true);
5516        }
5517        getListenerInfo().mOnLongClickListener = l;
5518    }
5519
5520    /**
5521     * Register a callback to be invoked when this view is context clicked. If the view is not
5522     * context clickable, it becomes context clickable.
5523     *
5524     * @param l The callback that will run
5525     * @see #setContextClickable(boolean)
5526     */
5527    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5528        if (!isContextClickable()) {
5529            setContextClickable(true);
5530        }
5531        getListenerInfo().mOnContextClickListener = l;
5532    }
5533
5534    /**
5535     * Register a callback to be invoked when the context menu for this view is
5536     * being built. If this view is not long clickable, it becomes long clickable.
5537     *
5538     * @param l The callback that will run
5539     *
5540     */
5541    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5542        if (!isLongClickable()) {
5543            setLongClickable(true);
5544        }
5545        getListenerInfo().mOnCreateContextMenuListener = l;
5546    }
5547
5548    /**
5549     * Set an observer to collect stats for each frame rendered for this view.
5550     *
5551     * @hide
5552     */
5553    public void addFrameMetricsListener(Window window,
5554            Window.OnFrameMetricsAvailableListener listener,
5555            Handler handler) {
5556        if (mAttachInfo != null) {
5557            if (mAttachInfo.mHardwareRenderer != null) {
5558                if (mFrameMetricsObservers == null) {
5559                    mFrameMetricsObservers = new ArrayList<>();
5560                }
5561
5562                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5563                        handler.getLooper(), listener);
5564                mFrameMetricsObservers.add(fmo);
5565                mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo);
5566            } else {
5567                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5568            }
5569        } else {
5570            if (mFrameMetricsObservers == null) {
5571                mFrameMetricsObservers = new ArrayList<>();
5572            }
5573
5574            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5575                    handler.getLooper(), listener);
5576            mFrameMetricsObservers.add(fmo);
5577        }
5578    }
5579
5580    /**
5581     * Remove observer configured to collect frame stats for this view.
5582     *
5583     * @hide
5584     */
5585    public void removeFrameMetricsListener(
5586            Window.OnFrameMetricsAvailableListener listener) {
5587        ThreadedRenderer renderer = getHardwareRenderer();
5588        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
5589        if (fmo == null) {
5590            throw new IllegalArgumentException(
5591                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
5592        }
5593
5594        if (mFrameMetricsObservers != null) {
5595            mFrameMetricsObservers.remove(fmo);
5596            if (renderer != null) {
5597                renderer.removeFrameMetricsObserver(fmo);
5598            }
5599        }
5600    }
5601
5602    private void registerPendingFrameMetricsObservers() {
5603        if (mFrameMetricsObservers != null) {
5604            ThreadedRenderer renderer = getHardwareRenderer();
5605            if (renderer != null) {
5606                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
5607                    renderer.addFrameMetricsObserver(fmo);
5608                }
5609            } else {
5610                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5611            }
5612        }
5613    }
5614
5615    private FrameMetricsObserver findFrameMetricsObserver(
5616            Window.OnFrameMetricsAvailableListener listener) {
5617        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
5618            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
5619            if (observer.mListener == listener) {
5620                return observer;
5621            }
5622        }
5623
5624        return null;
5625    }
5626
5627    /**
5628     * Call this view's OnClickListener, if it is defined.  Performs all normal
5629     * actions associated with clicking: reporting accessibility event, playing
5630     * a sound, etc.
5631     *
5632     * @return True there was an assigned OnClickListener that was called, false
5633     *         otherwise is returned.
5634     */
5635    public boolean performClick() {
5636        final boolean result;
5637        final ListenerInfo li = mListenerInfo;
5638        if (li != null && li.mOnClickListener != null) {
5639            playSoundEffect(SoundEffectConstants.CLICK);
5640            li.mOnClickListener.onClick(this);
5641            result = true;
5642        } else {
5643            result = false;
5644        }
5645
5646        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5647        return result;
5648    }
5649
5650    /**
5651     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5652     * this only calls the listener, and does not do any associated clicking
5653     * actions like reporting an accessibility event.
5654     *
5655     * @return True there was an assigned OnClickListener that was called, false
5656     *         otherwise is returned.
5657     */
5658    public boolean callOnClick() {
5659        ListenerInfo li = mListenerInfo;
5660        if (li != null && li.mOnClickListener != null) {
5661            li.mOnClickListener.onClick(this);
5662            return true;
5663        }
5664        return false;
5665    }
5666
5667    /**
5668     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5669     * context menu if the OnLongClickListener did not consume the event.
5670     *
5671     * @return {@code true} if one of the above receivers consumed the event,
5672     *         {@code false} otherwise
5673     */
5674    public boolean performLongClick() {
5675        return performLongClickInternal(mLongClickX, mLongClickY);
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     * anchoring it to an (x,y) coordinate.
5682     *
5683     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5684     *          to disable anchoring
5685     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5686     *          to disable anchoring
5687     * @return {@code true} if one of the above receivers consumed the event,
5688     *         {@code false} otherwise
5689     */
5690    public boolean performLongClick(float x, float y) {
5691        mLongClickX = x;
5692        mLongClickY = y;
5693        final boolean handled = performLongClick();
5694        mLongClickX = Float.NaN;
5695        mLongClickY = Float.NaN;
5696        return handled;
5697    }
5698
5699    /**
5700     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5701     * context menu if the OnLongClickListener did not consume the event,
5702     * optionally anchoring it to an (x,y) coordinate.
5703     *
5704     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5705     *          to disable anchoring
5706     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5707     *          to disable anchoring
5708     * @return {@code true} if one of the above receivers consumed the event,
5709     *         {@code false} otherwise
5710     */
5711    private boolean performLongClickInternal(float x, float y) {
5712        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5713
5714        boolean handled = false;
5715        final ListenerInfo li = mListenerInfo;
5716        if (li != null && li.mOnLongClickListener != null) {
5717            handled = li.mOnLongClickListener.onLongClick(View.this);
5718        }
5719        if (!handled) {
5720            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5721            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5722        }
5723        if (handled) {
5724            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5725        }
5726        return handled;
5727    }
5728
5729    /**
5730     * Call this view's OnContextClickListener, if it is defined.
5731     *
5732     * @param x the x coordinate of the context click
5733     * @param y the y coordinate of the context click
5734     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5735     *         otherwise.
5736     */
5737    public boolean performContextClick(float x, float y) {
5738        return performContextClick();
5739    }
5740
5741    /**
5742     * Call this view's OnContextClickListener, if it is defined.
5743     *
5744     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5745     *         otherwise.
5746     */
5747    public boolean performContextClick() {
5748        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5749
5750        boolean handled = false;
5751        ListenerInfo li = mListenerInfo;
5752        if (li != null && li.mOnContextClickListener != null) {
5753            handled = li.mOnContextClickListener.onContextClick(View.this);
5754        }
5755        if (handled) {
5756            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5757        }
5758        return handled;
5759    }
5760
5761    /**
5762     * Performs button-related actions during a touch down event.
5763     *
5764     * @param event The event.
5765     * @return True if the down was consumed.
5766     *
5767     * @hide
5768     */
5769    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5770        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5771            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5772            showContextMenu(event.getX(), event.getY());
5773            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5774            return true;
5775        }
5776        return false;
5777    }
5778
5779    /**
5780     * Shows the context menu for this view.
5781     *
5782     * @return {@code true} if the context menu was shown, {@code false}
5783     *         otherwise
5784     * @see #showContextMenu(float, float)
5785     */
5786    public boolean showContextMenu() {
5787        return getParent().showContextMenuForChild(this);
5788    }
5789
5790    /**
5791     * Shows the context menu for this view anchored to the specified
5792     * view-relative coordinate.
5793     *
5794     * @param x the X coordinate in pixels relative to the view to which the
5795     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5796     * @param y the Y coordinate in pixels relative to the view to which the
5797     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5798     * @return {@code true} if the context menu was shown, {@code false}
5799     *         otherwise
5800     */
5801    public boolean showContextMenu(float x, float y) {
5802        return getParent().showContextMenuForChild(this, x, y);
5803    }
5804
5805    /**
5806     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5807     *
5808     * @param callback Callback that will control the lifecycle of the action mode
5809     * @return The new action mode if it is started, null otherwise
5810     *
5811     * @see ActionMode
5812     * @see #startActionMode(android.view.ActionMode.Callback, int)
5813     */
5814    public ActionMode startActionMode(ActionMode.Callback callback) {
5815        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5816    }
5817
5818    /**
5819     * Start an action mode with the given type.
5820     *
5821     * @param callback Callback that will control the lifecycle of the action mode
5822     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5823     * @return The new action mode if it is started, null otherwise
5824     *
5825     * @see ActionMode
5826     */
5827    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5828        ViewParent parent = getParent();
5829        if (parent == null) return null;
5830        try {
5831            return parent.startActionModeForChild(this, callback, type);
5832        } catch (AbstractMethodError ame) {
5833            // Older implementations of custom views might not implement this.
5834            return parent.startActionModeForChild(this, callback);
5835        }
5836    }
5837
5838    /**
5839     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5840     * Context, creating a unique View identifier to retrieve the result.
5841     *
5842     * @param intent The Intent to be started.
5843     * @param requestCode The request code to use.
5844     * @hide
5845     */
5846    public void startActivityForResult(Intent intent, int requestCode) {
5847        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5848        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5849    }
5850
5851    /**
5852     * If this View corresponds to the calling who, dispatches the activity result.
5853     * @param who The identifier for the targeted View to receive the result.
5854     * @param requestCode The integer request code originally supplied to
5855     *                    startActivityForResult(), allowing you to identify who this
5856     *                    result came from.
5857     * @param resultCode The integer result code returned by the child activity
5858     *                   through its setResult().
5859     * @param data An Intent, which can return result data to the caller
5860     *               (various data can be attached to Intent "extras").
5861     * @return {@code true} if the activity result was dispatched.
5862     * @hide
5863     */
5864    public boolean dispatchActivityResult(
5865            String who, int requestCode, int resultCode, Intent data) {
5866        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5867            onActivityResult(requestCode, resultCode, data);
5868            mStartActivityRequestWho = null;
5869            return true;
5870        }
5871        return false;
5872    }
5873
5874    /**
5875     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5876     *
5877     * @param requestCode The integer request code originally supplied to
5878     *                    startActivityForResult(), allowing you to identify who this
5879     *                    result came from.
5880     * @param resultCode The integer result code returned by the child activity
5881     *                   through its setResult().
5882     * @param data An Intent, which can return result data to the caller
5883     *               (various data can be attached to Intent "extras").
5884     * @hide
5885     */
5886    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5887        // Do nothing.
5888    }
5889
5890    /**
5891     * Register a callback to be invoked when a hardware key is pressed in this view.
5892     * Key presses in software input methods will generally not trigger the methods of
5893     * this listener.
5894     * @param l the key listener to attach to this view
5895     */
5896    public void setOnKeyListener(OnKeyListener l) {
5897        getListenerInfo().mOnKeyListener = l;
5898    }
5899
5900    /**
5901     * Register a callback to be invoked when a touch event is sent to this view.
5902     * @param l the touch listener to attach to this view
5903     */
5904    public void setOnTouchListener(OnTouchListener l) {
5905        getListenerInfo().mOnTouchListener = l;
5906    }
5907
5908    /**
5909     * Register a callback to be invoked when a generic motion event is sent to this view.
5910     * @param l the generic motion listener to attach to this view
5911     */
5912    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5913        getListenerInfo().mOnGenericMotionListener = l;
5914    }
5915
5916    /**
5917     * Register a callback to be invoked when a hover event is sent to this view.
5918     * @param l the hover listener to attach to this view
5919     */
5920    public void setOnHoverListener(OnHoverListener l) {
5921        getListenerInfo().mOnHoverListener = l;
5922    }
5923
5924    /**
5925     * Register a drag event listener callback object for this View. The parameter is
5926     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5927     * View, the system calls the
5928     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5929     * @param l An implementation of {@link android.view.View.OnDragListener}.
5930     */
5931    public void setOnDragListener(OnDragListener l) {
5932        getListenerInfo().mOnDragListener = l;
5933    }
5934
5935    /**
5936     * Give this view focus. This will cause
5937     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5938     *
5939     * Note: this does not check whether this {@link View} should get focus, it just
5940     * gives it focus no matter what.  It should only be called internally by framework
5941     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5942     *
5943     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5944     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5945     *        focus moved when requestFocus() is called. It may not always
5946     *        apply, in which case use the default View.FOCUS_DOWN.
5947     * @param previouslyFocusedRect The rectangle of the view that had focus
5948     *        prior in this View's coordinate system.
5949     */
5950    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5951        if (DBG) {
5952            System.out.println(this + " requestFocus()");
5953        }
5954
5955        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5956            mPrivateFlags |= PFLAG_FOCUSED;
5957
5958            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5959
5960            if (mParent != null) {
5961                mParent.requestChildFocus(this, this);
5962            }
5963
5964            if (mAttachInfo != null) {
5965                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5966            }
5967
5968            onFocusChanged(true, direction, previouslyFocusedRect);
5969            refreshDrawableState();
5970        }
5971    }
5972
5973    /**
5974     * Sets this view's preference for reveal behavior when it gains focus.
5975     *
5976     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
5977     * this view would prefer to be brought fully into view when it gains focus.
5978     * For example, a text field that a user is meant to type into. Other views such
5979     * as scrolling containers may prefer to opt-out of this behavior.</p>
5980     *
5981     * <p>The default value for views is true, though subclasses may change this
5982     * based on their preferred behavior.</p>
5983     *
5984     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
5985     *
5986     * @see #getRevealOnFocusHint()
5987     */
5988    public final void setRevealOnFocusHint(boolean revealOnFocus) {
5989        if (revealOnFocus) {
5990            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
5991        } else {
5992            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
5993        }
5994    }
5995
5996    /**
5997     * Returns this view's preference for reveal behavior when it gains focus.
5998     *
5999     * <p>When this method returns true for a child view requesting focus, ancestor
6000     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6001     * should make a best effort to make the newly focused child fully visible to the user.
6002     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6003     * other properties affecting visibility to the user as part of the focus change.</p>
6004     *
6005     * @return true if this view would prefer to become fully visible when it gains focus,
6006     *         false if it would prefer not to disrupt scroll positioning
6007     *
6008     * @see #setRevealOnFocusHint(boolean)
6009     */
6010    public final boolean getRevealOnFocusHint() {
6011        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6012    }
6013
6014    /**
6015     * Populates <code>outRect</code> with the hotspot bounds. By default,
6016     * the hotspot bounds are identical to the screen bounds.
6017     *
6018     * @param outRect rect to populate with hotspot bounds
6019     * @hide Only for internal use by views and widgets.
6020     */
6021    public void getHotspotBounds(Rect outRect) {
6022        final Drawable background = getBackground();
6023        if (background != null) {
6024            background.getHotspotBounds(outRect);
6025        } else {
6026            getBoundsOnScreen(outRect);
6027        }
6028    }
6029
6030    /**
6031     * Request that a rectangle of this view be visible on the screen,
6032     * scrolling if necessary just enough.
6033     *
6034     * <p>A View should call this if it maintains some notion of which part
6035     * of its content is interesting.  For example, a text editing view
6036     * should call this when its cursor moves.
6037     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6038     * It should not be affected by which part of the View is currently visible or its scroll
6039     * position.
6040     *
6041     * @param rectangle The rectangle in the View's content coordinate space
6042     * @return Whether any parent scrolled.
6043     */
6044    public boolean requestRectangleOnScreen(Rect rectangle) {
6045        return requestRectangleOnScreen(rectangle, false);
6046    }
6047
6048    /**
6049     * Request that a rectangle of this view be visible on the screen,
6050     * scrolling if necessary just enough.
6051     *
6052     * <p>A View should call this if it maintains some notion of which part
6053     * of its content is interesting.  For example, a text editing view
6054     * should call this when its cursor moves.
6055     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6056     * It should not be affected by which part of the View is currently visible or its scroll
6057     * position.
6058     * <p>When <code>immediate</code> is set to true, scrolling will not be
6059     * animated.
6060     *
6061     * @param rectangle The rectangle in the View's content coordinate space
6062     * @param immediate True to forbid animated scrolling, false otherwise
6063     * @return Whether any parent scrolled.
6064     */
6065    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6066        if (mParent == null) {
6067            return false;
6068        }
6069
6070        View child = this;
6071
6072        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6073        position.set(rectangle);
6074
6075        ViewParent parent = mParent;
6076        boolean scrolled = false;
6077        while (parent != null) {
6078            rectangle.set((int) position.left, (int) position.top,
6079                    (int) position.right, (int) position.bottom);
6080
6081            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6082
6083            if (!(parent instanceof View)) {
6084                break;
6085            }
6086
6087            // move it from child's content coordinate space to parent's content coordinate space
6088            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6089
6090            child = (View) parent;
6091            parent = child.getParent();
6092        }
6093
6094        return scrolled;
6095    }
6096
6097    /**
6098     * Called when this view wants to give up focus. If focus is cleared
6099     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6100     * <p>
6101     * <strong>Note:</strong> When a View clears focus the framework is trying
6102     * to give focus to the first focusable View from the top. Hence, if this
6103     * View is the first from the top that can take focus, then all callbacks
6104     * related to clearing focus will be invoked after which the framework will
6105     * give focus to this view.
6106     * </p>
6107     */
6108    public void clearFocus() {
6109        if (DBG) {
6110            System.out.println(this + " clearFocus()");
6111        }
6112
6113        clearFocusInternal(null, true, true);
6114    }
6115
6116    /**
6117     * Clears focus from the view, optionally propagating the change up through
6118     * the parent hierarchy and requesting that the root view place new focus.
6119     *
6120     * @param propagate whether to propagate the change up through the parent
6121     *            hierarchy
6122     * @param refocus when propagate is true, specifies whether to request the
6123     *            root view place new focus
6124     */
6125    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6126        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6127            mPrivateFlags &= ~PFLAG_FOCUSED;
6128
6129            if (propagate && mParent != null) {
6130                mParent.clearChildFocus(this);
6131            }
6132
6133            onFocusChanged(false, 0, null);
6134            refreshDrawableState();
6135
6136            if (propagate && (!refocus || !rootViewRequestFocus())) {
6137                notifyGlobalFocusCleared(this);
6138            }
6139        }
6140    }
6141
6142    void notifyGlobalFocusCleared(View oldFocus) {
6143        if (oldFocus != null && mAttachInfo != null) {
6144            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6145        }
6146    }
6147
6148    boolean rootViewRequestFocus() {
6149        final View root = getRootView();
6150        return root != null && root.requestFocus();
6151    }
6152
6153    /**
6154     * Called internally by the view system when a new view is getting focus.
6155     * This is what clears the old focus.
6156     * <p>
6157     * <b>NOTE:</b> The parent view's focused child must be updated manually
6158     * after calling this method. Otherwise, the view hierarchy may be left in
6159     * an inconstent state.
6160     */
6161    void unFocus(View focused) {
6162        if (DBG) {
6163            System.out.println(this + " unFocus()");
6164        }
6165
6166        clearFocusInternal(focused, false, false);
6167    }
6168
6169    /**
6170     * Returns true if this view has focus itself, or is the ancestor of the
6171     * view that has focus.
6172     *
6173     * @return True if this view has or contains focus, false otherwise.
6174     */
6175    @ViewDebug.ExportedProperty(category = "focus")
6176    public boolean hasFocus() {
6177        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6178    }
6179
6180    /**
6181     * Returns true if this view is focusable or if it contains a reachable View
6182     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
6183     * is a View whose parents do not block descendants focus.
6184     *
6185     * Only {@link #VISIBLE} views are considered focusable.
6186     *
6187     * @return True if the view is focusable or if the view contains a focusable
6188     *         View, false otherwise.
6189     *
6190     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6191     * @see ViewGroup#getTouchscreenBlocksFocus()
6192     */
6193    public boolean hasFocusable() {
6194        if (!isFocusableInTouchMode()) {
6195            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6196                final ViewGroup g = (ViewGroup) p;
6197                if (g.shouldBlockFocusForTouchscreen()) {
6198                    return false;
6199                }
6200            }
6201        }
6202        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
6203    }
6204
6205    /**
6206     * Called by the view system when the focus state of this view changes.
6207     * When the focus change event is caused by directional navigation, direction
6208     * and previouslyFocusedRect provide insight into where the focus is coming from.
6209     * When overriding, be sure to call up through to the super class so that
6210     * the standard focus handling will occur.
6211     *
6212     * @param gainFocus True if the View has focus; false otherwise.
6213     * @param direction The direction focus has moved when requestFocus()
6214     *                  is called to give this view focus. Values are
6215     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6216     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6217     *                  It may not always apply, in which case use the default.
6218     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6219     *        system, of the previously focused view.  If applicable, this will be
6220     *        passed in as finer grained information about where the focus is coming
6221     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6222     */
6223    @CallSuper
6224    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6225            @Nullable Rect previouslyFocusedRect) {
6226        if (gainFocus) {
6227            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6228        } else {
6229            notifyViewAccessibilityStateChangedIfNeeded(
6230                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6231        }
6232
6233        InputMethodManager imm = InputMethodManager.peekInstance();
6234        if (!gainFocus) {
6235            if (isPressed()) {
6236                setPressed(false);
6237            }
6238            if (imm != null && mAttachInfo != null
6239                    && mAttachInfo.mHasWindowFocus) {
6240                imm.focusOut(this);
6241            }
6242            onFocusLost();
6243        } else if (imm != null && mAttachInfo != null
6244                && mAttachInfo.mHasWindowFocus) {
6245            imm.focusIn(this);
6246        }
6247
6248        invalidate(true);
6249        ListenerInfo li = mListenerInfo;
6250        if (li != null && li.mOnFocusChangeListener != null) {
6251            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6252        }
6253
6254        if (mAttachInfo != null) {
6255            mAttachInfo.mKeyDispatchState.reset(this);
6256        }
6257    }
6258
6259    /**
6260     * Sends an accessibility event of the given type. If accessibility is
6261     * not enabled this method has no effect. The default implementation calls
6262     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6263     * to populate information about the event source (this View), then calls
6264     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6265     * populate the text content of the event source including its descendants,
6266     * and last calls
6267     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6268     * on its parent to request sending of the event to interested parties.
6269     * <p>
6270     * If an {@link AccessibilityDelegate} has been specified via calling
6271     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6272     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6273     * responsible for handling this call.
6274     * </p>
6275     *
6276     * @param eventType The type of the event to send, as defined by several types from
6277     * {@link android.view.accessibility.AccessibilityEvent}, such as
6278     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6279     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6280     *
6281     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6282     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6283     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6284     * @see AccessibilityDelegate
6285     */
6286    public void sendAccessibilityEvent(int eventType) {
6287        if (mAccessibilityDelegate != null) {
6288            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6289        } else {
6290            sendAccessibilityEventInternal(eventType);
6291        }
6292    }
6293
6294    /**
6295     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6296     * {@link AccessibilityEvent} to make an announcement which is related to some
6297     * sort of a context change for which none of the events representing UI transitions
6298     * is a good fit. For example, announcing a new page in a book. If accessibility
6299     * is not enabled this method does nothing.
6300     *
6301     * @param text The announcement text.
6302     */
6303    public void announceForAccessibility(CharSequence text) {
6304        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6305            AccessibilityEvent event = AccessibilityEvent.obtain(
6306                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6307            onInitializeAccessibilityEvent(event);
6308            event.getText().add(text);
6309            event.setContentDescription(null);
6310            mParent.requestSendAccessibilityEvent(this, event);
6311        }
6312    }
6313
6314    /**
6315     * @see #sendAccessibilityEvent(int)
6316     *
6317     * Note: Called from the default {@link AccessibilityDelegate}.
6318     *
6319     * @hide
6320     */
6321    public void sendAccessibilityEventInternal(int eventType) {
6322        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6323            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6324        }
6325    }
6326
6327    /**
6328     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6329     * takes as an argument an empty {@link AccessibilityEvent} and does not
6330     * perform a check whether accessibility is enabled.
6331     * <p>
6332     * If an {@link AccessibilityDelegate} has been specified via calling
6333     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6334     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6335     * is responsible for handling this call.
6336     * </p>
6337     *
6338     * @param event The event to send.
6339     *
6340     * @see #sendAccessibilityEvent(int)
6341     */
6342    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6343        if (mAccessibilityDelegate != null) {
6344            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6345        } else {
6346            sendAccessibilityEventUncheckedInternal(event);
6347        }
6348    }
6349
6350    /**
6351     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6352     *
6353     * Note: Called from the default {@link AccessibilityDelegate}.
6354     *
6355     * @hide
6356     */
6357    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6358        if (!isShown()) {
6359            return;
6360        }
6361        onInitializeAccessibilityEvent(event);
6362        // Only a subset of accessibility events populates text content.
6363        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6364            dispatchPopulateAccessibilityEvent(event);
6365        }
6366        // In the beginning we called #isShown(), so we know that getParent() is not null.
6367        getParent().requestSendAccessibilityEvent(this, event);
6368    }
6369
6370    /**
6371     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6372     * to its children for adding their text content to the event. Note that the
6373     * event text is populated in a separate dispatch path since we add to the
6374     * event not only the text of the source but also the text of all its descendants.
6375     * A typical implementation will call
6376     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6377     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6378     * on each child. Override this method if custom population of the event text
6379     * content is required.
6380     * <p>
6381     * If an {@link AccessibilityDelegate} has been specified via calling
6382     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6383     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6384     * is responsible for handling this call.
6385     * </p>
6386     * <p>
6387     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6388     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6389     * </p>
6390     *
6391     * @param event The event.
6392     *
6393     * @return True if the event population was completed.
6394     */
6395    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6396        if (mAccessibilityDelegate != null) {
6397            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6398        } else {
6399            return dispatchPopulateAccessibilityEventInternal(event);
6400        }
6401    }
6402
6403    /**
6404     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6405     *
6406     * Note: Called from the default {@link AccessibilityDelegate}.
6407     *
6408     * @hide
6409     */
6410    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6411        onPopulateAccessibilityEvent(event);
6412        return false;
6413    }
6414
6415    /**
6416     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6417     * giving a chance to this View to populate the accessibility event with its
6418     * text content. While this method is free to modify event
6419     * attributes other than text content, doing so should normally be performed in
6420     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6421     * <p>
6422     * Example: Adding formatted date string to an accessibility event in addition
6423     *          to the text added by the super implementation:
6424     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6425     *     super.onPopulateAccessibilityEvent(event);
6426     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6427     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6428     *         mCurrentDate.getTimeInMillis(), flags);
6429     *     event.getText().add(selectedDateUtterance);
6430     * }</pre>
6431     * <p>
6432     * If an {@link AccessibilityDelegate} has been specified via calling
6433     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6434     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6435     * is responsible for handling this call.
6436     * </p>
6437     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6438     * information to the event, in case the default implementation has basic information to add.
6439     * </p>
6440     *
6441     * @param event The accessibility event which to populate.
6442     *
6443     * @see #sendAccessibilityEvent(int)
6444     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6445     */
6446    @CallSuper
6447    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6448        if (mAccessibilityDelegate != null) {
6449            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6450        } else {
6451            onPopulateAccessibilityEventInternal(event);
6452        }
6453    }
6454
6455    /**
6456     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6457     *
6458     * Note: Called from the default {@link AccessibilityDelegate}.
6459     *
6460     * @hide
6461     */
6462    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6463    }
6464
6465    /**
6466     * Initializes an {@link AccessibilityEvent} with information about
6467     * this View which is the event source. In other words, the source of
6468     * an accessibility event is the view whose state change triggered firing
6469     * the event.
6470     * <p>
6471     * Example: Setting the password property of an event in addition
6472     *          to properties set by the super implementation:
6473     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6474     *     super.onInitializeAccessibilityEvent(event);
6475     *     event.setPassword(true);
6476     * }</pre>
6477     * <p>
6478     * If an {@link AccessibilityDelegate} has been specified via calling
6479     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6480     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6481     * is responsible for handling this call.
6482     * </p>
6483     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6484     * information to the event, in case the default implementation has basic information to add.
6485     * </p>
6486     * @param event The event to initialize.
6487     *
6488     * @see #sendAccessibilityEvent(int)
6489     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6490     */
6491    @CallSuper
6492    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6493        if (mAccessibilityDelegate != null) {
6494            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6495        } else {
6496            onInitializeAccessibilityEventInternal(event);
6497        }
6498    }
6499
6500    /**
6501     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6502     *
6503     * Note: Called from the default {@link AccessibilityDelegate}.
6504     *
6505     * @hide
6506     */
6507    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6508        event.setSource(this);
6509        event.setClassName(getAccessibilityClassName());
6510        event.setPackageName(getContext().getPackageName());
6511        event.setEnabled(isEnabled());
6512        event.setContentDescription(mContentDescription);
6513
6514        switch (event.getEventType()) {
6515            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6516                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6517                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6518                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6519                event.setItemCount(focusablesTempList.size());
6520                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6521                if (mAttachInfo != null) {
6522                    focusablesTempList.clear();
6523                }
6524            } break;
6525            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6526                CharSequence text = getIterableTextForAccessibility();
6527                if (text != null && text.length() > 0) {
6528                    event.setFromIndex(getAccessibilitySelectionStart());
6529                    event.setToIndex(getAccessibilitySelectionEnd());
6530                    event.setItemCount(text.length());
6531                }
6532            } break;
6533        }
6534    }
6535
6536    /**
6537     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6538     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6539     * This method is responsible for obtaining an accessibility node info from a
6540     * pool of reusable instances and calling
6541     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6542     * initialize the former.
6543     * <p>
6544     * Note: The client is responsible for recycling the obtained instance by calling
6545     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6546     * </p>
6547     *
6548     * @return A populated {@link AccessibilityNodeInfo}.
6549     *
6550     * @see AccessibilityNodeInfo
6551     */
6552    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6553        if (mAccessibilityDelegate != null) {
6554            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6555        } else {
6556            return createAccessibilityNodeInfoInternal();
6557        }
6558    }
6559
6560    /**
6561     * @see #createAccessibilityNodeInfo()
6562     *
6563     * @hide
6564     */
6565    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6566        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6567        if (provider != null) {
6568            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6569        } else {
6570            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6571            onInitializeAccessibilityNodeInfo(info);
6572            return info;
6573        }
6574    }
6575
6576    /**
6577     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6578     * The base implementation sets:
6579     * <ul>
6580     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6581     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6582     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6583     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6584     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6585     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6586     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6587     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6588     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6589     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6590     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6591     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6592     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6593     * </ul>
6594     * <p>
6595     * Subclasses should override this method, call the super implementation,
6596     * and set additional attributes.
6597     * </p>
6598     * <p>
6599     * If an {@link AccessibilityDelegate} has been specified via calling
6600     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6601     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6602     * is responsible for handling this call.
6603     * </p>
6604     *
6605     * @param info The instance to initialize.
6606     */
6607    @CallSuper
6608    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6609        if (mAccessibilityDelegate != null) {
6610            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6611        } else {
6612            onInitializeAccessibilityNodeInfoInternal(info);
6613        }
6614    }
6615
6616    /**
6617     * Gets the location of this view in screen coordinates.
6618     *
6619     * @param outRect The output location
6620     * @hide
6621     */
6622    public void getBoundsOnScreen(Rect outRect) {
6623        getBoundsOnScreen(outRect, false);
6624    }
6625
6626    /**
6627     * Gets the location of this view in screen coordinates.
6628     *
6629     * @param outRect The output location
6630     * @param clipToParent Whether to clip child bounds to the parent ones.
6631     * @hide
6632     */
6633    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6634        if (mAttachInfo == null) {
6635            return;
6636        }
6637
6638        RectF position = mAttachInfo.mTmpTransformRect;
6639        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6640
6641        if (!hasIdentityMatrix()) {
6642            getMatrix().mapRect(position);
6643        }
6644
6645        position.offset(mLeft, mTop);
6646
6647        ViewParent parent = mParent;
6648        while (parent instanceof View) {
6649            View parentView = (View) parent;
6650
6651            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6652
6653            if (clipToParent) {
6654                position.left = Math.max(position.left, 0);
6655                position.top = Math.max(position.top, 0);
6656                position.right = Math.min(position.right, parentView.getWidth());
6657                position.bottom = Math.min(position.bottom, parentView.getHeight());
6658            }
6659
6660            if (!parentView.hasIdentityMatrix()) {
6661                parentView.getMatrix().mapRect(position);
6662            }
6663
6664            position.offset(parentView.mLeft, parentView.mTop);
6665
6666            parent = parentView.mParent;
6667        }
6668
6669        if (parent instanceof ViewRootImpl) {
6670            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6671            position.offset(0, -viewRootImpl.mCurScrollY);
6672        }
6673
6674        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6675
6676        outRect.set(Math.round(position.left), Math.round(position.top),
6677                Math.round(position.right), Math.round(position.bottom));
6678    }
6679
6680    /**
6681     * Return the class name of this object to be used for accessibility purposes.
6682     * Subclasses should only override this if they are implementing something that
6683     * should be seen as a completely new class of view when used by accessibility,
6684     * unrelated to the class it is deriving from.  This is used to fill in
6685     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6686     */
6687    public CharSequence getAccessibilityClassName() {
6688        return View.class.getName();
6689    }
6690
6691    /**
6692     * Called when assist structure is being retrieved from a view as part of
6693     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6694     * @param structure Fill in with structured view data.  The default implementation
6695     * fills in all data that can be inferred from the view itself.
6696     */
6697    public void onProvideStructure(ViewStructure structure) {
6698        final int id = mID;
6699        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6700                && (id&0x0000ffff) != 0) {
6701            String pkg, type, entry;
6702            try {
6703                final Resources res = getResources();
6704                entry = res.getResourceEntryName(id);
6705                type = res.getResourceTypeName(id);
6706                pkg = res.getResourcePackageName(id);
6707            } catch (Resources.NotFoundException e) {
6708                entry = type = pkg = null;
6709            }
6710            structure.setId(id, pkg, type, entry);
6711        } else {
6712            structure.setId(id, null, null, null);
6713        }
6714        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6715        if (!hasIdentityMatrix()) {
6716            structure.setTransformation(getMatrix());
6717        }
6718        structure.setElevation(getZ());
6719        structure.setVisibility(getVisibility());
6720        structure.setEnabled(isEnabled());
6721        if (isClickable()) {
6722            structure.setClickable(true);
6723        }
6724        if (isFocusable()) {
6725            structure.setFocusable(true);
6726        }
6727        if (isFocused()) {
6728            structure.setFocused(true);
6729        }
6730        if (isAccessibilityFocused()) {
6731            structure.setAccessibilityFocused(true);
6732        }
6733        if (isSelected()) {
6734            structure.setSelected(true);
6735        }
6736        if (isActivated()) {
6737            structure.setActivated(true);
6738        }
6739        if (isLongClickable()) {
6740            structure.setLongClickable(true);
6741        }
6742        if (this instanceof Checkable) {
6743            structure.setCheckable(true);
6744            if (((Checkable)this).isChecked()) {
6745                structure.setChecked(true);
6746            }
6747        }
6748        if (isContextClickable()) {
6749            structure.setContextClickable(true);
6750        }
6751        structure.setClassName(getAccessibilityClassName().toString());
6752        structure.setContentDescription(getContentDescription());
6753    }
6754
6755    /**
6756     * Called when assist structure is being retrieved from a view as part of
6757     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6758     * generate additional virtual structure under this view.  The defaullt implementation
6759     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6760     * view's virtual accessibility nodes, if any.  You can override this for a more
6761     * optimal implementation providing this data.
6762     */
6763    public void onProvideVirtualStructure(ViewStructure structure) {
6764        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6765        if (provider != null) {
6766            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6767            structure.setChildCount(1);
6768            ViewStructure root = structure.newChild(0);
6769            populateVirtualStructure(root, provider, info);
6770            info.recycle();
6771        }
6772    }
6773
6774    private void populateVirtualStructure(ViewStructure structure,
6775            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6776        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6777                null, null, null);
6778        Rect rect = structure.getTempRect();
6779        info.getBoundsInParent(rect);
6780        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6781        structure.setVisibility(VISIBLE);
6782        structure.setEnabled(info.isEnabled());
6783        if (info.isClickable()) {
6784            structure.setClickable(true);
6785        }
6786        if (info.isFocusable()) {
6787            structure.setFocusable(true);
6788        }
6789        if (info.isFocused()) {
6790            structure.setFocused(true);
6791        }
6792        if (info.isAccessibilityFocused()) {
6793            structure.setAccessibilityFocused(true);
6794        }
6795        if (info.isSelected()) {
6796            structure.setSelected(true);
6797        }
6798        if (info.isLongClickable()) {
6799            structure.setLongClickable(true);
6800        }
6801        if (info.isCheckable()) {
6802            structure.setCheckable(true);
6803            if (info.isChecked()) {
6804                structure.setChecked(true);
6805            }
6806        }
6807        if (info.isContextClickable()) {
6808            structure.setContextClickable(true);
6809        }
6810        CharSequence cname = info.getClassName();
6811        structure.setClassName(cname != null ? cname.toString() : null);
6812        structure.setContentDescription(info.getContentDescription());
6813        if (info.getText() != null || info.getError() != null) {
6814            structure.setText(info.getText(), info.getTextSelectionStart(),
6815                    info.getTextSelectionEnd());
6816        }
6817        final int NCHILDREN = info.getChildCount();
6818        if (NCHILDREN > 0) {
6819            structure.setChildCount(NCHILDREN);
6820            for (int i=0; i<NCHILDREN; i++) {
6821                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6822                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6823                ViewStructure child = structure.newChild(i);
6824                populateVirtualStructure(child, provider, cinfo);
6825                cinfo.recycle();
6826            }
6827        }
6828    }
6829
6830    /**
6831     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6832     * implementation calls {@link #onProvideStructure} and
6833     * {@link #onProvideVirtualStructure}.
6834     */
6835    public void dispatchProvideStructure(ViewStructure structure) {
6836        if (!isAssistBlocked()) {
6837            onProvideStructure(structure);
6838            onProvideVirtualStructure(structure);
6839        } else {
6840            structure.setClassName(getAccessibilityClassName().toString());
6841            structure.setAssistBlocked(true);
6842        }
6843    }
6844
6845    /**
6846     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6847     *
6848     * Note: Called from the default {@link AccessibilityDelegate}.
6849     *
6850     * @hide
6851     */
6852    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6853        if (mAttachInfo == null) {
6854            return;
6855        }
6856
6857        Rect bounds = mAttachInfo.mTmpInvalRect;
6858
6859        getDrawingRect(bounds);
6860        info.setBoundsInParent(bounds);
6861
6862        getBoundsOnScreen(bounds, true);
6863        info.setBoundsInScreen(bounds);
6864
6865        ViewParent parent = getParentForAccessibility();
6866        if (parent instanceof View) {
6867            info.setParent((View) parent);
6868        }
6869
6870        if (mID != View.NO_ID) {
6871            View rootView = getRootView();
6872            if (rootView == null) {
6873                rootView = this;
6874            }
6875
6876            View label = rootView.findLabelForView(this, mID);
6877            if (label != null) {
6878                info.setLabeledBy(label);
6879            }
6880
6881            if ((mAttachInfo.mAccessibilityFetchFlags
6882                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6883                    && Resources.resourceHasPackage(mID)) {
6884                try {
6885                    String viewId = getResources().getResourceName(mID);
6886                    info.setViewIdResourceName(viewId);
6887                } catch (Resources.NotFoundException nfe) {
6888                    /* ignore */
6889                }
6890            }
6891        }
6892
6893        if (mLabelForId != View.NO_ID) {
6894            View rootView = getRootView();
6895            if (rootView == null) {
6896                rootView = this;
6897            }
6898            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6899            if (labeled != null) {
6900                info.setLabelFor(labeled);
6901            }
6902        }
6903
6904        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6905            View rootView = getRootView();
6906            if (rootView == null) {
6907                rootView = this;
6908            }
6909            View next = rootView.findViewInsideOutShouldExist(this,
6910                    mAccessibilityTraversalBeforeId);
6911            if (next != null && next.includeForAccessibility()) {
6912                info.setTraversalBefore(next);
6913            }
6914        }
6915
6916        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6917            View rootView = getRootView();
6918            if (rootView == null) {
6919                rootView = this;
6920            }
6921            View next = rootView.findViewInsideOutShouldExist(this,
6922                    mAccessibilityTraversalAfterId);
6923            if (next != null && next.includeForAccessibility()) {
6924                info.setTraversalAfter(next);
6925            }
6926        }
6927
6928        info.setVisibleToUser(isVisibleToUser());
6929
6930        if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags
6931                & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) {
6932            info.setImportantForAccessibility(isImportantForAccessibility());
6933        } else {
6934            info.setImportantForAccessibility(true);
6935        }
6936
6937        info.setPackageName(mContext.getPackageName());
6938        info.setClassName(getAccessibilityClassName());
6939        info.setContentDescription(getContentDescription());
6940
6941        info.setEnabled(isEnabled());
6942        info.setClickable(isClickable());
6943        info.setFocusable(isFocusable());
6944        info.setFocused(isFocused());
6945        info.setAccessibilityFocused(isAccessibilityFocused());
6946        info.setSelected(isSelected());
6947        info.setLongClickable(isLongClickable());
6948        info.setContextClickable(isContextClickable());
6949        info.setLiveRegion(getAccessibilityLiveRegion());
6950
6951        // TODO: These make sense only if we are in an AdapterView but all
6952        // views can be selected. Maybe from accessibility perspective
6953        // we should report as selectable view in an AdapterView.
6954        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6955        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6956
6957        if (isFocusable()) {
6958            if (isFocused()) {
6959                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6960            } else {
6961                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6962            }
6963        }
6964
6965        if (!isAccessibilityFocused()) {
6966            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6967        } else {
6968            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6969        }
6970
6971        if (isClickable() && isEnabled()) {
6972            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6973        }
6974
6975        if (isLongClickable() && isEnabled()) {
6976            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6977        }
6978
6979        if (isContextClickable() && isEnabled()) {
6980            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6981        }
6982
6983        CharSequence text = getIterableTextForAccessibility();
6984        if (text != null && text.length() > 0) {
6985            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6986
6987            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6988            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6989            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6990            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6991                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6992                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6993        }
6994
6995        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6996        populateAccessibilityNodeInfoDrawingOrderInParent(info);
6997    }
6998
6999    /**
7000     * Determine the order in which this view will be drawn relative to its siblings for a11y
7001     *
7002     * @param info The info whose drawing order should be populated
7003     */
7004    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7005        /*
7006         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7007         * drawing order may not be well-defined, and some Views with custom drawing order may
7008         * not be initialized sufficiently to respond properly getChildDrawingOrder.
7009         */
7010        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7011            info.setDrawingOrder(0);
7012            return;
7013        }
7014        int drawingOrderInParent = 1;
7015        // Iterate up the hierarchy if parents are not important for a11y
7016        View viewAtDrawingLevel = this;
7017        final ViewParent parent = getParentForAccessibility();
7018        while (viewAtDrawingLevel != parent) {
7019            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7020            if (!(currentParent instanceof ViewGroup)) {
7021                // Should only happen for the Decor
7022                drawingOrderInParent = 0;
7023                break;
7024            } else {
7025                final ViewGroup parentGroup = (ViewGroup) currentParent;
7026                final int childCount = parentGroup.getChildCount();
7027                if (childCount > 1) {
7028                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7029                    if (preorderedList != null) {
7030                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7031                        for (int i = 0; i < childDrawIndex; i++) {
7032                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7033                        }
7034                    } else {
7035                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7036                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7037                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7038                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7039                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7040                        if (childDrawIndex != 0) {
7041                            for (int i = 0; i < numChildrenToIterate; i++) {
7042                                final int otherDrawIndex = (customOrder ?
7043                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7044                                if (otherDrawIndex < childDrawIndex) {
7045                                    drawingOrderInParent +=
7046                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7047                                }
7048                            }
7049                        }
7050                    }
7051                }
7052            }
7053            viewAtDrawingLevel = (View) currentParent;
7054        }
7055        info.setDrawingOrder(drawingOrderInParent);
7056    }
7057
7058    private static int numViewsForAccessibility(View view) {
7059        if (view != null) {
7060            if (view.includeForAccessibility()) {
7061                return 1;
7062            } else if (view instanceof ViewGroup) {
7063                return ((ViewGroup) view).getNumChildrenForAccessibility();
7064            }
7065        }
7066        return 0;
7067    }
7068
7069    private View findLabelForView(View view, int labeledId) {
7070        if (mMatchLabelForPredicate == null) {
7071            mMatchLabelForPredicate = new MatchLabelForPredicate();
7072        }
7073        mMatchLabelForPredicate.mLabeledId = labeledId;
7074        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7075    }
7076
7077    /**
7078     * Computes whether this view is visible to the user. Such a view is
7079     * attached, visible, all its predecessors are visible, it is not clipped
7080     * entirely by its predecessors, and has an alpha greater than zero.
7081     *
7082     * @return Whether the view is visible on the screen.
7083     *
7084     * @hide
7085     */
7086    protected boolean isVisibleToUser() {
7087        return isVisibleToUser(null);
7088    }
7089
7090    /**
7091     * Computes whether the given portion of this view is visible to the user.
7092     * Such a view is attached, visible, all its predecessors are visible,
7093     * has an alpha greater than zero, and the specified portion is not
7094     * clipped entirely by its predecessors.
7095     *
7096     * @param boundInView the portion of the view to test; coordinates should be relative; may be
7097     *                    <code>null</code>, and the entire view will be tested in this case.
7098     *                    When <code>true</code> is returned by the function, the actual visible
7099     *                    region will be stored in this parameter; that is, if boundInView is fully
7100     *                    contained within the view, no modification will be made, otherwise regions
7101     *                    outside of the visible area of the view will be clipped.
7102     *
7103     * @return Whether the specified portion of the view is visible on the screen.
7104     *
7105     * @hide
7106     */
7107    protected boolean isVisibleToUser(Rect boundInView) {
7108        if (mAttachInfo != null) {
7109            // Attached to invisible window means this view is not visible.
7110            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
7111                return false;
7112            }
7113            // An invisible predecessor or one with alpha zero means
7114            // that this view is not visible to the user.
7115            Object current = this;
7116            while (current instanceof View) {
7117                View view = (View) current;
7118                // We have attach info so this view is attached and there is no
7119                // need to check whether we reach to ViewRootImpl on the way up.
7120                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
7121                        view.getVisibility() != VISIBLE) {
7122                    return false;
7123                }
7124                current = view.mParent;
7125            }
7126            // Check if the view is entirely covered by its predecessors.
7127            Rect visibleRect = mAttachInfo.mTmpInvalRect;
7128            Point offset = mAttachInfo.mPoint;
7129            if (!getGlobalVisibleRect(visibleRect, offset)) {
7130                return false;
7131            }
7132            // Check if the visible portion intersects the rectangle of interest.
7133            if (boundInView != null) {
7134                visibleRect.offset(-offset.x, -offset.y);
7135                return boundInView.intersect(visibleRect);
7136            }
7137            return true;
7138        }
7139        return false;
7140    }
7141
7142    /**
7143     * Returns the delegate for implementing accessibility support via
7144     * composition. For more details see {@link AccessibilityDelegate}.
7145     *
7146     * @return The delegate, or null if none set.
7147     *
7148     * @hide
7149     */
7150    public AccessibilityDelegate getAccessibilityDelegate() {
7151        return mAccessibilityDelegate;
7152    }
7153
7154    /**
7155     * Sets a delegate for implementing accessibility support via composition
7156     * (as opposed to inheritance). For more details, see
7157     * {@link AccessibilityDelegate}.
7158     * <p>
7159     * <strong>Note:</strong> On platform versions prior to
7160     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
7161     * views in the {@code android.widget.*} package are called <i>before</i>
7162     * host methods. This prevents certain properties such as class name from
7163     * being modified by overriding
7164     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
7165     * as any changes will be overwritten by the host class.
7166     * <p>
7167     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
7168     * methods are called <i>after</i> host methods, which all properties to be
7169     * modified without being overwritten by the host class.
7170     *
7171     * @param delegate the object to which accessibility method calls should be
7172     *                 delegated
7173     * @see AccessibilityDelegate
7174     */
7175    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
7176        mAccessibilityDelegate = delegate;
7177    }
7178
7179    /**
7180     * Gets the provider for managing a virtual view hierarchy rooted at this View
7181     * and reported to {@link android.accessibilityservice.AccessibilityService}s
7182     * that explore the window content.
7183     * <p>
7184     * If this method returns an instance, this instance is responsible for managing
7185     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
7186     * View including the one representing the View itself. Similarly the returned
7187     * instance is responsible for performing accessibility actions on any virtual
7188     * view or the root view itself.
7189     * </p>
7190     * <p>
7191     * If an {@link AccessibilityDelegate} has been specified via calling
7192     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7193     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
7194     * is responsible for handling this call.
7195     * </p>
7196     *
7197     * @return The provider.
7198     *
7199     * @see AccessibilityNodeProvider
7200     */
7201    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
7202        if (mAccessibilityDelegate != null) {
7203            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
7204        } else {
7205            return null;
7206        }
7207    }
7208
7209    /**
7210     * Gets the unique identifier of this view on the screen for accessibility purposes.
7211     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
7212     *
7213     * @return The view accessibility id.
7214     *
7215     * @hide
7216     */
7217    public int getAccessibilityViewId() {
7218        if (mAccessibilityViewId == NO_ID) {
7219            mAccessibilityViewId = sNextAccessibilityViewId++;
7220        }
7221        return mAccessibilityViewId;
7222    }
7223
7224    /**
7225     * Gets the unique identifier of the window in which this View reseides.
7226     *
7227     * @return The window accessibility id.
7228     *
7229     * @hide
7230     */
7231    public int getAccessibilityWindowId() {
7232        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
7233                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
7234    }
7235
7236    /**
7237     * Returns the {@link View}'s content description.
7238     * <p>
7239     * <strong>Note:</strong> Do not override this method, as it will have no
7240     * effect on the content description presented to accessibility services.
7241     * You must call {@link #setContentDescription(CharSequence)} to modify the
7242     * content description.
7243     *
7244     * @return the content description
7245     * @see #setContentDescription(CharSequence)
7246     * @attr ref android.R.styleable#View_contentDescription
7247     */
7248    @ViewDebug.ExportedProperty(category = "accessibility")
7249    public CharSequence getContentDescription() {
7250        return mContentDescription;
7251    }
7252
7253    /**
7254     * Sets the {@link View}'s content description.
7255     * <p>
7256     * A content description briefly describes the view and is primarily used
7257     * for accessibility support to determine how a view should be presented to
7258     * the user. In the case of a view with no textual representation, such as
7259     * {@link android.widget.ImageButton}, a useful content description
7260     * explains what the view does. For example, an image button with a phone
7261     * icon that is used to place a call may use "Call" as its content
7262     * description. An image of a floppy disk that is used to save a file may
7263     * use "Save".
7264     *
7265     * @param contentDescription The content description.
7266     * @see #getContentDescription()
7267     * @attr ref android.R.styleable#View_contentDescription
7268     */
7269    @RemotableViewMethod
7270    public void setContentDescription(CharSequence contentDescription) {
7271        if (mContentDescription == null) {
7272            if (contentDescription == null) {
7273                return;
7274            }
7275        } else if (mContentDescription.equals(contentDescription)) {
7276            return;
7277        }
7278        mContentDescription = contentDescription;
7279        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
7280        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
7281            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
7282            notifySubtreeAccessibilityStateChangedIfNeeded();
7283        } else {
7284            notifyViewAccessibilityStateChangedIfNeeded(
7285                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
7286        }
7287    }
7288
7289    /**
7290     * Sets the id of a view before which this one is visited in accessibility traversal.
7291     * A screen-reader must visit the content of this view before the content of the one
7292     * it precedes. For example, if view B is set to be before view A, then a screen-reader
7293     * will traverse the entire content of B before traversing the entire content of A,
7294     * regardles of what traversal strategy it is using.
7295     * <p>
7296     * Views that do not have specified before/after relationships are traversed in order
7297     * determined by the screen-reader.
7298     * </p>
7299     * <p>
7300     * Setting that this view is before a view that is not important for accessibility
7301     * or if this view is not important for accessibility will have no effect as the
7302     * screen-reader is not aware of unimportant views.
7303     * </p>
7304     *
7305     * @param beforeId The id of a view this one precedes in accessibility traversal.
7306     *
7307     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
7308     *
7309     * @see #setImportantForAccessibility(int)
7310     */
7311    @RemotableViewMethod
7312    public void setAccessibilityTraversalBefore(int beforeId) {
7313        if (mAccessibilityTraversalBeforeId == beforeId) {
7314            return;
7315        }
7316        mAccessibilityTraversalBeforeId = beforeId;
7317        notifyViewAccessibilityStateChangedIfNeeded(
7318                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7319    }
7320
7321    /**
7322     * Gets the id of a view before which this one is visited in accessibility traversal.
7323     *
7324     * @return The id of a view this one precedes in accessibility traversal if
7325     *         specified, otherwise {@link #NO_ID}.
7326     *
7327     * @see #setAccessibilityTraversalBefore(int)
7328     */
7329    public int getAccessibilityTraversalBefore() {
7330        return mAccessibilityTraversalBeforeId;
7331    }
7332
7333    /**
7334     * Sets the id of a view after which this one is visited in accessibility traversal.
7335     * A screen-reader must visit the content of the other view before the content of this
7336     * one. For example, if view B is set to be after view A, then a screen-reader
7337     * will traverse the entire content of A before traversing the entire content of B,
7338     * regardles of what traversal strategy it is using.
7339     * <p>
7340     * Views that do not have specified before/after relationships are traversed in order
7341     * determined by the screen-reader.
7342     * </p>
7343     * <p>
7344     * Setting that this view is after a view that is not important for accessibility
7345     * or if this view is not important for accessibility will have no effect as the
7346     * screen-reader is not aware of unimportant views.
7347     * </p>
7348     *
7349     * @param afterId The id of a view this one succedees in accessibility traversal.
7350     *
7351     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
7352     *
7353     * @see #setImportantForAccessibility(int)
7354     */
7355    @RemotableViewMethod
7356    public void setAccessibilityTraversalAfter(int afterId) {
7357        if (mAccessibilityTraversalAfterId == afterId) {
7358            return;
7359        }
7360        mAccessibilityTraversalAfterId = afterId;
7361        notifyViewAccessibilityStateChangedIfNeeded(
7362                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7363    }
7364
7365    /**
7366     * Gets the id of a view after which this one is visited in accessibility traversal.
7367     *
7368     * @return The id of a view this one succeedes in accessibility traversal if
7369     *         specified, otherwise {@link #NO_ID}.
7370     *
7371     * @see #setAccessibilityTraversalAfter(int)
7372     */
7373    public int getAccessibilityTraversalAfter() {
7374        return mAccessibilityTraversalAfterId;
7375    }
7376
7377    /**
7378     * Gets the id of a view for which this view serves as a label for
7379     * accessibility purposes.
7380     *
7381     * @return The labeled view id.
7382     */
7383    @ViewDebug.ExportedProperty(category = "accessibility")
7384    public int getLabelFor() {
7385        return mLabelForId;
7386    }
7387
7388    /**
7389     * Sets the id of a view for which this view serves as a label for
7390     * accessibility purposes.
7391     *
7392     * @param id The labeled view id.
7393     */
7394    @RemotableViewMethod
7395    public void setLabelFor(@IdRes int id) {
7396        if (mLabelForId == id) {
7397            return;
7398        }
7399        mLabelForId = id;
7400        if (mLabelForId != View.NO_ID
7401                && mID == View.NO_ID) {
7402            mID = generateViewId();
7403        }
7404        notifyViewAccessibilityStateChangedIfNeeded(
7405                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7406    }
7407
7408    /**
7409     * Invoked whenever this view loses focus, either by losing window focus or by losing
7410     * focus within its window. This method can be used to clear any state tied to the
7411     * focus. For instance, if a button is held pressed with the trackball and the window
7412     * loses focus, this method can be used to cancel the press.
7413     *
7414     * Subclasses of View overriding this method should always call super.onFocusLost().
7415     *
7416     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7417     * @see #onWindowFocusChanged(boolean)
7418     *
7419     * @hide pending API council approval
7420     */
7421    @CallSuper
7422    protected void onFocusLost() {
7423        resetPressedState();
7424    }
7425
7426    private void resetPressedState() {
7427        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7428            return;
7429        }
7430
7431        if (isPressed()) {
7432            setPressed(false);
7433
7434            if (!mHasPerformedLongPress) {
7435                removeLongPressCallback();
7436            }
7437        }
7438    }
7439
7440    /**
7441     * Returns true if this view has focus
7442     *
7443     * @return True if this view has focus, false otherwise.
7444     */
7445    @ViewDebug.ExportedProperty(category = "focus")
7446    public boolean isFocused() {
7447        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7448    }
7449
7450    /**
7451     * Find the view in the hierarchy rooted at this view that currently has
7452     * focus.
7453     *
7454     * @return The view that currently has focus, or null if no focused view can
7455     *         be found.
7456     */
7457    public View findFocus() {
7458        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7459    }
7460
7461    /**
7462     * Indicates whether this view is one of the set of scrollable containers in
7463     * its window.
7464     *
7465     * @return whether this view is one of the set of scrollable containers in
7466     * its window
7467     *
7468     * @attr ref android.R.styleable#View_isScrollContainer
7469     */
7470    public boolean isScrollContainer() {
7471        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7472    }
7473
7474    /**
7475     * Change whether this view is one of the set of scrollable containers in
7476     * its window.  This will be used to determine whether the window can
7477     * resize or must pan when a soft input area is open -- scrollable
7478     * containers allow the window to use resize mode since the container
7479     * will appropriately shrink.
7480     *
7481     * @attr ref android.R.styleable#View_isScrollContainer
7482     */
7483    public void setScrollContainer(boolean isScrollContainer) {
7484        if (isScrollContainer) {
7485            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7486                mAttachInfo.mScrollContainers.add(this);
7487                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7488            }
7489            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7490        } else {
7491            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7492                mAttachInfo.mScrollContainers.remove(this);
7493            }
7494            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7495        }
7496    }
7497
7498    /**
7499     * Returns the quality of the drawing cache.
7500     *
7501     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7502     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7503     *
7504     * @see #setDrawingCacheQuality(int)
7505     * @see #setDrawingCacheEnabled(boolean)
7506     * @see #isDrawingCacheEnabled()
7507     *
7508     * @attr ref android.R.styleable#View_drawingCacheQuality
7509     */
7510    @DrawingCacheQuality
7511    public int getDrawingCacheQuality() {
7512        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7513    }
7514
7515    /**
7516     * Set the drawing cache quality of this view. This value is used only when the
7517     * drawing cache is enabled
7518     *
7519     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7520     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7521     *
7522     * @see #getDrawingCacheQuality()
7523     * @see #setDrawingCacheEnabled(boolean)
7524     * @see #isDrawingCacheEnabled()
7525     *
7526     * @attr ref android.R.styleable#View_drawingCacheQuality
7527     */
7528    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7529        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7530    }
7531
7532    /**
7533     * Returns whether the screen should remain on, corresponding to the current
7534     * value of {@link #KEEP_SCREEN_ON}.
7535     *
7536     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7537     *
7538     * @see #setKeepScreenOn(boolean)
7539     *
7540     * @attr ref android.R.styleable#View_keepScreenOn
7541     */
7542    public boolean getKeepScreenOn() {
7543        return (mViewFlags & KEEP_SCREEN_ON) != 0;
7544    }
7545
7546    /**
7547     * Controls whether the screen should remain on, modifying the
7548     * value of {@link #KEEP_SCREEN_ON}.
7549     *
7550     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7551     *
7552     * @see #getKeepScreenOn()
7553     *
7554     * @attr ref android.R.styleable#View_keepScreenOn
7555     */
7556    public void setKeepScreenOn(boolean keepScreenOn) {
7557        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7558    }
7559
7560    /**
7561     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7562     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7563     *
7564     * @attr ref android.R.styleable#View_nextFocusLeft
7565     */
7566    public int getNextFocusLeftId() {
7567        return mNextFocusLeftId;
7568    }
7569
7570    /**
7571     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7572     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7573     * decide automatically.
7574     *
7575     * @attr ref android.R.styleable#View_nextFocusLeft
7576     */
7577    public void setNextFocusLeftId(int nextFocusLeftId) {
7578        mNextFocusLeftId = nextFocusLeftId;
7579    }
7580
7581    /**
7582     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7583     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7584     *
7585     * @attr ref android.R.styleable#View_nextFocusRight
7586     */
7587    public int getNextFocusRightId() {
7588        return mNextFocusRightId;
7589    }
7590
7591    /**
7592     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7593     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7594     * decide automatically.
7595     *
7596     * @attr ref android.R.styleable#View_nextFocusRight
7597     */
7598    public void setNextFocusRightId(int nextFocusRightId) {
7599        mNextFocusRightId = nextFocusRightId;
7600    }
7601
7602    /**
7603     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7604     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7605     *
7606     * @attr ref android.R.styleable#View_nextFocusUp
7607     */
7608    public int getNextFocusUpId() {
7609        return mNextFocusUpId;
7610    }
7611
7612    /**
7613     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7614     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7615     * decide automatically.
7616     *
7617     * @attr ref android.R.styleable#View_nextFocusUp
7618     */
7619    public void setNextFocusUpId(int nextFocusUpId) {
7620        mNextFocusUpId = nextFocusUpId;
7621    }
7622
7623    /**
7624     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7625     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7626     *
7627     * @attr ref android.R.styleable#View_nextFocusDown
7628     */
7629    public int getNextFocusDownId() {
7630        return mNextFocusDownId;
7631    }
7632
7633    /**
7634     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7635     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7636     * decide automatically.
7637     *
7638     * @attr ref android.R.styleable#View_nextFocusDown
7639     */
7640    public void setNextFocusDownId(int nextFocusDownId) {
7641        mNextFocusDownId = nextFocusDownId;
7642    }
7643
7644    /**
7645     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7646     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7647     *
7648     * @attr ref android.R.styleable#View_nextFocusForward
7649     */
7650    public int getNextFocusForwardId() {
7651        return mNextFocusForwardId;
7652    }
7653
7654    /**
7655     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7656     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7657     * decide automatically.
7658     *
7659     * @attr ref android.R.styleable#View_nextFocusForward
7660     */
7661    public void setNextFocusForwardId(int nextFocusForwardId) {
7662        mNextFocusForwardId = nextFocusForwardId;
7663    }
7664
7665    /**
7666     * Returns the visibility of this view and all of its ancestors
7667     *
7668     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7669     */
7670    public boolean isShown() {
7671        View current = this;
7672        //noinspection ConstantConditions
7673        do {
7674            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7675                return false;
7676            }
7677            ViewParent parent = current.mParent;
7678            if (parent == null) {
7679                return false; // We are not attached to the view root
7680            }
7681            if (!(parent instanceof View)) {
7682                return true;
7683            }
7684            current = (View) parent;
7685        } while (current != null);
7686
7687        return false;
7688    }
7689
7690    /**
7691     * Called by the view hierarchy when the content insets for a window have
7692     * changed, to allow it to adjust its content to fit within those windows.
7693     * The content insets tell you the space that the status bar, input method,
7694     * and other system windows infringe on the application's window.
7695     *
7696     * <p>You do not normally need to deal with this function, since the default
7697     * window decoration given to applications takes care of applying it to the
7698     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7699     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7700     * and your content can be placed under those system elements.  You can then
7701     * use this method within your view hierarchy if you have parts of your UI
7702     * which you would like to ensure are not being covered.
7703     *
7704     * <p>The default implementation of this method simply applies the content
7705     * insets to the view's padding, consuming that content (modifying the
7706     * insets to be 0), and returning true.  This behavior is off by default, but can
7707     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7708     *
7709     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7710     * insets object is propagated down the hierarchy, so any changes made to it will
7711     * be seen by all following views (including potentially ones above in
7712     * the hierarchy since this is a depth-first traversal).  The first view
7713     * that returns true will abort the entire traversal.
7714     *
7715     * <p>The default implementation works well for a situation where it is
7716     * used with a container that covers the entire window, allowing it to
7717     * apply the appropriate insets to its content on all edges.  If you need
7718     * a more complicated layout (such as two different views fitting system
7719     * windows, one on the top of the window, and one on the bottom),
7720     * you can override the method and handle the insets however you would like.
7721     * Note that the insets provided by the framework are always relative to the
7722     * far edges of the window, not accounting for the location of the called view
7723     * within that window.  (In fact when this method is called you do not yet know
7724     * where the layout will place the view, as it is done before layout happens.)
7725     *
7726     * <p>Note: unlike many View methods, there is no dispatch phase to this
7727     * call.  If you are overriding it in a ViewGroup and want to allow the
7728     * call to continue to your children, you must be sure to call the super
7729     * implementation.
7730     *
7731     * <p>Here is a sample layout that makes use of fitting system windows
7732     * to have controls for a video view placed inside of the window decorations
7733     * that it hides and shows.  This can be used with code like the second
7734     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7735     *
7736     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7737     *
7738     * @param insets Current content insets of the window.  Prior to
7739     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7740     * the insets or else you and Android will be unhappy.
7741     *
7742     * @return {@code true} if this view applied the insets and it should not
7743     * continue propagating further down the hierarchy, {@code false} otherwise.
7744     * @see #getFitsSystemWindows()
7745     * @see #setFitsSystemWindows(boolean)
7746     * @see #setSystemUiVisibility(int)
7747     *
7748     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7749     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7750     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7751     * to implement handling their own insets.
7752     */
7753    protected boolean fitSystemWindows(Rect insets) {
7754        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7755            if (insets == null) {
7756                // Null insets by definition have already been consumed.
7757                // This call cannot apply insets since there are none to apply,
7758                // so return false.
7759                return false;
7760            }
7761            // If we're not in the process of dispatching the newer apply insets call,
7762            // that means we're not in the compatibility path. Dispatch into the newer
7763            // apply insets path and take things from there.
7764            try {
7765                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7766                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7767            } finally {
7768                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7769            }
7770        } else {
7771            // We're being called from the newer apply insets path.
7772            // Perform the standard fallback behavior.
7773            return fitSystemWindowsInt(insets);
7774        }
7775    }
7776
7777    private boolean fitSystemWindowsInt(Rect insets) {
7778        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7779            mUserPaddingStart = UNDEFINED_PADDING;
7780            mUserPaddingEnd = UNDEFINED_PADDING;
7781            Rect localInsets = sThreadLocal.get();
7782            if (localInsets == null) {
7783                localInsets = new Rect();
7784                sThreadLocal.set(localInsets);
7785            }
7786            boolean res = computeFitSystemWindows(insets, localInsets);
7787            mUserPaddingLeftInitial = localInsets.left;
7788            mUserPaddingRightInitial = localInsets.right;
7789            internalSetPadding(localInsets.left, localInsets.top,
7790                    localInsets.right, localInsets.bottom);
7791            return res;
7792        }
7793        return false;
7794    }
7795
7796    /**
7797     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7798     *
7799     * <p>This method should be overridden by views that wish to apply a policy different from or
7800     * in addition to the default behavior. Clients that wish to force a view subtree
7801     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7802     *
7803     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7804     * it will be called during dispatch instead of this method. The listener may optionally
7805     * call this method from its own implementation if it wishes to apply the view's default
7806     * insets policy in addition to its own.</p>
7807     *
7808     * <p>Implementations of this method should either return the insets parameter unchanged
7809     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7810     * that this view applied itself. This allows new inset types added in future platform
7811     * versions to pass through existing implementations unchanged without being erroneously
7812     * consumed.</p>
7813     *
7814     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7815     * property is set then the view will consume the system window insets and apply them
7816     * as padding for the view.</p>
7817     *
7818     * @param insets Insets to apply
7819     * @return The supplied insets with any applied insets consumed
7820     */
7821    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7822        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7823            // We weren't called from within a direct call to fitSystemWindows,
7824            // call into it as a fallback in case we're in a class that overrides it
7825            // and has logic to perform.
7826            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7827                return insets.consumeSystemWindowInsets();
7828            }
7829        } else {
7830            // We were called from within a direct call to fitSystemWindows.
7831            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7832                return insets.consumeSystemWindowInsets();
7833            }
7834        }
7835        return insets;
7836    }
7837
7838    /**
7839     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7840     * window insets to this view. The listener's
7841     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7842     * method will be called instead of the view's
7843     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7844     *
7845     * @param listener Listener to set
7846     *
7847     * @see #onApplyWindowInsets(WindowInsets)
7848     */
7849    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7850        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7851    }
7852
7853    /**
7854     * Request to apply the given window insets to this view or another view in its subtree.
7855     *
7856     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7857     * obscured by window decorations or overlays. This can include the status and navigation bars,
7858     * action bars, input methods and more. New inset categories may be added in the future.
7859     * The method returns the insets provided minus any that were applied by this view or its
7860     * children.</p>
7861     *
7862     * <p>Clients wishing to provide custom behavior should override the
7863     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7864     * {@link OnApplyWindowInsetsListener} via the
7865     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7866     * method.</p>
7867     *
7868     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7869     * </p>
7870     *
7871     * @param insets Insets to apply
7872     * @return The provided insets minus the insets that were consumed
7873     */
7874    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7875        try {
7876            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7877            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7878                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7879            } else {
7880                return onApplyWindowInsets(insets);
7881            }
7882        } finally {
7883            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7884        }
7885    }
7886
7887    /**
7888     * Compute the view's coordinate within the surface.
7889     *
7890     * <p>Computes the coordinates of this view in its surface. The argument
7891     * must be an array of two integers. After the method returns, the array
7892     * contains the x and y location in that order.</p>
7893     * @hide
7894     * @param location an array of two integers in which to hold the coordinates
7895     */
7896    public void getLocationInSurface(@Size(2) int[] location) {
7897        getLocationInWindow(location);
7898        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
7899            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
7900            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
7901        }
7902    }
7903
7904    /**
7905     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7906     * only available if the view is attached.
7907     *
7908     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7909     */
7910    public WindowInsets getRootWindowInsets() {
7911        if (mAttachInfo != null) {
7912            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7913        }
7914        return null;
7915    }
7916
7917    /**
7918     * @hide Compute the insets that should be consumed by this view and the ones
7919     * that should propagate to those under it.
7920     */
7921    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7922        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7923                || mAttachInfo == null
7924                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7925                        && !mAttachInfo.mOverscanRequested)) {
7926            outLocalInsets.set(inoutInsets);
7927            inoutInsets.set(0, 0, 0, 0);
7928            return true;
7929        } else {
7930            // The application wants to take care of fitting system window for
7931            // the content...  however we still need to take care of any overscan here.
7932            final Rect overscan = mAttachInfo.mOverscanInsets;
7933            outLocalInsets.set(overscan);
7934            inoutInsets.left -= overscan.left;
7935            inoutInsets.top -= overscan.top;
7936            inoutInsets.right -= overscan.right;
7937            inoutInsets.bottom -= overscan.bottom;
7938            return false;
7939        }
7940    }
7941
7942    /**
7943     * Compute insets that should be consumed by this view and the ones that should propagate
7944     * to those under it.
7945     *
7946     * @param in Insets currently being processed by this View, likely received as a parameter
7947     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7948     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7949     *                       by this view
7950     * @return Insets that should be passed along to views under this one
7951     */
7952    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7953        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7954                || mAttachInfo == null
7955                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7956            outLocalInsets.set(in.getSystemWindowInsets());
7957            return in.consumeSystemWindowInsets();
7958        } else {
7959            outLocalInsets.set(0, 0, 0, 0);
7960            return in;
7961        }
7962    }
7963
7964    /**
7965     * Sets whether or not this view should account for system screen decorations
7966     * such as the status bar and inset its content; that is, controlling whether
7967     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7968     * executed.  See that method for more details.
7969     *
7970     * <p>Note that if you are providing your own implementation of
7971     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7972     * flag to true -- your implementation will be overriding the default
7973     * implementation that checks this flag.
7974     *
7975     * @param fitSystemWindows If true, then the default implementation of
7976     * {@link #fitSystemWindows(Rect)} will be executed.
7977     *
7978     * @attr ref android.R.styleable#View_fitsSystemWindows
7979     * @see #getFitsSystemWindows()
7980     * @see #fitSystemWindows(Rect)
7981     * @see #setSystemUiVisibility(int)
7982     */
7983    public void setFitsSystemWindows(boolean fitSystemWindows) {
7984        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7985    }
7986
7987    /**
7988     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7989     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7990     * will be executed.
7991     *
7992     * @return {@code true} if the default implementation of
7993     * {@link #fitSystemWindows(Rect)} will be executed.
7994     *
7995     * @attr ref android.R.styleable#View_fitsSystemWindows
7996     * @see #setFitsSystemWindows(boolean)
7997     * @see #fitSystemWindows(Rect)
7998     * @see #setSystemUiVisibility(int)
7999     */
8000    @ViewDebug.ExportedProperty
8001    public boolean getFitsSystemWindows() {
8002        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8003    }
8004
8005    /** @hide */
8006    public boolean fitsSystemWindows() {
8007        return getFitsSystemWindows();
8008    }
8009
8010    /**
8011     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8012     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8013     */
8014    public void requestFitSystemWindows() {
8015        if (mParent != null) {
8016            mParent.requestFitSystemWindows();
8017        }
8018    }
8019
8020    /**
8021     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8022     */
8023    public void requestApplyInsets() {
8024        requestFitSystemWindows();
8025    }
8026
8027    /**
8028     * For use by PhoneWindow to make its own system window fitting optional.
8029     * @hide
8030     */
8031    public void makeOptionalFitsSystemWindows() {
8032        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8033    }
8034
8035    /**
8036     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8037     * treat them as such.
8038     * @hide
8039     */
8040    public void getOutsets(Rect outOutsetRect) {
8041        if (mAttachInfo != null) {
8042            outOutsetRect.set(mAttachInfo.mOutsets);
8043        } else {
8044            outOutsetRect.setEmpty();
8045        }
8046    }
8047
8048    /**
8049     * Returns the visibility status for this view.
8050     *
8051     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8052     * @attr ref android.R.styleable#View_visibility
8053     */
8054    @ViewDebug.ExportedProperty(mapping = {
8055        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8056        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8057        @ViewDebug.IntToString(from = GONE,      to = "GONE")
8058    })
8059    @Visibility
8060    public int getVisibility() {
8061        return mViewFlags & VISIBILITY_MASK;
8062    }
8063
8064    /**
8065     * Set the enabled state of this view.
8066     *
8067     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8068     * @attr ref android.R.styleable#View_visibility
8069     */
8070    @RemotableViewMethod
8071    public void setVisibility(@Visibility int visibility) {
8072        setFlags(visibility, VISIBILITY_MASK);
8073    }
8074
8075    /**
8076     * Returns the enabled status for this view. The interpretation of the
8077     * enabled state varies by subclass.
8078     *
8079     * @return True if this view is enabled, false otherwise.
8080     */
8081    @ViewDebug.ExportedProperty
8082    public boolean isEnabled() {
8083        return (mViewFlags & ENABLED_MASK) == ENABLED;
8084    }
8085
8086    /**
8087     * Set the enabled state of this view. The interpretation of the enabled
8088     * state varies by subclass.
8089     *
8090     * @param enabled True if this view is enabled, false otherwise.
8091     */
8092    @RemotableViewMethod
8093    public void setEnabled(boolean enabled) {
8094        if (enabled == isEnabled()) return;
8095
8096        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
8097
8098        /*
8099         * The View most likely has to change its appearance, so refresh
8100         * the drawable state.
8101         */
8102        refreshDrawableState();
8103
8104        // Invalidate too, since the default behavior for views is to be
8105        // be drawn at 50% alpha rather than to change the drawable.
8106        invalidate(true);
8107
8108        if (!enabled) {
8109            cancelPendingInputEvents();
8110        }
8111    }
8112
8113    /**
8114     * Set whether this view can receive the focus.
8115     *
8116     * Setting this to false will also ensure that this view is not focusable
8117     * in touch mode.
8118     *
8119     * @param focusable If true, this view can receive the focus.
8120     *
8121     * @see #setFocusableInTouchMode(boolean)
8122     * @attr ref android.R.styleable#View_focusable
8123     */
8124    public void setFocusable(boolean focusable) {
8125        if (!focusable) {
8126            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
8127        }
8128        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
8129    }
8130
8131    /**
8132     * Set whether this view can receive focus while in touch mode.
8133     *
8134     * Setting this to true will also ensure that this view is focusable.
8135     *
8136     * @param focusableInTouchMode If true, this view can receive the focus while
8137     *   in touch mode.
8138     *
8139     * @see #setFocusable(boolean)
8140     * @attr ref android.R.styleable#View_focusableInTouchMode
8141     */
8142    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
8143        // Focusable in touch mode should always be set before the focusable flag
8144        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
8145        // which, in touch mode, will not successfully request focus on this view
8146        // because the focusable in touch mode flag is not set
8147        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
8148        if (focusableInTouchMode) {
8149            setFlags(FOCUSABLE, FOCUSABLE_MASK);
8150        }
8151    }
8152
8153    /**
8154     * Set whether this view should have sound effects enabled for events such as
8155     * clicking and touching.
8156     *
8157     * <p>You may wish to disable sound effects for a view if you already play sounds,
8158     * for instance, a dial key that plays dtmf tones.
8159     *
8160     * @param soundEffectsEnabled whether sound effects are enabled for this view.
8161     * @see #isSoundEffectsEnabled()
8162     * @see #playSoundEffect(int)
8163     * @attr ref android.R.styleable#View_soundEffectsEnabled
8164     */
8165    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
8166        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
8167    }
8168
8169    /**
8170     * @return whether this view should have sound effects enabled for events such as
8171     *     clicking and touching.
8172     *
8173     * @see #setSoundEffectsEnabled(boolean)
8174     * @see #playSoundEffect(int)
8175     * @attr ref android.R.styleable#View_soundEffectsEnabled
8176     */
8177    @ViewDebug.ExportedProperty
8178    public boolean isSoundEffectsEnabled() {
8179        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
8180    }
8181
8182    /**
8183     * Set whether this view should have haptic feedback for events such as
8184     * long presses.
8185     *
8186     * <p>You may wish to disable haptic feedback if your view already controls
8187     * its own haptic feedback.
8188     *
8189     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
8190     * @see #isHapticFeedbackEnabled()
8191     * @see #performHapticFeedback(int)
8192     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8193     */
8194    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
8195        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
8196    }
8197
8198    /**
8199     * @return whether this view should have haptic feedback enabled for events
8200     * long presses.
8201     *
8202     * @see #setHapticFeedbackEnabled(boolean)
8203     * @see #performHapticFeedback(int)
8204     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8205     */
8206    @ViewDebug.ExportedProperty
8207    public boolean isHapticFeedbackEnabled() {
8208        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
8209    }
8210
8211    /**
8212     * Returns the layout direction for this view.
8213     *
8214     * @return One of {@link #LAYOUT_DIRECTION_LTR},
8215     *   {@link #LAYOUT_DIRECTION_RTL},
8216     *   {@link #LAYOUT_DIRECTION_INHERIT} or
8217     *   {@link #LAYOUT_DIRECTION_LOCALE}.
8218     *
8219     * @attr ref android.R.styleable#View_layoutDirection
8220     *
8221     * @hide
8222     */
8223    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8224        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
8225        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
8226        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
8227        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
8228    })
8229    @LayoutDir
8230    public int getRawLayoutDirection() {
8231        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
8232    }
8233
8234    /**
8235     * Set the layout direction for this view. This will propagate a reset of layout direction
8236     * resolution to the view's children and resolve layout direction for this view.
8237     *
8238     * @param layoutDirection the layout direction to set. Should be one of:
8239     *
8240     * {@link #LAYOUT_DIRECTION_LTR},
8241     * {@link #LAYOUT_DIRECTION_RTL},
8242     * {@link #LAYOUT_DIRECTION_INHERIT},
8243     * {@link #LAYOUT_DIRECTION_LOCALE}.
8244     *
8245     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
8246     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
8247     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
8248     *
8249     * @attr ref android.R.styleable#View_layoutDirection
8250     */
8251    @RemotableViewMethod
8252    public void setLayoutDirection(@LayoutDir int layoutDirection) {
8253        if (getRawLayoutDirection() != layoutDirection) {
8254            // Reset the current layout direction and the resolved one
8255            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
8256            resetRtlProperties();
8257            // Set the new layout direction (filtered)
8258            mPrivateFlags2 |=
8259                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
8260            // We need to resolve all RTL properties as they all depend on layout direction
8261            resolveRtlPropertiesIfNeeded();
8262            requestLayout();
8263            invalidate(true);
8264        }
8265    }
8266
8267    /**
8268     * Returns the resolved layout direction for this view.
8269     *
8270     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
8271     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
8272     *
8273     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
8274     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
8275     *
8276     * @attr ref android.R.styleable#View_layoutDirection
8277     */
8278    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8279        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
8280        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
8281    })
8282    @ResolvedLayoutDir
8283    public int getLayoutDirection() {
8284        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
8285        if (targetSdkVersion < JELLY_BEAN_MR1) {
8286            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
8287            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
8288        }
8289        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
8290                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
8291    }
8292
8293    /**
8294     * Indicates whether or not this view's layout is right-to-left. This is resolved from
8295     * layout attribute and/or the inherited value from the parent
8296     *
8297     * @return true if the layout is right-to-left.
8298     *
8299     * @hide
8300     */
8301    @ViewDebug.ExportedProperty(category = "layout")
8302    public boolean isLayoutRtl() {
8303        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
8304    }
8305
8306    /**
8307     * Indicates whether the view is currently tracking transient state that the
8308     * app should not need to concern itself with saving and restoring, but that
8309     * the framework should take special note to preserve when possible.
8310     *
8311     * <p>A view with transient state cannot be trivially rebound from an external
8312     * data source, such as an adapter binding item views in a list. This may be
8313     * because the view is performing an animation, tracking user selection
8314     * of content, or similar.</p>
8315     *
8316     * @return true if the view has transient state
8317     */
8318    @ViewDebug.ExportedProperty(category = "layout")
8319    public boolean hasTransientState() {
8320        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
8321    }
8322
8323    /**
8324     * Set whether this view is currently tracking transient state that the
8325     * framework should attempt to preserve when possible. This flag is reference counted,
8326     * so every call to setHasTransientState(true) should be paired with a later call
8327     * to setHasTransientState(false).
8328     *
8329     * <p>A view with transient state cannot be trivially rebound from an external
8330     * data source, such as an adapter binding item views in a list. This may be
8331     * because the view is performing an animation, tracking user selection
8332     * of content, or similar.</p>
8333     *
8334     * @param hasTransientState true if this view has transient state
8335     */
8336    public void setHasTransientState(boolean hasTransientState) {
8337        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
8338                mTransientStateCount - 1;
8339        if (mTransientStateCount < 0) {
8340            mTransientStateCount = 0;
8341            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
8342                    "unmatched pair of setHasTransientState calls");
8343        } else if ((hasTransientState && mTransientStateCount == 1) ||
8344                (!hasTransientState && mTransientStateCount == 0)) {
8345            // update flag if we've just incremented up from 0 or decremented down to 0
8346            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
8347                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
8348            if (mParent != null) {
8349                try {
8350                    mParent.childHasTransientStateChanged(this, hasTransientState);
8351                } catch (AbstractMethodError e) {
8352                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8353                            " does not fully implement ViewParent", e);
8354                }
8355            }
8356        }
8357    }
8358
8359    /**
8360     * Returns true if this view is currently attached to a window.
8361     */
8362    public boolean isAttachedToWindow() {
8363        return mAttachInfo != null;
8364    }
8365
8366    /**
8367     * Returns true if this view has been through at least one layout since it
8368     * was last attached to or detached from a window.
8369     */
8370    public boolean isLaidOut() {
8371        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
8372    }
8373
8374    /**
8375     * If this view doesn't do any drawing on its own, set this flag to
8376     * allow further optimizations. By default, this flag is not set on
8377     * View, but could be set on some View subclasses such as ViewGroup.
8378     *
8379     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8380     * you should clear this flag.
8381     *
8382     * @param willNotDraw whether or not this View draw on its own
8383     */
8384    public void setWillNotDraw(boolean willNotDraw) {
8385        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8386    }
8387
8388    /**
8389     * Returns whether or not this View draws on its own.
8390     *
8391     * @return true if this view has nothing to draw, false otherwise
8392     */
8393    @ViewDebug.ExportedProperty(category = "drawing")
8394    public boolean willNotDraw() {
8395        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8396    }
8397
8398    /**
8399     * When a View's drawing cache is enabled, drawing is redirected to an
8400     * offscreen bitmap. Some views, like an ImageView, must be able to
8401     * bypass this mechanism if they already draw a single bitmap, to avoid
8402     * unnecessary usage of the memory.
8403     *
8404     * @param willNotCacheDrawing true if this view does not cache its
8405     *        drawing, false otherwise
8406     */
8407    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8408        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8409    }
8410
8411    /**
8412     * Returns whether or not this View can cache its drawing or not.
8413     *
8414     * @return true if this view does not cache its drawing, false otherwise
8415     */
8416    @ViewDebug.ExportedProperty(category = "drawing")
8417    public boolean willNotCacheDrawing() {
8418        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8419    }
8420
8421    /**
8422     * Indicates whether this view reacts to click events or not.
8423     *
8424     * @return true if the view is clickable, false otherwise
8425     *
8426     * @see #setClickable(boolean)
8427     * @attr ref android.R.styleable#View_clickable
8428     */
8429    @ViewDebug.ExportedProperty
8430    public boolean isClickable() {
8431        return (mViewFlags & CLICKABLE) == CLICKABLE;
8432    }
8433
8434    /**
8435     * Enables or disables click events for this view. When a view
8436     * is clickable it will change its state to "pressed" on every click.
8437     * Subclasses should set the view clickable to visually react to
8438     * user's clicks.
8439     *
8440     * @param clickable true to make the view clickable, false otherwise
8441     *
8442     * @see #isClickable()
8443     * @attr ref android.R.styleable#View_clickable
8444     */
8445    public void setClickable(boolean clickable) {
8446        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8447    }
8448
8449    /**
8450     * Indicates whether this view reacts to long click events or not.
8451     *
8452     * @return true if the view is long clickable, false otherwise
8453     *
8454     * @see #setLongClickable(boolean)
8455     * @attr ref android.R.styleable#View_longClickable
8456     */
8457    public boolean isLongClickable() {
8458        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8459    }
8460
8461    /**
8462     * Enables or disables long click events for this view. When a view is long
8463     * clickable it reacts to the user holding down the button for a longer
8464     * duration than a tap. This event can either launch the listener or a
8465     * context menu.
8466     *
8467     * @param longClickable true to make the view long clickable, false otherwise
8468     * @see #isLongClickable()
8469     * @attr ref android.R.styleable#View_longClickable
8470     */
8471    public void setLongClickable(boolean longClickable) {
8472        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8473    }
8474
8475    /**
8476     * Indicates whether this view reacts to context clicks or not.
8477     *
8478     * @return true if the view is context clickable, false otherwise
8479     * @see #setContextClickable(boolean)
8480     * @attr ref android.R.styleable#View_contextClickable
8481     */
8482    public boolean isContextClickable() {
8483        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8484    }
8485
8486    /**
8487     * Enables or disables context clicking for this view. This event can launch the listener.
8488     *
8489     * @param contextClickable true to make the view react to a context click, false otherwise
8490     * @see #isContextClickable()
8491     * @attr ref android.R.styleable#View_contextClickable
8492     */
8493    public void setContextClickable(boolean contextClickable) {
8494        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8495    }
8496
8497    /**
8498     * Sets the pressed state for this view and provides a touch coordinate for
8499     * animation hinting.
8500     *
8501     * @param pressed Pass true to set the View's internal state to "pressed",
8502     *            or false to reverts the View's internal state from a
8503     *            previously set "pressed" state.
8504     * @param x The x coordinate of the touch that caused the press
8505     * @param y The y coordinate of the touch that caused the press
8506     */
8507    private void setPressed(boolean pressed, float x, float y) {
8508        if (pressed) {
8509            drawableHotspotChanged(x, y);
8510        }
8511
8512        setPressed(pressed);
8513    }
8514
8515    /**
8516     * Sets the pressed state for this view.
8517     *
8518     * @see #isClickable()
8519     * @see #setClickable(boolean)
8520     *
8521     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8522     *        the View's internal state from a previously set "pressed" state.
8523     */
8524    public void setPressed(boolean pressed) {
8525        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8526
8527        if (pressed) {
8528            mPrivateFlags |= PFLAG_PRESSED;
8529        } else {
8530            mPrivateFlags &= ~PFLAG_PRESSED;
8531        }
8532
8533        if (needsRefresh) {
8534            refreshDrawableState();
8535        }
8536        dispatchSetPressed(pressed);
8537    }
8538
8539    /**
8540     * Dispatch setPressed to all of this View's children.
8541     *
8542     * @see #setPressed(boolean)
8543     *
8544     * @param pressed The new pressed state
8545     */
8546    protected void dispatchSetPressed(boolean pressed) {
8547    }
8548
8549    /**
8550     * Indicates whether the view is currently in pressed state. Unless
8551     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8552     * the pressed state.
8553     *
8554     * @see #setPressed(boolean)
8555     * @see #isClickable()
8556     * @see #setClickable(boolean)
8557     *
8558     * @return true if the view is currently pressed, false otherwise
8559     */
8560    @ViewDebug.ExportedProperty
8561    public boolean isPressed() {
8562        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8563    }
8564
8565    /**
8566     * @hide
8567     * Indicates whether this view will participate in data collection through
8568     * {@link ViewStructure}.  If true, it will not provide any data
8569     * for itself or its children.  If false, the normal data collection will be allowed.
8570     *
8571     * @return Returns false if assist data collection is not blocked, else true.
8572     *
8573     * @see #setAssistBlocked(boolean)
8574     * @attr ref android.R.styleable#View_assistBlocked
8575     */
8576    public boolean isAssistBlocked() {
8577        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8578    }
8579
8580    /**
8581     * @hide
8582     * Controls whether assist data collection from this view and its children is enabled
8583     * (that is, whether {@link #onProvideStructure} and
8584     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8585     * allowing normal assist collection.  Setting this to false will disable assist collection.
8586     *
8587     * @param enabled Set to true to <em>disable</em> assist data collection, or false
8588     * (the default) to allow it.
8589     *
8590     * @see #isAssistBlocked()
8591     * @see #onProvideStructure
8592     * @see #onProvideVirtualStructure
8593     * @attr ref android.R.styleable#View_assistBlocked
8594     */
8595    public void setAssistBlocked(boolean enabled) {
8596        if (enabled) {
8597            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8598        } else {
8599            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8600        }
8601    }
8602
8603    /**
8604     * Indicates whether this view will save its state (that is,
8605     * whether its {@link #onSaveInstanceState} method will be called).
8606     *
8607     * @return Returns true if the view state saving is enabled, else false.
8608     *
8609     * @see #setSaveEnabled(boolean)
8610     * @attr ref android.R.styleable#View_saveEnabled
8611     */
8612    public boolean isSaveEnabled() {
8613        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8614    }
8615
8616    /**
8617     * Controls whether the saving of this view's state is
8618     * enabled (that is, whether its {@link #onSaveInstanceState} method
8619     * will be called).  Note that even if freezing is enabled, the
8620     * view still must have an id assigned to it (via {@link #setId(int)})
8621     * for its state to be saved.  This flag can only disable the
8622     * saving of this view; any child views may still have their state saved.
8623     *
8624     * @param enabled Set to false to <em>disable</em> state saving, or true
8625     * (the default) to allow it.
8626     *
8627     * @see #isSaveEnabled()
8628     * @see #setId(int)
8629     * @see #onSaveInstanceState()
8630     * @attr ref android.R.styleable#View_saveEnabled
8631     */
8632    public void setSaveEnabled(boolean enabled) {
8633        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8634    }
8635
8636    /**
8637     * Gets whether the framework should discard touches when the view's
8638     * window is obscured by another visible window.
8639     * Refer to the {@link View} security documentation for more details.
8640     *
8641     * @return True if touch filtering is enabled.
8642     *
8643     * @see #setFilterTouchesWhenObscured(boolean)
8644     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8645     */
8646    @ViewDebug.ExportedProperty
8647    public boolean getFilterTouchesWhenObscured() {
8648        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8649    }
8650
8651    /**
8652     * Sets whether the framework should discard touches when the view's
8653     * window is obscured by another visible window.
8654     * Refer to the {@link View} security documentation for more details.
8655     *
8656     * @param enabled True if touch filtering should be enabled.
8657     *
8658     * @see #getFilterTouchesWhenObscured
8659     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8660     */
8661    public void setFilterTouchesWhenObscured(boolean enabled) {
8662        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8663                FILTER_TOUCHES_WHEN_OBSCURED);
8664    }
8665
8666    /**
8667     * Indicates whether the entire hierarchy under this view will save its
8668     * state when a state saving traversal occurs from its parent.  The default
8669     * is true; if false, these views will not be saved unless
8670     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8671     *
8672     * @return Returns true if the view state saving from parent is enabled, else false.
8673     *
8674     * @see #setSaveFromParentEnabled(boolean)
8675     */
8676    public boolean isSaveFromParentEnabled() {
8677        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8678    }
8679
8680    /**
8681     * Controls whether the entire hierarchy under this view will save its
8682     * state when a state saving traversal occurs from its parent.  The default
8683     * is true; if false, these views will not be saved unless
8684     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8685     *
8686     * @param enabled Set to false to <em>disable</em> state saving, or true
8687     * (the default) to allow it.
8688     *
8689     * @see #isSaveFromParentEnabled()
8690     * @see #setId(int)
8691     * @see #onSaveInstanceState()
8692     */
8693    public void setSaveFromParentEnabled(boolean enabled) {
8694        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8695    }
8696
8697
8698    /**
8699     * Returns whether this View is able to take focus.
8700     *
8701     * @return True if this view can take focus, or false otherwise.
8702     * @attr ref android.R.styleable#View_focusable
8703     */
8704    @ViewDebug.ExportedProperty(category = "focus")
8705    public final boolean isFocusable() {
8706        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8707    }
8708
8709    /**
8710     * When a view is focusable, it may not want to take focus when in touch mode.
8711     * For example, a button would like focus when the user is navigating via a D-pad
8712     * so that the user can click on it, but once the user starts touching the screen,
8713     * the button shouldn't take focus
8714     * @return Whether the view is focusable in touch mode.
8715     * @attr ref android.R.styleable#View_focusableInTouchMode
8716     */
8717    @ViewDebug.ExportedProperty
8718    public final boolean isFocusableInTouchMode() {
8719        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8720    }
8721
8722    /**
8723     * Find the nearest view in the specified direction that can take focus.
8724     * This does not actually give focus to that view.
8725     *
8726     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8727     *
8728     * @return The nearest focusable in the specified direction, or null if none
8729     *         can be found.
8730     */
8731    public View focusSearch(@FocusRealDirection int direction) {
8732        if (mParent != null) {
8733            return mParent.focusSearch(this, direction);
8734        } else {
8735            return null;
8736        }
8737    }
8738
8739    /**
8740     * This method is the last chance for the focused view and its ancestors to
8741     * respond to an arrow key. This is called when the focused view did not
8742     * consume the key internally, nor could the view system find a new view in
8743     * the requested direction to give focus to.
8744     *
8745     * @param focused The currently focused view.
8746     * @param direction The direction focus wants to move. One of FOCUS_UP,
8747     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8748     * @return True if the this view consumed this unhandled move.
8749     */
8750    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8751        return false;
8752    }
8753
8754    /**
8755     * If a user manually specified the next view id for a particular direction,
8756     * use the root to look up the view.
8757     * @param root The root view of the hierarchy containing this view.
8758     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8759     * or FOCUS_BACKWARD.
8760     * @return The user specified next view, or null if there is none.
8761     */
8762    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8763        switch (direction) {
8764            case FOCUS_LEFT:
8765                if (mNextFocusLeftId == View.NO_ID) return null;
8766                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8767            case FOCUS_RIGHT:
8768                if (mNextFocusRightId == View.NO_ID) return null;
8769                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8770            case FOCUS_UP:
8771                if (mNextFocusUpId == View.NO_ID) return null;
8772                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8773            case FOCUS_DOWN:
8774                if (mNextFocusDownId == View.NO_ID) return null;
8775                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8776            case FOCUS_FORWARD:
8777                if (mNextFocusForwardId == View.NO_ID) return null;
8778                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8779            case FOCUS_BACKWARD: {
8780                if (mID == View.NO_ID) return null;
8781                final int id = mID;
8782                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8783                    @Override
8784                    public boolean apply(View t) {
8785                        return t.mNextFocusForwardId == id;
8786                    }
8787                });
8788            }
8789        }
8790        return null;
8791    }
8792
8793    private View findViewInsideOutShouldExist(View root, int id) {
8794        if (mMatchIdPredicate == null) {
8795            mMatchIdPredicate = new MatchIdPredicate();
8796        }
8797        mMatchIdPredicate.mId = id;
8798        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8799        if (result == null) {
8800            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8801        }
8802        return result;
8803    }
8804
8805    /**
8806     * Find and return all focusable views that are descendants of this view,
8807     * possibly including this view if it is focusable itself.
8808     *
8809     * @param direction The direction of the focus
8810     * @return A list of focusable views
8811     */
8812    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8813        ArrayList<View> result = new ArrayList<View>(24);
8814        addFocusables(result, direction);
8815        return result;
8816    }
8817
8818    /**
8819     * Add any focusable views that are descendants of this view (possibly
8820     * including this view if it is focusable itself) to views.  If we are in touch mode,
8821     * only add views that are also focusable in touch mode.
8822     *
8823     * @param views Focusable views found so far
8824     * @param direction The direction of the focus
8825     */
8826    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8827        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
8828    }
8829
8830    /**
8831     * Adds any focusable views that are descendants of this view (possibly
8832     * including this view if it is focusable itself) to views. This method
8833     * adds all focusable views regardless if we are in touch mode or
8834     * only views focusable in touch mode if we are in touch mode or
8835     * only views that can take accessibility focus if accessibility is enabled
8836     * depending on the focusable mode parameter.
8837     *
8838     * @param views Focusable views found so far or null if all we are interested is
8839     *        the number of focusables.
8840     * @param direction The direction of the focus.
8841     * @param focusableMode The type of focusables to be added.
8842     *
8843     * @see #FOCUSABLES_ALL
8844     * @see #FOCUSABLES_TOUCH_MODE
8845     */
8846    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8847            @FocusableMode int focusableMode) {
8848        if (views == null) {
8849            return;
8850        }
8851        if (!isFocusable()) {
8852            return;
8853        }
8854        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8855                && !isFocusableInTouchMode()) {
8856            return;
8857        }
8858        views.add(this);
8859    }
8860
8861    /**
8862     * Finds the Views that contain given text. The containment is case insensitive.
8863     * The search is performed by either the text that the View renders or the content
8864     * description that describes the view for accessibility purposes and the view does
8865     * not render or both. Clients can specify how the search is to be performed via
8866     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8867     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8868     *
8869     * @param outViews The output list of matching Views.
8870     * @param searched The text to match against.
8871     *
8872     * @see #FIND_VIEWS_WITH_TEXT
8873     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8874     * @see #setContentDescription(CharSequence)
8875     */
8876    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8877            @FindViewFlags int flags) {
8878        if (getAccessibilityNodeProvider() != null) {
8879            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8880                outViews.add(this);
8881            }
8882        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8883                && (searched != null && searched.length() > 0)
8884                && (mContentDescription != null && mContentDescription.length() > 0)) {
8885            String searchedLowerCase = searched.toString().toLowerCase();
8886            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8887            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8888                outViews.add(this);
8889            }
8890        }
8891    }
8892
8893    /**
8894     * Find and return all touchable views that are descendants of this view,
8895     * possibly including this view if it is touchable itself.
8896     *
8897     * @return A list of touchable views
8898     */
8899    public ArrayList<View> getTouchables() {
8900        ArrayList<View> result = new ArrayList<View>();
8901        addTouchables(result);
8902        return result;
8903    }
8904
8905    /**
8906     * Add any touchable views that are descendants of this view (possibly
8907     * including this view if it is touchable itself) to views.
8908     *
8909     * @param views Touchable views found so far
8910     */
8911    public void addTouchables(ArrayList<View> views) {
8912        final int viewFlags = mViewFlags;
8913
8914        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8915                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8916                && (viewFlags & ENABLED_MASK) == ENABLED) {
8917            views.add(this);
8918        }
8919    }
8920
8921    /**
8922     * Returns whether this View is accessibility focused.
8923     *
8924     * @return True if this View is accessibility focused.
8925     */
8926    public boolean isAccessibilityFocused() {
8927        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8928    }
8929
8930    /**
8931     * Call this to try to give accessibility focus to this view.
8932     *
8933     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8934     * returns false or the view is no visible or the view already has accessibility
8935     * focus.
8936     *
8937     * See also {@link #focusSearch(int)}, which is what you call to say that you
8938     * have focus, and you want your parent to look for the next one.
8939     *
8940     * @return Whether this view actually took accessibility focus.
8941     *
8942     * @hide
8943     */
8944    public boolean requestAccessibilityFocus() {
8945        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8946        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8947            return false;
8948        }
8949        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8950            return false;
8951        }
8952        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8953            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8954            ViewRootImpl viewRootImpl = getViewRootImpl();
8955            if (viewRootImpl != null) {
8956                viewRootImpl.setAccessibilityFocus(this, null);
8957            }
8958            invalidate();
8959            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8960            return true;
8961        }
8962        return false;
8963    }
8964
8965    /**
8966     * Call this to try to clear accessibility focus of this view.
8967     *
8968     * See also {@link #focusSearch(int)}, which is what you call to say that you
8969     * have focus, and you want your parent to look for the next one.
8970     *
8971     * @hide
8972     */
8973    public void clearAccessibilityFocus() {
8974        clearAccessibilityFocusNoCallbacks(0);
8975
8976        // Clear the global reference of accessibility focus if this view or
8977        // any of its descendants had accessibility focus. This will NOT send
8978        // an event or update internal state if focus is cleared from a
8979        // descendant view, which may leave views in inconsistent states.
8980        final ViewRootImpl viewRootImpl = getViewRootImpl();
8981        if (viewRootImpl != null) {
8982            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8983            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8984                viewRootImpl.setAccessibilityFocus(null, null);
8985            }
8986        }
8987    }
8988
8989    private void sendAccessibilityHoverEvent(int eventType) {
8990        // Since we are not delivering to a client accessibility events from not
8991        // important views (unless the clinet request that) we need to fire the
8992        // event from the deepest view exposed to the client. As a consequence if
8993        // the user crosses a not exposed view the client will see enter and exit
8994        // of the exposed predecessor followed by and enter and exit of that same
8995        // predecessor when entering and exiting the not exposed descendant. This
8996        // is fine since the client has a clear idea which view is hovered at the
8997        // price of a couple more events being sent. This is a simple and
8998        // working solution.
8999        View source = this;
9000        while (true) {
9001            if (source.includeForAccessibility()) {
9002                source.sendAccessibilityEvent(eventType);
9003                return;
9004            }
9005            ViewParent parent = source.getParent();
9006            if (parent instanceof View) {
9007                source = (View) parent;
9008            } else {
9009                return;
9010            }
9011        }
9012    }
9013
9014    /**
9015     * Clears accessibility focus without calling any callback methods
9016     * normally invoked in {@link #clearAccessibilityFocus()}. This method
9017     * is used separately from that one for clearing accessibility focus when
9018     * giving this focus to another view.
9019     *
9020     * @param action The action, if any, that led to focus being cleared. Set to
9021     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
9022     * the window.
9023     */
9024    void clearAccessibilityFocusNoCallbacks(int action) {
9025        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
9026            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
9027            invalidate();
9028            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9029                AccessibilityEvent event = AccessibilityEvent.obtain(
9030                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
9031                event.setAction(action);
9032                if (mAccessibilityDelegate != null) {
9033                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
9034                } else {
9035                    sendAccessibilityEventUnchecked(event);
9036                }
9037            }
9038        }
9039    }
9040
9041    /**
9042     * Call this to try to give focus to a specific view or to one of its
9043     * descendants.
9044     *
9045     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9046     * false), or if it is focusable and it is not focusable in touch mode
9047     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9048     *
9049     * See also {@link #focusSearch(int)}, which is what you call to say that you
9050     * have focus, and you want your parent to look for the next one.
9051     *
9052     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
9053     * {@link #FOCUS_DOWN} and <code>null</code>.
9054     *
9055     * @return Whether this view or one of its descendants actually took focus.
9056     */
9057    public final boolean requestFocus() {
9058        return requestFocus(View.FOCUS_DOWN);
9059    }
9060
9061    /**
9062     * Call this to try to give focus to a specific view or to one of its
9063     * descendants and give it a hint about what direction focus is heading.
9064     *
9065     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9066     * false), or if it is focusable and it is not focusable in touch mode
9067     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9068     *
9069     * See also {@link #focusSearch(int)}, which is what you call to say that you
9070     * have focus, and you want your parent to look for the next one.
9071     *
9072     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
9073     * <code>null</code> set for the previously focused rectangle.
9074     *
9075     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9076     * @return Whether this view or one of its descendants actually took focus.
9077     */
9078    public final boolean requestFocus(int direction) {
9079        return requestFocus(direction, null);
9080    }
9081
9082    /**
9083     * Call this to try to give focus to a specific view or to one of its descendants
9084     * and give it hints about the direction and a specific rectangle that the focus
9085     * is coming from.  The rectangle can help give larger views a finer grained hint
9086     * about where focus is coming from, and therefore, where to show selection, or
9087     * forward focus change internally.
9088     *
9089     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9090     * false), or if it is focusable and it is not focusable in touch mode
9091     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9092     *
9093     * A View will not take focus if it is not visible.
9094     *
9095     * A View will not take focus if one of its parents has
9096     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
9097     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
9098     *
9099     * See also {@link #focusSearch(int)}, which is what you call to say that you
9100     * have focus, and you want your parent to look for the next one.
9101     *
9102     * You may wish to override this method if your custom {@link View} has an internal
9103     * {@link View} that it wishes to forward the request to.
9104     *
9105     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9106     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
9107     *        to give a finer grained hint about where focus is coming from.  May be null
9108     *        if there is no hint.
9109     * @return Whether this view or one of its descendants actually took focus.
9110     */
9111    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
9112        return requestFocusNoSearch(direction, previouslyFocusedRect);
9113    }
9114
9115    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
9116        // need to be focusable
9117        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
9118                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9119            return false;
9120        }
9121
9122        // need to be focusable in touch mode if in touch mode
9123        if (isInTouchMode() &&
9124            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
9125               return false;
9126        }
9127
9128        // need to not have any parents blocking us
9129        if (hasAncestorThatBlocksDescendantFocus()) {
9130            return false;
9131        }
9132
9133        handleFocusGainInternal(direction, previouslyFocusedRect);
9134        return true;
9135    }
9136
9137    /**
9138     * Call this to try to give focus to a specific view or to one of its descendants. This is a
9139     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
9140     * touch mode to request focus when they are touched.
9141     *
9142     * @return Whether this view or one of its descendants actually took focus.
9143     *
9144     * @see #isInTouchMode()
9145     *
9146     */
9147    public final boolean requestFocusFromTouch() {
9148        // Leave touch mode if we need to
9149        if (isInTouchMode()) {
9150            ViewRootImpl viewRoot = getViewRootImpl();
9151            if (viewRoot != null) {
9152                viewRoot.ensureTouchMode(false);
9153            }
9154        }
9155        return requestFocus(View.FOCUS_DOWN);
9156    }
9157
9158    /**
9159     * @return Whether any ancestor of this view blocks descendant focus.
9160     */
9161    private boolean hasAncestorThatBlocksDescendantFocus() {
9162        final boolean focusableInTouchMode = isFocusableInTouchMode();
9163        ViewParent ancestor = mParent;
9164        while (ancestor instanceof ViewGroup) {
9165            final ViewGroup vgAncestor = (ViewGroup) ancestor;
9166            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
9167                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
9168                return true;
9169            } else {
9170                ancestor = vgAncestor.getParent();
9171            }
9172        }
9173        return false;
9174    }
9175
9176    /**
9177     * Gets the mode for determining whether this View is important for accessibility
9178     * which is if it fires accessibility events and if it is reported to
9179     * accessibility services that query the screen.
9180     *
9181     * @return The mode for determining whether a View is important for accessibility.
9182     *
9183     * @attr ref android.R.styleable#View_importantForAccessibility
9184     *
9185     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9186     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9187     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9188     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9189     */
9190    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
9191            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
9192            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
9193            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
9194            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
9195                    to = "noHideDescendants")
9196        })
9197    public int getImportantForAccessibility() {
9198        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9199                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9200    }
9201
9202    /**
9203     * Sets the live region mode for this view. This indicates to accessibility
9204     * services whether they should automatically notify the user about changes
9205     * to the view's content description or text, or to the content descriptions
9206     * or text of the view's children (where applicable).
9207     * <p>
9208     * For example, in a login screen with a TextView that displays an "incorrect
9209     * password" notification, that view should be marked as a live region with
9210     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9211     * <p>
9212     * To disable change notifications for this view, use
9213     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
9214     * mode for most views.
9215     * <p>
9216     * To indicate that the user should be notified of changes, use
9217     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9218     * <p>
9219     * If the view's changes should interrupt ongoing speech and notify the user
9220     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
9221     *
9222     * @param mode The live region mode for this view, one of:
9223     *        <ul>
9224     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
9225     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
9226     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
9227     *        </ul>
9228     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9229     */
9230    public void setAccessibilityLiveRegion(int mode) {
9231        if (mode != getAccessibilityLiveRegion()) {
9232            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9233            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
9234                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9235            notifyViewAccessibilityStateChangedIfNeeded(
9236                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9237        }
9238    }
9239
9240    /**
9241     * Gets the live region mode for this View.
9242     *
9243     * @return The live region mode for the view.
9244     *
9245     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9246     *
9247     * @see #setAccessibilityLiveRegion(int)
9248     */
9249    public int getAccessibilityLiveRegion() {
9250        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
9251                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
9252    }
9253
9254    /**
9255     * Sets how to determine whether this view is important for accessibility
9256     * which is if it fires accessibility events and if it is reported to
9257     * accessibility services that query the screen.
9258     *
9259     * @param mode How to determine whether this view is important for accessibility.
9260     *
9261     * @attr ref android.R.styleable#View_importantForAccessibility
9262     *
9263     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9264     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9265     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9266     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9267     */
9268    public void setImportantForAccessibility(int mode) {
9269        final int oldMode = getImportantForAccessibility();
9270        if (mode != oldMode) {
9271            final boolean hideDescendants =
9272                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
9273
9274            // If this node or its descendants are no longer important, try to
9275            // clear accessibility focus.
9276            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
9277                final View focusHost = findAccessibilityFocusHost(hideDescendants);
9278                if (focusHost != null) {
9279                    focusHost.clearAccessibilityFocus();
9280                }
9281            }
9282
9283            // If we're moving between AUTO and another state, we might not need
9284            // to send a subtree changed notification. We'll store the computed
9285            // importance, since we'll need to check it later to make sure.
9286            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
9287                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
9288            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
9289            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9290            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
9291                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9292            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
9293                notifySubtreeAccessibilityStateChangedIfNeeded();
9294            } else {
9295                notifyViewAccessibilityStateChangedIfNeeded(
9296                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9297            }
9298        }
9299    }
9300
9301    /**
9302     * Returns the view within this view's hierarchy that is hosting
9303     * accessibility focus.
9304     *
9305     * @param searchDescendants whether to search for focus in descendant views
9306     * @return the view hosting accessibility focus, or {@code null}
9307     */
9308    private View findAccessibilityFocusHost(boolean searchDescendants) {
9309        if (isAccessibilityFocusedViewOrHost()) {
9310            return this;
9311        }
9312
9313        if (searchDescendants) {
9314            final ViewRootImpl viewRoot = getViewRootImpl();
9315            if (viewRoot != null) {
9316                final View focusHost = viewRoot.getAccessibilityFocusedHost();
9317                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9318                    return focusHost;
9319                }
9320            }
9321        }
9322
9323        return null;
9324    }
9325
9326    /**
9327     * Computes whether this view should be exposed for accessibility. In
9328     * general, views that are interactive or provide information are exposed
9329     * while views that serve only as containers are hidden.
9330     * <p>
9331     * If an ancestor of this view has importance
9332     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
9333     * returns <code>false</code>.
9334     * <p>
9335     * Otherwise, the value is computed according to the view's
9336     * {@link #getImportantForAccessibility()} value:
9337     * <ol>
9338     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
9339     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
9340     * </code>
9341     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
9342     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
9343     * view satisfies any of the following:
9344     * <ul>
9345     * <li>Is actionable, e.g. {@link #isClickable()},
9346     * {@link #isLongClickable()}, or {@link #isFocusable()}
9347     * <li>Has an {@link AccessibilityDelegate}
9348     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
9349     * {@link OnKeyListener}, etc.
9350     * <li>Is an accessibility live region, e.g.
9351     * {@link #getAccessibilityLiveRegion()} is not
9352     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
9353     * </ul>
9354     * </ol>
9355     *
9356     * @return Whether the view is exposed for accessibility.
9357     * @see #setImportantForAccessibility(int)
9358     * @see #getImportantForAccessibility()
9359     */
9360    public boolean isImportantForAccessibility() {
9361        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9362                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9363        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
9364                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9365            return false;
9366        }
9367
9368        // Check parent mode to ensure we're not hidden.
9369        ViewParent parent = mParent;
9370        while (parent instanceof View) {
9371            if (((View) parent).getImportantForAccessibility()
9372                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9373                return false;
9374            }
9375            parent = parent.getParent();
9376        }
9377
9378        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
9379                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
9380                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
9381    }
9382
9383    /**
9384     * Gets the parent for accessibility purposes. Note that the parent for
9385     * accessibility is not necessary the immediate parent. It is the first
9386     * predecessor that is important for accessibility.
9387     *
9388     * @return The parent for accessibility purposes.
9389     */
9390    public ViewParent getParentForAccessibility() {
9391        if (mParent instanceof View) {
9392            View parentView = (View) mParent;
9393            if (parentView.includeForAccessibility()) {
9394                return mParent;
9395            } else {
9396                return mParent.getParentForAccessibility();
9397            }
9398        }
9399        return null;
9400    }
9401
9402    /**
9403     * Adds the children of this View relevant for accessibility to the given list
9404     * as output. Since some Views are not important for accessibility the added
9405     * child views are not necessarily direct children of this view, rather they are
9406     * the first level of descendants important for accessibility.
9407     *
9408     * @param outChildren The output list that will receive children for accessibility.
9409     */
9410    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
9411
9412    }
9413
9414    /**
9415     * Whether to regard this view for accessibility. A view is regarded for
9416     * accessibility if it is important for accessibility or the querying
9417     * accessibility service has explicitly requested that view not
9418     * important for accessibility are regarded.
9419     *
9420     * @return Whether to regard the view for accessibility.
9421     *
9422     * @hide
9423     */
9424    public boolean includeForAccessibility() {
9425        if (mAttachInfo != null) {
9426            return (mAttachInfo.mAccessibilityFetchFlags
9427                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
9428                    || isImportantForAccessibility();
9429        }
9430        return false;
9431    }
9432
9433    /**
9434     * Returns whether the View is considered actionable from
9435     * accessibility perspective. Such view are important for
9436     * accessibility.
9437     *
9438     * @return True if the view is actionable for accessibility.
9439     *
9440     * @hide
9441     */
9442    public boolean isActionableForAccessibility() {
9443        return (isClickable() || isLongClickable() || isFocusable());
9444    }
9445
9446    /**
9447     * Returns whether the View has registered callbacks which makes it
9448     * important for accessibility.
9449     *
9450     * @return True if the view is actionable for accessibility.
9451     */
9452    private boolean hasListenersForAccessibility() {
9453        ListenerInfo info = getListenerInfo();
9454        return mTouchDelegate != null || info.mOnKeyListener != null
9455                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
9456                || info.mOnHoverListener != null || info.mOnDragListener != null;
9457    }
9458
9459    /**
9460     * Notifies that the accessibility state of this view changed. The change
9461     * is local to this view and does not represent structural changes such
9462     * as children and parent. For example, the view became focusable. The
9463     * notification is at at most once every
9464     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9465     * to avoid unnecessary load to the system. Also once a view has a pending
9466     * notification this method is a NOP until the notification has been sent.
9467     *
9468     * @hide
9469     */
9470    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
9471        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9472            return;
9473        }
9474        if (mSendViewStateChangedAccessibilityEvent == null) {
9475            mSendViewStateChangedAccessibilityEvent =
9476                    new SendViewStateChangedAccessibilityEvent();
9477        }
9478        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9479    }
9480
9481    /**
9482     * Notifies that the accessibility state of this view changed. The change
9483     * is *not* local to this view and does represent structural changes such
9484     * as children and parent. For example, the view size changed. The
9485     * notification is at at most once every
9486     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9487     * to avoid unnecessary load to the system. Also once a view has a pending
9488     * notification this method is a NOP until the notification has been sent.
9489     *
9490     * @hide
9491     */
9492    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9493        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9494            return;
9495        }
9496        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9497            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9498            if (mParent != null) {
9499                try {
9500                    mParent.notifySubtreeAccessibilityStateChanged(
9501                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9502                } catch (AbstractMethodError e) {
9503                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9504                            " does not fully implement ViewParent", e);
9505                }
9506            }
9507        }
9508    }
9509
9510    /**
9511     * Change the visibility of the View without triggering any other changes. This is
9512     * important for transitions, where visibility changes should not adjust focus or
9513     * trigger a new layout. This is only used when the visibility has already been changed
9514     * and we need a transient value during an animation. When the animation completes,
9515     * the original visibility value is always restored.
9516     *
9517     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9518     * @hide
9519     */
9520    public void setTransitionVisibility(@Visibility int visibility) {
9521        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9522    }
9523
9524    /**
9525     * Reset the flag indicating the accessibility state of the subtree rooted
9526     * at this view changed.
9527     */
9528    void resetSubtreeAccessibilityStateChanged() {
9529        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9530    }
9531
9532    /**
9533     * Report an accessibility action to this view's parents for delegated processing.
9534     *
9535     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9536     * call this method to delegate an accessibility action to a supporting parent. If the parent
9537     * returns true from its
9538     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9539     * method this method will return true to signify that the action was consumed.</p>
9540     *
9541     * <p>This method is useful for implementing nested scrolling child views. If
9542     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9543     * a custom view implementation may invoke this method to allow a parent to consume the
9544     * scroll first. If this method returns true the custom view should skip its own scrolling
9545     * behavior.</p>
9546     *
9547     * @param action Accessibility action to delegate
9548     * @param arguments Optional action arguments
9549     * @return true if the action was consumed by a parent
9550     */
9551    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9552        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9553            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9554                return true;
9555            }
9556        }
9557        return false;
9558    }
9559
9560    /**
9561     * Performs the specified accessibility action on the view. For
9562     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9563     * <p>
9564     * If an {@link AccessibilityDelegate} has been specified via calling
9565     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9566     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9567     * is responsible for handling this call.
9568     * </p>
9569     *
9570     * <p>The default implementation will delegate
9571     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9572     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9573     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9574     *
9575     * @param action The action to perform.
9576     * @param arguments Optional action arguments.
9577     * @return Whether the action was performed.
9578     */
9579    public boolean performAccessibilityAction(int action, Bundle arguments) {
9580      if (mAccessibilityDelegate != null) {
9581          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9582      } else {
9583          return performAccessibilityActionInternal(action, arguments);
9584      }
9585    }
9586
9587   /**
9588    * @see #performAccessibilityAction(int, Bundle)
9589    *
9590    * Note: Called from the default {@link AccessibilityDelegate}.
9591    *
9592    * @hide
9593    */
9594    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9595        if (isNestedScrollingEnabled()
9596                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9597                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9598                || action == R.id.accessibilityActionScrollUp
9599                || action == R.id.accessibilityActionScrollLeft
9600                || action == R.id.accessibilityActionScrollDown
9601                || action == R.id.accessibilityActionScrollRight)) {
9602            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9603                return true;
9604            }
9605        }
9606
9607        switch (action) {
9608            case AccessibilityNodeInfo.ACTION_CLICK: {
9609                if (isClickable()) {
9610                    performClick();
9611                    return true;
9612                }
9613            } break;
9614            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9615                if (isLongClickable()) {
9616                    performLongClick();
9617                    return true;
9618                }
9619            } break;
9620            case AccessibilityNodeInfo.ACTION_FOCUS: {
9621                if (!hasFocus()) {
9622                    // Get out of touch mode since accessibility
9623                    // wants to move focus around.
9624                    getViewRootImpl().ensureTouchMode(false);
9625                    return requestFocus();
9626                }
9627            } break;
9628            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9629                if (hasFocus()) {
9630                    clearFocus();
9631                    return !isFocused();
9632                }
9633            } break;
9634            case AccessibilityNodeInfo.ACTION_SELECT: {
9635                if (!isSelected()) {
9636                    setSelected(true);
9637                    return isSelected();
9638                }
9639            } break;
9640            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9641                if (isSelected()) {
9642                    setSelected(false);
9643                    return !isSelected();
9644                }
9645            } break;
9646            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9647                if (!isAccessibilityFocused()) {
9648                    return requestAccessibilityFocus();
9649                }
9650            } break;
9651            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9652                if (isAccessibilityFocused()) {
9653                    clearAccessibilityFocus();
9654                    return true;
9655                }
9656            } break;
9657            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9658                if (arguments != null) {
9659                    final int granularity = arguments.getInt(
9660                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9661                    final boolean extendSelection = arguments.getBoolean(
9662                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9663                    return traverseAtGranularity(granularity, true, extendSelection);
9664                }
9665            } break;
9666            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9667                if (arguments != null) {
9668                    final int granularity = arguments.getInt(
9669                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9670                    final boolean extendSelection = arguments.getBoolean(
9671                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9672                    return traverseAtGranularity(granularity, false, extendSelection);
9673                }
9674            } break;
9675            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9676                CharSequence text = getIterableTextForAccessibility();
9677                if (text == null) {
9678                    return false;
9679                }
9680                final int start = (arguments != null) ? arguments.getInt(
9681                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9682                final int end = (arguments != null) ? arguments.getInt(
9683                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9684                // Only cursor position can be specified (selection length == 0)
9685                if ((getAccessibilitySelectionStart() != start
9686                        || getAccessibilitySelectionEnd() != end)
9687                        && (start == end)) {
9688                    setAccessibilitySelection(start, end);
9689                    notifyViewAccessibilityStateChangedIfNeeded(
9690                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9691                    return true;
9692                }
9693            } break;
9694            case R.id.accessibilityActionShowOnScreen: {
9695                if (mAttachInfo != null) {
9696                    final Rect r = mAttachInfo.mTmpInvalRect;
9697                    getDrawingRect(r);
9698                    return requestRectangleOnScreen(r, true);
9699                }
9700            } break;
9701            case R.id.accessibilityActionContextClick: {
9702                if (isContextClickable()) {
9703                    performContextClick();
9704                    return true;
9705                }
9706            } break;
9707        }
9708        return false;
9709    }
9710
9711    private boolean traverseAtGranularity(int granularity, boolean forward,
9712            boolean extendSelection) {
9713        CharSequence text = getIterableTextForAccessibility();
9714        if (text == null || text.length() == 0) {
9715            return false;
9716        }
9717        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9718        if (iterator == null) {
9719            return false;
9720        }
9721        int current = getAccessibilitySelectionEnd();
9722        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9723            current = forward ? 0 : text.length();
9724        }
9725        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9726        if (range == null) {
9727            return false;
9728        }
9729        final int segmentStart = range[0];
9730        final int segmentEnd = range[1];
9731        int selectionStart;
9732        int selectionEnd;
9733        if (extendSelection && isAccessibilitySelectionExtendable()) {
9734            selectionStart = getAccessibilitySelectionStart();
9735            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9736                selectionStart = forward ? segmentStart : segmentEnd;
9737            }
9738            selectionEnd = forward ? segmentEnd : segmentStart;
9739        } else {
9740            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9741        }
9742        setAccessibilitySelection(selectionStart, selectionEnd);
9743        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9744                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9745        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9746        return true;
9747    }
9748
9749    /**
9750     * Gets the text reported for accessibility purposes.
9751     *
9752     * @return The accessibility text.
9753     *
9754     * @hide
9755     */
9756    public CharSequence getIterableTextForAccessibility() {
9757        return getContentDescription();
9758    }
9759
9760    /**
9761     * Gets whether accessibility selection can be extended.
9762     *
9763     * @return If selection is extensible.
9764     *
9765     * @hide
9766     */
9767    public boolean isAccessibilitySelectionExtendable() {
9768        return false;
9769    }
9770
9771    /**
9772     * @hide
9773     */
9774    public int getAccessibilitySelectionStart() {
9775        return mAccessibilityCursorPosition;
9776    }
9777
9778    /**
9779     * @hide
9780     */
9781    public int getAccessibilitySelectionEnd() {
9782        return getAccessibilitySelectionStart();
9783    }
9784
9785    /**
9786     * @hide
9787     */
9788    public void setAccessibilitySelection(int start, int end) {
9789        if (start ==  end && end == mAccessibilityCursorPosition) {
9790            return;
9791        }
9792        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9793            mAccessibilityCursorPosition = start;
9794        } else {
9795            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9796        }
9797        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9798    }
9799
9800    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9801            int fromIndex, int toIndex) {
9802        if (mParent == null) {
9803            return;
9804        }
9805        AccessibilityEvent event = AccessibilityEvent.obtain(
9806                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9807        onInitializeAccessibilityEvent(event);
9808        onPopulateAccessibilityEvent(event);
9809        event.setFromIndex(fromIndex);
9810        event.setToIndex(toIndex);
9811        event.setAction(action);
9812        event.setMovementGranularity(granularity);
9813        mParent.requestSendAccessibilityEvent(this, event);
9814    }
9815
9816    /**
9817     * @hide
9818     */
9819    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9820        switch (granularity) {
9821            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9822                CharSequence text = getIterableTextForAccessibility();
9823                if (text != null && text.length() > 0) {
9824                    CharacterTextSegmentIterator iterator =
9825                        CharacterTextSegmentIterator.getInstance(
9826                                mContext.getResources().getConfiguration().locale);
9827                    iterator.initialize(text.toString());
9828                    return iterator;
9829                }
9830            } break;
9831            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9832                CharSequence text = getIterableTextForAccessibility();
9833                if (text != null && text.length() > 0) {
9834                    WordTextSegmentIterator iterator =
9835                        WordTextSegmentIterator.getInstance(
9836                                mContext.getResources().getConfiguration().locale);
9837                    iterator.initialize(text.toString());
9838                    return iterator;
9839                }
9840            } break;
9841            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9842                CharSequence text = getIterableTextForAccessibility();
9843                if (text != null && text.length() > 0) {
9844                    ParagraphTextSegmentIterator iterator =
9845                        ParagraphTextSegmentIterator.getInstance();
9846                    iterator.initialize(text.toString());
9847                    return iterator;
9848                }
9849            } break;
9850        }
9851        return null;
9852    }
9853
9854    /**
9855     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
9856     * and {@link #onFinishTemporaryDetach()}.
9857     */
9858    public final boolean isTemporarilyDetached() {
9859        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
9860    }
9861
9862    /**
9863     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
9864     * a container View.
9865     */
9866    @CallSuper
9867    public void dispatchStartTemporaryDetach() {
9868        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
9869        onStartTemporaryDetach();
9870    }
9871
9872    /**
9873     * This is called when a container is going to temporarily detach a child, with
9874     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9875     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9876     * {@link #onDetachedFromWindow()} when the container is done.
9877     */
9878    public void onStartTemporaryDetach() {
9879        removeUnsetPressCallback();
9880        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9881    }
9882
9883    /**
9884     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
9885     * a container View.
9886     */
9887    @CallSuper
9888    public void dispatchFinishTemporaryDetach() {
9889        onFinishTemporaryDetach();
9890        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
9891    }
9892
9893    /**
9894     * Called after {@link #onStartTemporaryDetach} when the container is done
9895     * changing the view.
9896     */
9897    public void onFinishTemporaryDetach() {
9898    }
9899
9900    /**
9901     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9902     * for this view's window.  Returns null if the view is not currently attached
9903     * to the window.  Normally you will not need to use this directly, but
9904     * just use the standard high-level event callbacks like
9905     * {@link #onKeyDown(int, KeyEvent)}.
9906     */
9907    public KeyEvent.DispatcherState getKeyDispatcherState() {
9908        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9909    }
9910
9911    /**
9912     * Dispatch a key event before it is processed by any input method
9913     * associated with the view hierarchy.  This can be used to intercept
9914     * key events in special situations before the IME consumes them; a
9915     * typical example would be handling the BACK key to update the application's
9916     * UI instead of allowing the IME to see it and close itself.
9917     *
9918     * @param event The key event to be dispatched.
9919     * @return True if the event was handled, false otherwise.
9920     */
9921    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9922        return onKeyPreIme(event.getKeyCode(), event);
9923    }
9924
9925    /**
9926     * Dispatch a key event to the next view on the focus path. This path runs
9927     * from the top of the view tree down to the currently focused view. If this
9928     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9929     * the next node down the focus path. This method also fires any key
9930     * listeners.
9931     *
9932     * @param event The key event to be dispatched.
9933     * @return True if the event was handled, false otherwise.
9934     */
9935    public boolean dispatchKeyEvent(KeyEvent event) {
9936        if (mInputEventConsistencyVerifier != null) {
9937            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9938        }
9939
9940        // Give any attached key listener a first crack at the event.
9941        //noinspection SimplifiableIfStatement
9942        ListenerInfo li = mListenerInfo;
9943        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9944                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9945            return true;
9946        }
9947
9948        if (event.dispatch(this, mAttachInfo != null
9949                ? mAttachInfo.mKeyDispatchState : null, this)) {
9950            return true;
9951        }
9952
9953        if (mInputEventConsistencyVerifier != null) {
9954            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9955        }
9956        return false;
9957    }
9958
9959    /**
9960     * Dispatches a key shortcut event.
9961     *
9962     * @param event The key event to be dispatched.
9963     * @return True if the event was handled by the view, false otherwise.
9964     */
9965    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9966        return onKeyShortcut(event.getKeyCode(), event);
9967    }
9968
9969    /**
9970     * Pass the touch screen motion event down to the target view, or this
9971     * view if it is the target.
9972     *
9973     * @param event The motion event to be dispatched.
9974     * @return True if the event was handled by the view, false otherwise.
9975     */
9976    public boolean dispatchTouchEvent(MotionEvent event) {
9977        // If the event should be handled by accessibility focus first.
9978        if (event.isTargetAccessibilityFocus()) {
9979            // We don't have focus or no virtual descendant has it, do not handle the event.
9980            if (!isAccessibilityFocusedViewOrHost()) {
9981                return false;
9982            }
9983            // We have focus and got the event, then use normal event dispatch.
9984            event.setTargetAccessibilityFocus(false);
9985        }
9986
9987        boolean result = false;
9988
9989        if (mInputEventConsistencyVerifier != null) {
9990            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9991        }
9992
9993        final int actionMasked = event.getActionMasked();
9994        if (actionMasked == MotionEvent.ACTION_DOWN) {
9995            // Defensive cleanup for new gesture
9996            stopNestedScroll();
9997        }
9998
9999        if (onFilterTouchEventForSecurity(event)) {
10000            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
10001                result = true;
10002            }
10003            //noinspection SimplifiableIfStatement
10004            ListenerInfo li = mListenerInfo;
10005            if (li != null && li.mOnTouchListener != null
10006                    && (mViewFlags & ENABLED_MASK) == ENABLED
10007                    && li.mOnTouchListener.onTouch(this, event)) {
10008                result = true;
10009            }
10010
10011            if (!result && onTouchEvent(event)) {
10012                result = true;
10013            }
10014        }
10015
10016        if (!result && mInputEventConsistencyVerifier != null) {
10017            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10018        }
10019
10020        // Clean up after nested scrolls if this is the end of a gesture;
10021        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
10022        // of the gesture.
10023        if (actionMasked == MotionEvent.ACTION_UP ||
10024                actionMasked == MotionEvent.ACTION_CANCEL ||
10025                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
10026            stopNestedScroll();
10027        }
10028
10029        return result;
10030    }
10031
10032    boolean isAccessibilityFocusedViewOrHost() {
10033        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
10034                .getAccessibilityFocusedHost() == this);
10035    }
10036
10037    /**
10038     * Filter the touch event to apply security policies.
10039     *
10040     * @param event The motion event to be filtered.
10041     * @return True if the event should be dispatched, false if the event should be dropped.
10042     *
10043     * @see #getFilterTouchesWhenObscured
10044     */
10045    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
10046        //noinspection RedundantIfStatement
10047        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
10048                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
10049            // Window is obscured, drop this touch.
10050            return false;
10051        }
10052        return true;
10053    }
10054
10055    /**
10056     * Pass a trackball motion event down to the focused view.
10057     *
10058     * @param event The motion event to be dispatched.
10059     * @return True if the event was handled by the view, false otherwise.
10060     */
10061    public boolean dispatchTrackballEvent(MotionEvent event) {
10062        if (mInputEventConsistencyVerifier != null) {
10063            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
10064        }
10065
10066        return onTrackballEvent(event);
10067    }
10068
10069    /**
10070     * Dispatch a generic motion event.
10071     * <p>
10072     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10073     * are delivered to the view under the pointer.  All other generic motion events are
10074     * delivered to the focused view.  Hover events are handled specially and are delivered
10075     * to {@link #onHoverEvent(MotionEvent)}.
10076     * </p>
10077     *
10078     * @param event The motion event to be dispatched.
10079     * @return True if the event was handled by the view, false otherwise.
10080     */
10081    public boolean dispatchGenericMotionEvent(MotionEvent event) {
10082        if (mInputEventConsistencyVerifier != null) {
10083            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
10084        }
10085
10086        final int source = event.getSource();
10087        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
10088            final int action = event.getAction();
10089            if (action == MotionEvent.ACTION_HOVER_ENTER
10090                    || action == MotionEvent.ACTION_HOVER_MOVE
10091                    || action == MotionEvent.ACTION_HOVER_EXIT) {
10092                if (dispatchHoverEvent(event)) {
10093                    return true;
10094                }
10095            } else if (dispatchGenericPointerEvent(event)) {
10096                return true;
10097            }
10098        } else if (dispatchGenericFocusedEvent(event)) {
10099            return true;
10100        }
10101
10102        if (dispatchGenericMotionEventInternal(event)) {
10103            return true;
10104        }
10105
10106        if (mInputEventConsistencyVerifier != null) {
10107            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10108        }
10109        return false;
10110    }
10111
10112    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
10113        //noinspection SimplifiableIfStatement
10114        ListenerInfo li = mListenerInfo;
10115        if (li != null && li.mOnGenericMotionListener != null
10116                && (mViewFlags & ENABLED_MASK) == ENABLED
10117                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
10118            return true;
10119        }
10120
10121        if (onGenericMotionEvent(event)) {
10122            return true;
10123        }
10124
10125        final int actionButton = event.getActionButton();
10126        switch (event.getActionMasked()) {
10127            case MotionEvent.ACTION_BUTTON_PRESS:
10128                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
10129                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10130                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10131                    if (performContextClick(event.getX(), event.getY())) {
10132                        mInContextButtonPress = true;
10133                        setPressed(true, event.getX(), event.getY());
10134                        removeTapCallback();
10135                        removeLongPressCallback();
10136                        return true;
10137                    }
10138                }
10139                break;
10140
10141            case MotionEvent.ACTION_BUTTON_RELEASE:
10142                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10143                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10144                    mInContextButtonPress = false;
10145                    mIgnoreNextUpEvent = true;
10146                }
10147                break;
10148        }
10149
10150        if (mInputEventConsistencyVerifier != null) {
10151            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10152        }
10153        return false;
10154    }
10155
10156    /**
10157     * Dispatch a hover event.
10158     * <p>
10159     * Do not call this method directly.
10160     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10161     * </p>
10162     *
10163     * @param event The motion event to be dispatched.
10164     * @return True if the event was handled by the view, false otherwise.
10165     */
10166    protected boolean dispatchHoverEvent(MotionEvent event) {
10167        ListenerInfo li = mListenerInfo;
10168        //noinspection SimplifiableIfStatement
10169        if (li != null && li.mOnHoverListener != null
10170                && (mViewFlags & ENABLED_MASK) == ENABLED
10171                && li.mOnHoverListener.onHover(this, event)) {
10172            return true;
10173        }
10174
10175        return onHoverEvent(event);
10176    }
10177
10178    /**
10179     * Returns true if the view has a child to which it has recently sent
10180     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
10181     * it does not have a hovered child, then it must be the innermost hovered view.
10182     * @hide
10183     */
10184    protected boolean hasHoveredChild() {
10185        return false;
10186    }
10187
10188    /**
10189     * Dispatch a generic motion event to the view under the first pointer.
10190     * <p>
10191     * Do not call this method directly.
10192     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10193     * </p>
10194     *
10195     * @param event The motion event to be dispatched.
10196     * @return True if the event was handled by the view, false otherwise.
10197     */
10198    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
10199        return false;
10200    }
10201
10202    /**
10203     * Dispatch a generic motion event to the currently focused view.
10204     * <p>
10205     * Do not call this method directly.
10206     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10207     * </p>
10208     *
10209     * @param event The motion event to be dispatched.
10210     * @return True if the event was handled by the view, false otherwise.
10211     */
10212    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
10213        return false;
10214    }
10215
10216    /**
10217     * Dispatch a pointer event.
10218     * <p>
10219     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
10220     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
10221     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
10222     * and should not be expected to handle other pointing device features.
10223     * </p>
10224     *
10225     * @param event The motion event to be dispatched.
10226     * @return True if the event was handled by the view, false otherwise.
10227     * @hide
10228     */
10229    public final boolean dispatchPointerEvent(MotionEvent event) {
10230        if (event.isTouchEvent()) {
10231            return dispatchTouchEvent(event);
10232        } else {
10233            return dispatchGenericMotionEvent(event);
10234        }
10235    }
10236
10237    /**
10238     * Called when the window containing this view gains or loses window focus.
10239     * ViewGroups should override to route to their children.
10240     *
10241     * @param hasFocus True if the window containing this view now has focus,
10242     *        false otherwise.
10243     */
10244    public void dispatchWindowFocusChanged(boolean hasFocus) {
10245        onWindowFocusChanged(hasFocus);
10246    }
10247
10248    /**
10249     * Called when the window containing this view gains or loses focus.  Note
10250     * that this is separate from view focus: to receive key events, both
10251     * your view and its window must have focus.  If a window is displayed
10252     * on top of yours that takes input focus, then your own window will lose
10253     * focus but the view focus will remain unchanged.
10254     *
10255     * @param hasWindowFocus True if the window containing this view now has
10256     *        focus, false otherwise.
10257     */
10258    public void onWindowFocusChanged(boolean hasWindowFocus) {
10259        InputMethodManager imm = InputMethodManager.peekInstance();
10260        if (!hasWindowFocus) {
10261            if (isPressed()) {
10262                setPressed(false);
10263            }
10264            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10265                imm.focusOut(this);
10266            }
10267            removeLongPressCallback();
10268            removeTapCallback();
10269            onFocusLost();
10270        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10271            imm.focusIn(this);
10272        }
10273        refreshDrawableState();
10274    }
10275
10276    /**
10277     * Returns true if this view is in a window that currently has window focus.
10278     * Note that this is not the same as the view itself having focus.
10279     *
10280     * @return True if this view is in a window that currently has window focus.
10281     */
10282    public boolean hasWindowFocus() {
10283        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
10284    }
10285
10286    /**
10287     * Dispatch a view visibility change down the view hierarchy.
10288     * ViewGroups should override to route to their children.
10289     * @param changedView The view whose visibility changed. Could be 'this' or
10290     * an ancestor view.
10291     * @param visibility The new visibility of changedView: {@link #VISIBLE},
10292     * {@link #INVISIBLE} or {@link #GONE}.
10293     */
10294    protected void dispatchVisibilityChanged(@NonNull View changedView,
10295            @Visibility int visibility) {
10296        onVisibilityChanged(changedView, visibility);
10297    }
10298
10299    /**
10300     * Called when the visibility of the view or an ancestor of the view has
10301     * changed.
10302     *
10303     * @param changedView The view whose visibility changed. May be
10304     *                    {@code this} or an ancestor view.
10305     * @param visibility The new visibility, one of {@link #VISIBLE},
10306     *                   {@link #INVISIBLE} or {@link #GONE}.
10307     */
10308    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
10309    }
10310
10311    /**
10312     * Dispatch a hint about whether this view is displayed. For instance, when
10313     * a View moves out of the screen, it might receives a display hint indicating
10314     * the view is not displayed. Applications should not <em>rely</em> on this hint
10315     * as there is no guarantee that they will receive one.
10316     *
10317     * @param hint A hint about whether or not this view is displayed:
10318     * {@link #VISIBLE} or {@link #INVISIBLE}.
10319     */
10320    public void dispatchDisplayHint(@Visibility int hint) {
10321        onDisplayHint(hint);
10322    }
10323
10324    /**
10325     * Gives this view a hint about whether is displayed or not. For instance, when
10326     * a View moves out of the screen, it might receives a display hint indicating
10327     * the view is not displayed. Applications should not <em>rely</em> on this hint
10328     * as there is no guarantee that they will receive one.
10329     *
10330     * @param hint A hint about whether or not this view is displayed:
10331     * {@link #VISIBLE} or {@link #INVISIBLE}.
10332     */
10333    protected void onDisplayHint(@Visibility int hint) {
10334    }
10335
10336    /**
10337     * Dispatch a window visibility change down the view hierarchy.
10338     * ViewGroups should override to route to their children.
10339     *
10340     * @param visibility The new visibility of the window.
10341     *
10342     * @see #onWindowVisibilityChanged(int)
10343     */
10344    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
10345        onWindowVisibilityChanged(visibility);
10346    }
10347
10348    /**
10349     * Called when the window containing has change its visibility
10350     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
10351     * that this tells you whether or not your window is being made visible
10352     * to the window manager; this does <em>not</em> tell you whether or not
10353     * your window is obscured by other windows on the screen, even if it
10354     * is itself visible.
10355     *
10356     * @param visibility The new visibility of the window.
10357     */
10358    protected void onWindowVisibilityChanged(@Visibility int visibility) {
10359        if (visibility == VISIBLE) {
10360            initialAwakenScrollBars();
10361        }
10362    }
10363
10364    /**
10365     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
10366     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
10367     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
10368     *
10369     * @param isVisible true if this view's visibility to the user is uninterrupted by its
10370     *                  ancestors or by window visibility
10371     * @return true if this view is visible to the user, not counting clipping or overlapping
10372     */
10373    @Visibility boolean dispatchVisibilityAggregated(boolean isVisible) {
10374        final boolean thisVisible = getVisibility() == VISIBLE;
10375        // If we're not visible but something is telling us we are, ignore it.
10376        if (thisVisible || !isVisible) {
10377            onVisibilityAggregated(isVisible);
10378        }
10379        return thisVisible && isVisible;
10380    }
10381
10382    /**
10383     * Called when the user-visibility of this View is potentially affected by a change
10384     * to this view itself, an ancestor view or the window this view is attached to.
10385     *
10386     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
10387     *                  and this view's window is also visible
10388     */
10389    @CallSuper
10390    public void onVisibilityAggregated(boolean isVisible) {
10391        if (isVisible && mAttachInfo != null) {
10392            initialAwakenScrollBars();
10393        }
10394
10395        final Drawable dr = mBackground;
10396        if (dr != null && isVisible != dr.isVisible()) {
10397            dr.setVisible(isVisible, false);
10398        }
10399        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
10400        if (fg != null && isVisible != fg.isVisible()) {
10401            fg.setVisible(isVisible, false);
10402        }
10403    }
10404
10405    /**
10406     * Returns the current visibility of the window this view is attached to
10407     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
10408     *
10409     * @return Returns the current visibility of the view's window.
10410     */
10411    @Visibility
10412    public int getWindowVisibility() {
10413        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
10414    }
10415
10416    /**
10417     * Retrieve the overall visible display size in which the window this view is
10418     * attached to has been positioned in.  This takes into account screen
10419     * decorations above the window, for both cases where the window itself
10420     * is being position inside of them or the window is being placed under
10421     * then and covered insets are used for the window to position its content
10422     * inside.  In effect, this tells you the available area where content can
10423     * be placed and remain visible to users.
10424     *
10425     * <p>This function requires an IPC back to the window manager to retrieve
10426     * the requested information, so should not be used in performance critical
10427     * code like drawing.
10428     *
10429     * @param outRect Filled in with the visible display frame.  If the view
10430     * is not attached to a window, this is simply the raw display size.
10431     */
10432    public void getWindowVisibleDisplayFrame(Rect outRect) {
10433        if (mAttachInfo != null) {
10434            try {
10435                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10436            } catch (RemoteException e) {
10437                return;
10438            }
10439            // XXX This is really broken, and probably all needs to be done
10440            // in the window manager, and we need to know more about whether
10441            // we want the area behind or in front of the IME.
10442            final Rect insets = mAttachInfo.mVisibleInsets;
10443            outRect.left += insets.left;
10444            outRect.top += insets.top;
10445            outRect.right -= insets.right;
10446            outRect.bottom -= insets.bottom;
10447            return;
10448        }
10449        // The view is not attached to a display so we don't have a context.
10450        // Make a best guess about the display size.
10451        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10452        d.getRectSize(outRect);
10453    }
10454
10455    /**
10456     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
10457     * is currently in without any insets.
10458     *
10459     * @hide
10460     */
10461    public void getWindowDisplayFrame(Rect outRect) {
10462        if (mAttachInfo != null) {
10463            try {
10464                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10465            } catch (RemoteException e) {
10466                return;
10467            }
10468            return;
10469        }
10470        // The view is not attached to a display so we don't have a context.
10471        // Make a best guess about the display size.
10472        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10473        d.getRectSize(outRect);
10474    }
10475
10476    /**
10477     * Dispatch a notification about a resource configuration change down
10478     * the view hierarchy.
10479     * ViewGroups should override to route to their children.
10480     *
10481     * @param newConfig The new resource configuration.
10482     *
10483     * @see #onConfigurationChanged(android.content.res.Configuration)
10484     */
10485    public void dispatchConfigurationChanged(Configuration newConfig) {
10486        onConfigurationChanged(newConfig);
10487    }
10488
10489    /**
10490     * Called when the current configuration of the resources being used
10491     * by the application have changed.  You can use this to decide when
10492     * to reload resources that can changed based on orientation and other
10493     * configuration characteristics.  You only need to use this if you are
10494     * not relying on the normal {@link android.app.Activity} mechanism of
10495     * recreating the activity instance upon a configuration change.
10496     *
10497     * @param newConfig The new resource configuration.
10498     */
10499    protected void onConfigurationChanged(Configuration newConfig) {
10500    }
10501
10502    /**
10503     * Private function to aggregate all per-view attributes in to the view
10504     * root.
10505     */
10506    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10507        performCollectViewAttributes(attachInfo, visibility);
10508    }
10509
10510    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10511        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
10512            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
10513                attachInfo.mKeepScreenOn = true;
10514            }
10515            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
10516            ListenerInfo li = mListenerInfo;
10517            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
10518                attachInfo.mHasSystemUiListeners = true;
10519            }
10520        }
10521    }
10522
10523    void needGlobalAttributesUpdate(boolean force) {
10524        final AttachInfo ai = mAttachInfo;
10525        if (ai != null && !ai.mRecomputeGlobalAttributes) {
10526            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
10527                    || ai.mHasSystemUiListeners) {
10528                ai.mRecomputeGlobalAttributes = true;
10529            }
10530        }
10531    }
10532
10533    /**
10534     * Returns whether the device is currently in touch mode.  Touch mode is entered
10535     * once the user begins interacting with the device by touch, and affects various
10536     * things like whether focus is always visible to the user.
10537     *
10538     * @return Whether the device is in touch mode.
10539     */
10540    @ViewDebug.ExportedProperty
10541    public boolean isInTouchMode() {
10542        if (mAttachInfo != null) {
10543            return mAttachInfo.mInTouchMode;
10544        } else {
10545            return ViewRootImpl.isInTouchMode();
10546        }
10547    }
10548
10549    /**
10550     * Returns the context the view is running in, through which it can
10551     * access the current theme, resources, etc.
10552     *
10553     * @return The view's Context.
10554     */
10555    @ViewDebug.CapturedViewProperty
10556    public final Context getContext() {
10557        return mContext;
10558    }
10559
10560    /**
10561     * Handle a key event before it is processed by any input method
10562     * associated with the view hierarchy.  This can be used to intercept
10563     * key events in special situations before the IME consumes them; a
10564     * typical example would be handling the BACK key to update the application's
10565     * UI instead of allowing the IME to see it and close itself.
10566     *
10567     * @param keyCode The value in event.getKeyCode().
10568     * @param event Description of the key event.
10569     * @return If you handled the event, return true. If you want to allow the
10570     *         event to be handled by the next receiver, return false.
10571     */
10572    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10573        return false;
10574    }
10575
10576    /**
10577     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10578     * KeyEvent.Callback.onKeyDown()}: perform press of the view
10579     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10580     * is released, if the view is enabled and clickable.
10581     * <p>
10582     * Key presses in software keyboards will generally NOT trigger this
10583     * listener, although some may elect to do so in some situations. Do not
10584     * rely on this to catch software key presses.
10585     *
10586     * @param keyCode a key code that represents the button pressed, from
10587     *                {@link android.view.KeyEvent}
10588     * @param event the KeyEvent object that defines the button action
10589     */
10590    public boolean onKeyDown(int keyCode, KeyEvent event) {
10591        if (KeyEvent.isConfirmKey(keyCode)) {
10592            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10593                return true;
10594            }
10595
10596            // Long clickable items don't necessarily have to be clickable.
10597            if (((mViewFlags & CLICKABLE) == CLICKABLE
10598                    || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10599                    && (event.getRepeatCount() == 0)) {
10600                // For the purposes of menu anchoring and drawable hotspots,
10601                // key events are considered to be at the center of the view.
10602                final float x = getWidth() / 2f;
10603                final float y = getHeight() / 2f;
10604                setPressed(true, x, y);
10605                checkForLongClick(0, x, y);
10606                return true;
10607            }
10608        }
10609
10610        return false;
10611    }
10612
10613    /**
10614     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
10615     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
10616     * the event).
10617     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10618     * although some may elect to do so in some situations. Do not rely on this to
10619     * catch software key presses.
10620     */
10621    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
10622        return false;
10623    }
10624
10625    /**
10626     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
10627     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
10628     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
10629     * or {@link KeyEvent#KEYCODE_SPACE} is released.
10630     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10631     * although some may elect to do so in some situations. Do not rely on this to
10632     * catch software key presses.
10633     *
10634     * @param keyCode A key code that represents the button pressed, from
10635     *                {@link android.view.KeyEvent}.
10636     * @param event   The KeyEvent object that defines the button action.
10637     */
10638    public boolean onKeyUp(int keyCode, KeyEvent event) {
10639        if (KeyEvent.isConfirmKey(keyCode)) {
10640            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10641                return true;
10642            }
10643            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
10644                setPressed(false);
10645
10646                if (!mHasPerformedLongPress) {
10647                    // This is a tap, so remove the longpress check
10648                    removeLongPressCallback();
10649                    return performClick();
10650                }
10651            }
10652        }
10653        return false;
10654    }
10655
10656    /**
10657     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10658     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
10659     * the event).
10660     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10661     * although some may elect to do so in some situations. Do not rely on this to
10662     * catch software key presses.
10663     *
10664     * @param keyCode     A key code that represents the button pressed, from
10665     *                    {@link android.view.KeyEvent}.
10666     * @param repeatCount The number of times the action was made.
10667     * @param event       The KeyEvent object that defines the button action.
10668     */
10669    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10670        return false;
10671    }
10672
10673    /**
10674     * Called on the focused view when a key shortcut event is not handled.
10675     * Override this method to implement local key shortcuts for the View.
10676     * Key shortcuts can also be implemented by setting the
10677     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10678     *
10679     * @param keyCode The value in event.getKeyCode().
10680     * @param event Description of the key event.
10681     * @return If you handled the event, return true. If you want to allow the
10682     *         event to be handled by the next receiver, return false.
10683     */
10684    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10685        return false;
10686    }
10687
10688    /**
10689     * Check whether the called view is a text editor, in which case it
10690     * would make sense to automatically display a soft input window for
10691     * it.  Subclasses should override this if they implement
10692     * {@link #onCreateInputConnection(EditorInfo)} to return true if
10693     * a call on that method would return a non-null InputConnection, and
10694     * they are really a first-class editor that the user would normally
10695     * start typing on when the go into a window containing your view.
10696     *
10697     * <p>The default implementation always returns false.  This does
10698     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10699     * will not be called or the user can not otherwise perform edits on your
10700     * view; it is just a hint to the system that this is not the primary
10701     * purpose of this view.
10702     *
10703     * @return Returns true if this view is a text editor, else false.
10704     */
10705    public boolean onCheckIsTextEditor() {
10706        return false;
10707    }
10708
10709    /**
10710     * Create a new InputConnection for an InputMethod to interact
10711     * with the view.  The default implementation returns null, since it doesn't
10712     * support input methods.  You can override this to implement such support.
10713     * This is only needed for views that take focus and text input.
10714     *
10715     * <p>When implementing this, you probably also want to implement
10716     * {@link #onCheckIsTextEditor()} to indicate you will return a
10717     * non-null InputConnection.</p>
10718     *
10719     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10720     * object correctly and in its entirety, so that the connected IME can rely
10721     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10722     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10723     * must be filled in with the correct cursor position for IMEs to work correctly
10724     * with your application.</p>
10725     *
10726     * @param outAttrs Fill in with attribute information about the connection.
10727     */
10728    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10729        return null;
10730    }
10731
10732    /**
10733     * Called by the {@link android.view.inputmethod.InputMethodManager}
10734     * when a view who is not the current
10735     * input connection target is trying to make a call on the manager.  The
10736     * default implementation returns false; you can override this to return
10737     * true for certain views if you are performing InputConnection proxying
10738     * to them.
10739     * @param view The View that is making the InputMethodManager call.
10740     * @return Return true to allow the call, false to reject.
10741     */
10742    public boolean checkInputConnectionProxy(View view) {
10743        return false;
10744    }
10745
10746    /**
10747     * Show the context menu for this view. It is not safe to hold on to the
10748     * menu after returning from this method.
10749     *
10750     * You should normally not overload this method. Overload
10751     * {@link #onCreateContextMenu(ContextMenu)} or define an
10752     * {@link OnCreateContextMenuListener} to add items to the context menu.
10753     *
10754     * @param menu The context menu to populate
10755     */
10756    public void createContextMenu(ContextMenu menu) {
10757        ContextMenuInfo menuInfo = getContextMenuInfo();
10758
10759        // Sets the current menu info so all items added to menu will have
10760        // my extra info set.
10761        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10762
10763        onCreateContextMenu(menu);
10764        ListenerInfo li = mListenerInfo;
10765        if (li != null && li.mOnCreateContextMenuListener != null) {
10766            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10767        }
10768
10769        // Clear the extra information so subsequent items that aren't mine don't
10770        // have my extra info.
10771        ((MenuBuilder)menu).setCurrentMenuInfo(null);
10772
10773        if (mParent != null) {
10774            mParent.createContextMenu(menu);
10775        }
10776    }
10777
10778    /**
10779     * Views should implement this if they have extra information to associate
10780     * with the context menu. The return result is supplied as a parameter to
10781     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10782     * callback.
10783     *
10784     * @return Extra information about the item for which the context menu
10785     *         should be shown. This information will vary across different
10786     *         subclasses of View.
10787     */
10788    protected ContextMenuInfo getContextMenuInfo() {
10789        return null;
10790    }
10791
10792    /**
10793     * Views should implement this if the view itself is going to add items to
10794     * the context menu.
10795     *
10796     * @param menu the context menu to populate
10797     */
10798    protected void onCreateContextMenu(ContextMenu menu) {
10799    }
10800
10801    /**
10802     * Implement this method to handle trackball motion events.  The
10803     * <em>relative</em> movement of the trackball since the last event
10804     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10805     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10806     * that a movement of 1 corresponds to the user pressing one DPAD key (so
10807     * they will often be fractional values, representing the more fine-grained
10808     * movement information available from a trackball).
10809     *
10810     * @param event The motion event.
10811     * @return True if the event was handled, false otherwise.
10812     */
10813    public boolean onTrackballEvent(MotionEvent event) {
10814        return false;
10815    }
10816
10817    /**
10818     * Implement this method to handle generic motion events.
10819     * <p>
10820     * Generic motion events describe joystick movements, mouse hovers, track pad
10821     * touches, scroll wheel movements and other input events.  The
10822     * {@link MotionEvent#getSource() source} of the motion event specifies
10823     * the class of input that was received.  Implementations of this method
10824     * must examine the bits in the source before processing the event.
10825     * The following code example shows how this is done.
10826     * </p><p>
10827     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10828     * are delivered to the view under the pointer.  All other generic motion events are
10829     * delivered to the focused view.
10830     * </p>
10831     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10832     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10833     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10834     *             // process the joystick movement...
10835     *             return true;
10836     *         }
10837     *     }
10838     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10839     *         switch (event.getAction()) {
10840     *             case MotionEvent.ACTION_HOVER_MOVE:
10841     *                 // process the mouse hover movement...
10842     *                 return true;
10843     *             case MotionEvent.ACTION_SCROLL:
10844     *                 // process the scroll wheel movement...
10845     *                 return true;
10846     *         }
10847     *     }
10848     *     return super.onGenericMotionEvent(event);
10849     * }</pre>
10850     *
10851     * @param event The generic motion event being processed.
10852     * @return True if the event was handled, false otherwise.
10853     */
10854    public boolean onGenericMotionEvent(MotionEvent event) {
10855        return false;
10856    }
10857
10858    /**
10859     * Implement this method to handle hover events.
10860     * <p>
10861     * This method is called whenever a pointer is hovering into, over, or out of the
10862     * bounds of a view and the view is not currently being touched.
10863     * Hover events are represented as pointer events with action
10864     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10865     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10866     * </p>
10867     * <ul>
10868     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10869     * when the pointer enters the bounds of the view.</li>
10870     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10871     * when the pointer has already entered the bounds of the view and has moved.</li>
10872     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10873     * when the pointer has exited the bounds of the view or when the pointer is
10874     * about to go down due to a button click, tap, or similar user action that
10875     * causes the view to be touched.</li>
10876     * </ul>
10877     * <p>
10878     * The view should implement this method to return true to indicate that it is
10879     * handling the hover event, such as by changing its drawable state.
10880     * </p><p>
10881     * The default implementation calls {@link #setHovered} to update the hovered state
10882     * of the view when a hover enter or hover exit event is received, if the view
10883     * is enabled and is clickable.  The default implementation also sends hover
10884     * accessibility events.
10885     * </p>
10886     *
10887     * @param event The motion event that describes the hover.
10888     * @return True if the view handled the hover event.
10889     *
10890     * @see #isHovered
10891     * @see #setHovered
10892     * @see #onHoverChanged
10893     */
10894    public boolean onHoverEvent(MotionEvent event) {
10895        // The root view may receive hover (or touch) events that are outside the bounds of
10896        // the window.  This code ensures that we only send accessibility events for
10897        // hovers that are actually within the bounds of the root view.
10898        final int action = event.getActionMasked();
10899        if (!mSendingHoverAccessibilityEvents) {
10900            if ((action == MotionEvent.ACTION_HOVER_ENTER
10901                    || action == MotionEvent.ACTION_HOVER_MOVE)
10902                    && !hasHoveredChild()
10903                    && pointInView(event.getX(), event.getY())) {
10904                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10905                mSendingHoverAccessibilityEvents = true;
10906            }
10907        } else {
10908            if (action == MotionEvent.ACTION_HOVER_EXIT
10909                    || (action == MotionEvent.ACTION_MOVE
10910                            && !pointInView(event.getX(), event.getY()))) {
10911                mSendingHoverAccessibilityEvents = false;
10912                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10913            }
10914        }
10915
10916        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
10917                && event.isFromSource(InputDevice.SOURCE_MOUSE)
10918                && isOnScrollbar(event.getX(), event.getY())) {
10919            awakenScrollBars();
10920        }
10921        if (isHoverable()) {
10922            switch (action) {
10923                case MotionEvent.ACTION_HOVER_ENTER:
10924                    setHovered(true);
10925                    break;
10926                case MotionEvent.ACTION_HOVER_EXIT:
10927                    setHovered(false);
10928                    break;
10929            }
10930
10931            // Dispatch the event to onGenericMotionEvent before returning true.
10932            // This is to provide compatibility with existing applications that
10933            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10934            // break because of the new default handling for hoverable views
10935            // in onHoverEvent.
10936            // Note that onGenericMotionEvent will be called by default when
10937            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10938            dispatchGenericMotionEventInternal(event);
10939            // The event was already handled by calling setHovered(), so always
10940            // return true.
10941            return true;
10942        }
10943
10944        return false;
10945    }
10946
10947    /**
10948     * Returns true if the view should handle {@link #onHoverEvent}
10949     * by calling {@link #setHovered} to change its hovered state.
10950     *
10951     * @return True if the view is hoverable.
10952     */
10953    private boolean isHoverable() {
10954        final int viewFlags = mViewFlags;
10955        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10956            return false;
10957        }
10958
10959        return (viewFlags & CLICKABLE) == CLICKABLE
10960                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10961                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10962    }
10963
10964    /**
10965     * Returns true if the view is currently hovered.
10966     *
10967     * @return True if the view is currently hovered.
10968     *
10969     * @see #setHovered
10970     * @see #onHoverChanged
10971     */
10972    @ViewDebug.ExportedProperty
10973    public boolean isHovered() {
10974        return (mPrivateFlags & PFLAG_HOVERED) != 0;
10975    }
10976
10977    /**
10978     * Sets whether the view is currently hovered.
10979     * <p>
10980     * Calling this method also changes the drawable state of the view.  This
10981     * enables the view to react to hover by using different drawable resources
10982     * to change its appearance.
10983     * </p><p>
10984     * The {@link #onHoverChanged} method is called when the hovered state changes.
10985     * </p>
10986     *
10987     * @param hovered True if the view is hovered.
10988     *
10989     * @see #isHovered
10990     * @see #onHoverChanged
10991     */
10992    public void setHovered(boolean hovered) {
10993        if (hovered) {
10994            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10995                mPrivateFlags |= PFLAG_HOVERED;
10996                refreshDrawableState();
10997                onHoverChanged(true);
10998            }
10999        } else {
11000            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
11001                mPrivateFlags &= ~PFLAG_HOVERED;
11002                refreshDrawableState();
11003                onHoverChanged(false);
11004            }
11005        }
11006    }
11007
11008    /**
11009     * Implement this method to handle hover state changes.
11010     * <p>
11011     * This method is called whenever the hover state changes as a result of a
11012     * call to {@link #setHovered}.
11013     * </p>
11014     *
11015     * @param hovered The current hover state, as returned by {@link #isHovered}.
11016     *
11017     * @see #isHovered
11018     * @see #setHovered
11019     */
11020    public void onHoverChanged(boolean hovered) {
11021    }
11022
11023    /**
11024     * Handles scroll bar dragging by mouse input.
11025     *
11026     * @hide
11027     * @param event The motion event.
11028     *
11029     * @return true if the event was handled as a scroll bar dragging, false otherwise.
11030     */
11031    protected boolean handleScrollBarDragging(MotionEvent event) {
11032        if (mScrollCache == null) {
11033            return false;
11034        }
11035        final float x = event.getX();
11036        final float y = event.getY();
11037        final int action = event.getAction();
11038        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
11039                && action != MotionEvent.ACTION_DOWN)
11040                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
11041                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
11042            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11043            return false;
11044        }
11045
11046        switch (action) {
11047            case MotionEvent.ACTION_MOVE:
11048                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
11049                    return false;
11050                }
11051                if (mScrollCache.mScrollBarDraggingState
11052                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
11053                    final Rect bounds = mScrollCache.mScrollBarBounds;
11054                    getVerticalScrollBarBounds(bounds);
11055                    final int range = computeVerticalScrollRange();
11056                    final int offset = computeVerticalScrollOffset();
11057                    final int extent = computeVerticalScrollExtent();
11058
11059                    final int thumbLength = ScrollBarUtils.getThumbLength(
11060                            bounds.height(), bounds.width(), extent, range);
11061                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11062                            bounds.height(), thumbLength, extent, range, offset);
11063
11064                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
11065                    final float maxThumbOffset = bounds.height() - thumbLength;
11066                    final float newThumbOffset =
11067                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11068                    final int height = getHeight();
11069                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11070                            && height > 0 && extent > 0) {
11071                        final int newY = Math.round((range - extent)
11072                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
11073                        if (newY != getScrollY()) {
11074                            mScrollCache.mScrollBarDraggingPos = y;
11075                            setScrollY(newY);
11076                        }
11077                    }
11078                    return true;
11079                }
11080                if (mScrollCache.mScrollBarDraggingState
11081                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
11082                    final Rect bounds = mScrollCache.mScrollBarBounds;
11083                    getHorizontalScrollBarBounds(bounds);
11084                    final int range = computeHorizontalScrollRange();
11085                    final int offset = computeHorizontalScrollOffset();
11086                    final int extent = computeHorizontalScrollExtent();
11087
11088                    final int thumbLength = ScrollBarUtils.getThumbLength(
11089                            bounds.width(), bounds.height(), extent, range);
11090                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11091                            bounds.width(), thumbLength, extent, range, offset);
11092
11093                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
11094                    final float maxThumbOffset = bounds.width() - thumbLength;
11095                    final float newThumbOffset =
11096                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11097                    final int width = getWidth();
11098                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11099                            && width > 0 && extent > 0) {
11100                        final int newX = Math.round((range - extent)
11101                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
11102                        if (newX != getScrollX()) {
11103                            mScrollCache.mScrollBarDraggingPos = x;
11104                            setScrollX(newX);
11105                        }
11106                    }
11107                    return true;
11108                }
11109            case MotionEvent.ACTION_DOWN:
11110                if (mScrollCache.state == ScrollabilityCache.OFF) {
11111                    return false;
11112                }
11113                if (isOnVerticalScrollbarThumb(x, y)) {
11114                    mScrollCache.mScrollBarDraggingState =
11115                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
11116                    mScrollCache.mScrollBarDraggingPos = y;
11117                    return true;
11118                }
11119                if (isOnHorizontalScrollbarThumb(x, y)) {
11120                    mScrollCache.mScrollBarDraggingState =
11121                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
11122                    mScrollCache.mScrollBarDraggingPos = x;
11123                    return true;
11124                }
11125        }
11126        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11127        return false;
11128    }
11129
11130    /**
11131     * Implement this method to handle touch screen motion events.
11132     * <p>
11133     * If this method is used to detect click actions, it is recommended that
11134     * the actions be performed by implementing and calling
11135     * {@link #performClick()}. This will ensure consistent system behavior,
11136     * including:
11137     * <ul>
11138     * <li>obeying click sound preferences
11139     * <li>dispatching OnClickListener calls
11140     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
11141     * accessibility features are enabled
11142     * </ul>
11143     *
11144     * @param event The motion event.
11145     * @return True if the event was handled, false otherwise.
11146     */
11147    public boolean onTouchEvent(MotionEvent event) {
11148        final float x = event.getX();
11149        final float y = event.getY();
11150        final int viewFlags = mViewFlags;
11151        final int action = event.getAction();
11152
11153        if ((viewFlags & ENABLED_MASK) == DISABLED) {
11154            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
11155                setPressed(false);
11156            }
11157            // A disabled view that is clickable still consumes the touch
11158            // events, it just doesn't respond to them.
11159            return (((viewFlags & CLICKABLE) == CLICKABLE
11160                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
11161                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
11162        }
11163        if (mTouchDelegate != null) {
11164            if (mTouchDelegate.onTouchEvent(event)) {
11165                return true;
11166            }
11167        }
11168
11169        if (((viewFlags & CLICKABLE) == CLICKABLE ||
11170                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
11171                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
11172            switch (action) {
11173                case MotionEvent.ACTION_UP:
11174                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
11175                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
11176                        // take focus if we don't have it already and we should in
11177                        // touch mode.
11178                        boolean focusTaken = false;
11179                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
11180                            focusTaken = requestFocus();
11181                        }
11182
11183                        if (prepressed) {
11184                            // The button is being released before we actually
11185                            // showed it as pressed.  Make it show the pressed
11186                            // state now (before scheduling the click) to ensure
11187                            // the user sees it.
11188                            setPressed(true, x, y);
11189                       }
11190
11191                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
11192                            // This is a tap, so remove the longpress check
11193                            removeLongPressCallback();
11194
11195                            // Only perform take click actions if we were in the pressed state
11196                            if (!focusTaken) {
11197                                // Use a Runnable and post this rather than calling
11198                                // performClick directly. This lets other visual state
11199                                // of the view update before click actions start.
11200                                if (mPerformClick == null) {
11201                                    mPerformClick = new PerformClick();
11202                                }
11203                                if (!post(mPerformClick)) {
11204                                    performClick();
11205                                }
11206                            }
11207                        }
11208
11209                        if (mUnsetPressedState == null) {
11210                            mUnsetPressedState = new UnsetPressedState();
11211                        }
11212
11213                        if (prepressed) {
11214                            postDelayed(mUnsetPressedState,
11215                                    ViewConfiguration.getPressedStateDuration());
11216                        } else if (!post(mUnsetPressedState)) {
11217                            // If the post failed, unpress right now
11218                            mUnsetPressedState.run();
11219                        }
11220
11221                        removeTapCallback();
11222                    }
11223                    mIgnoreNextUpEvent = false;
11224                    break;
11225
11226                case MotionEvent.ACTION_DOWN:
11227                    mHasPerformedLongPress = false;
11228
11229                    if (performButtonActionOnTouchDown(event)) {
11230                        break;
11231                    }
11232
11233                    // Walk up the hierarchy to determine if we're inside a scrolling container.
11234                    boolean isInScrollingContainer = isInScrollingContainer();
11235
11236                    // For views inside a scrolling container, delay the pressed feedback for
11237                    // a short period in case this is a scroll.
11238                    if (isInScrollingContainer) {
11239                        mPrivateFlags |= PFLAG_PREPRESSED;
11240                        if (mPendingCheckForTap == null) {
11241                            mPendingCheckForTap = new CheckForTap();
11242                        }
11243                        mPendingCheckForTap.x = event.getX();
11244                        mPendingCheckForTap.y = event.getY();
11245                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
11246                    } else {
11247                        // Not inside a scrolling container, so show the feedback right away
11248                        setPressed(true, x, y);
11249                        checkForLongClick(0, x, y);
11250                    }
11251                    break;
11252
11253                case MotionEvent.ACTION_CANCEL:
11254                    setPressed(false);
11255                    removeTapCallback();
11256                    removeLongPressCallback();
11257                    mInContextButtonPress = false;
11258                    mHasPerformedLongPress = false;
11259                    mIgnoreNextUpEvent = false;
11260                    break;
11261
11262                case MotionEvent.ACTION_MOVE:
11263                    drawableHotspotChanged(x, y);
11264
11265                    // Be lenient about moving outside of buttons
11266                    if (!pointInView(x, y, mTouchSlop)) {
11267                        // Outside button
11268                        removeTapCallback();
11269                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
11270                            // Remove any future long press/tap checks
11271                            removeLongPressCallback();
11272
11273                            setPressed(false);
11274                        }
11275                    }
11276                    break;
11277            }
11278
11279            return true;
11280        }
11281
11282        return false;
11283    }
11284
11285    /**
11286     * @hide
11287     */
11288    public boolean isInScrollingContainer() {
11289        ViewParent p = getParent();
11290        while (p != null && p instanceof ViewGroup) {
11291            if (((ViewGroup) p).shouldDelayChildPressedState()) {
11292                return true;
11293            }
11294            p = p.getParent();
11295        }
11296        return false;
11297    }
11298
11299    /**
11300     * Remove the longpress detection timer.
11301     */
11302    private void removeLongPressCallback() {
11303        if (mPendingCheckForLongPress != null) {
11304          removeCallbacks(mPendingCheckForLongPress);
11305        }
11306    }
11307
11308    /**
11309     * Remove the pending click action
11310     */
11311    private void removePerformClickCallback() {
11312        if (mPerformClick != null) {
11313            removeCallbacks(mPerformClick);
11314        }
11315    }
11316
11317    /**
11318     * Remove the prepress detection timer.
11319     */
11320    private void removeUnsetPressCallback() {
11321        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
11322            setPressed(false);
11323            removeCallbacks(mUnsetPressedState);
11324        }
11325    }
11326
11327    /**
11328     * Remove the tap detection timer.
11329     */
11330    private void removeTapCallback() {
11331        if (mPendingCheckForTap != null) {
11332            mPrivateFlags &= ~PFLAG_PREPRESSED;
11333            removeCallbacks(mPendingCheckForTap);
11334        }
11335    }
11336
11337    /**
11338     * Cancels a pending long press.  Your subclass can use this if you
11339     * want the context menu to come up if the user presses and holds
11340     * at the same place, but you don't want it to come up if they press
11341     * and then move around enough to cause scrolling.
11342     */
11343    public void cancelLongPress() {
11344        removeLongPressCallback();
11345
11346        /*
11347         * The prepressed state handled by the tap callback is a display
11348         * construct, but the tap callback will post a long press callback
11349         * less its own timeout. Remove it here.
11350         */
11351        removeTapCallback();
11352    }
11353
11354    /**
11355     * Remove the pending callback for sending a
11356     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
11357     */
11358    private void removeSendViewScrolledAccessibilityEventCallback() {
11359        if (mSendViewScrolledAccessibilityEvent != null) {
11360            removeCallbacks(mSendViewScrolledAccessibilityEvent);
11361            mSendViewScrolledAccessibilityEvent.mIsPending = false;
11362        }
11363    }
11364
11365    /**
11366     * Sets the TouchDelegate for this View.
11367     */
11368    public void setTouchDelegate(TouchDelegate delegate) {
11369        mTouchDelegate = delegate;
11370    }
11371
11372    /**
11373     * Gets the TouchDelegate for this View.
11374     */
11375    public TouchDelegate getTouchDelegate() {
11376        return mTouchDelegate;
11377    }
11378
11379    /**
11380     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
11381     *
11382     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
11383     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
11384     * available. This method should only be called for touch events.
11385     *
11386     * <p class="note">This api is not intended for most applications. Buffered dispatch
11387     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
11388     * streams will not improve your input latency. Side effects include: increased latency,
11389     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
11390     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
11391     * you.</p>
11392     */
11393    public final void requestUnbufferedDispatch(MotionEvent event) {
11394        final int action = event.getAction();
11395        if (mAttachInfo == null
11396                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
11397                || !event.isTouchEvent()) {
11398            return;
11399        }
11400        mAttachInfo.mUnbufferedDispatchRequested = true;
11401    }
11402
11403    /**
11404     * Set flags controlling behavior of this view.
11405     *
11406     * @param flags Constant indicating the value which should be set
11407     * @param mask Constant indicating the bit range that should be changed
11408     */
11409    void setFlags(int flags, int mask) {
11410        final boolean accessibilityEnabled =
11411                AccessibilityManager.getInstance(mContext).isEnabled();
11412        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
11413
11414        int old = mViewFlags;
11415        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
11416
11417        int changed = mViewFlags ^ old;
11418        if (changed == 0) {
11419            return;
11420        }
11421        int privateFlags = mPrivateFlags;
11422
11423        /* Check if the FOCUSABLE bit has changed */
11424        if (((changed & FOCUSABLE_MASK) != 0) &&
11425                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
11426            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
11427                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
11428                /* Give up focus if we are no longer focusable */
11429                clearFocus();
11430            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
11431                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
11432                /*
11433                 * Tell the view system that we are now available to take focus
11434                 * if no one else already has it.
11435                 */
11436                if (mParent != null) mParent.focusableViewAvailable(this);
11437            }
11438        }
11439
11440        final int newVisibility = flags & VISIBILITY_MASK;
11441        if (newVisibility == VISIBLE) {
11442            if ((changed & VISIBILITY_MASK) != 0) {
11443                /*
11444                 * If this view is becoming visible, invalidate it in case it changed while
11445                 * it was not visible. Marking it drawn ensures that the invalidation will
11446                 * go through.
11447                 */
11448                mPrivateFlags |= PFLAG_DRAWN;
11449                invalidate(true);
11450
11451                needGlobalAttributesUpdate(true);
11452
11453                // a view becoming visible is worth notifying the parent
11454                // about in case nothing has focus.  even if this specific view
11455                // isn't focusable, it may contain something that is, so let
11456                // the root view try to give this focus if nothing else does.
11457                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
11458                    mParent.focusableViewAvailable(this);
11459                }
11460            }
11461        }
11462
11463        /* Check if the GONE bit has changed */
11464        if ((changed & GONE) != 0) {
11465            needGlobalAttributesUpdate(false);
11466            requestLayout();
11467
11468            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
11469                if (hasFocus()) clearFocus();
11470                clearAccessibilityFocus();
11471                destroyDrawingCache();
11472                if (mParent instanceof View) {
11473                    // GONE views noop invalidation, so invalidate the parent
11474                    ((View) mParent).invalidate(true);
11475                }
11476                // Mark the view drawn to ensure that it gets invalidated properly the next
11477                // time it is visible and gets invalidated
11478                mPrivateFlags |= PFLAG_DRAWN;
11479            }
11480            if (mAttachInfo != null) {
11481                mAttachInfo.mViewVisibilityChanged = true;
11482            }
11483        }
11484
11485        /* Check if the VISIBLE bit has changed */
11486        if ((changed & INVISIBLE) != 0) {
11487            needGlobalAttributesUpdate(false);
11488            /*
11489             * If this view is becoming invisible, set the DRAWN flag so that
11490             * the next invalidate() will not be skipped.
11491             */
11492            mPrivateFlags |= PFLAG_DRAWN;
11493
11494            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
11495                // root view becoming invisible shouldn't clear focus and accessibility focus
11496                if (getRootView() != this) {
11497                    if (hasFocus()) clearFocus();
11498                    clearAccessibilityFocus();
11499                }
11500            }
11501            if (mAttachInfo != null) {
11502                mAttachInfo.mViewVisibilityChanged = true;
11503            }
11504        }
11505
11506        if ((changed & VISIBILITY_MASK) != 0) {
11507            // If the view is invisible, cleanup its display list to free up resources
11508            if (newVisibility != VISIBLE && mAttachInfo != null) {
11509                cleanupDraw();
11510            }
11511
11512            if (mParent instanceof ViewGroup) {
11513                ((ViewGroup) mParent).onChildVisibilityChanged(this,
11514                        (changed & VISIBILITY_MASK), newVisibility);
11515                ((View) mParent).invalidate(true);
11516            } else if (mParent != null) {
11517                mParent.invalidateChild(this, null);
11518            }
11519
11520            if (mAttachInfo != null) {
11521                dispatchVisibilityChanged(this, newVisibility);
11522
11523                // Aggregated visibility changes are dispatched to attached views
11524                // in visible windows where the parent is currently shown/drawn
11525                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
11526                // discounting clipping or overlapping. This makes it a good place
11527                // to change animation states.
11528                if (mParent != null && getWindowVisibility() == VISIBLE &&
11529                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
11530                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
11531                }
11532                notifySubtreeAccessibilityStateChangedIfNeeded();
11533            }
11534        }
11535
11536        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
11537            destroyDrawingCache();
11538        }
11539
11540        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
11541            destroyDrawingCache();
11542            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11543            invalidateParentCaches();
11544        }
11545
11546        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
11547            destroyDrawingCache();
11548            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11549        }
11550
11551        if ((changed & DRAW_MASK) != 0) {
11552            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
11553                if (mBackground != null
11554                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
11555                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11556                } else {
11557                    mPrivateFlags |= PFLAG_SKIP_DRAW;
11558                }
11559            } else {
11560                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11561            }
11562            requestLayout();
11563            invalidate(true);
11564        }
11565
11566        if ((changed & KEEP_SCREEN_ON) != 0) {
11567            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
11568                mParent.recomputeViewAttributes(this);
11569            }
11570        }
11571
11572        if (accessibilityEnabled) {
11573            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
11574                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
11575                    || (changed & CONTEXT_CLICKABLE) != 0) {
11576                if (oldIncludeForAccessibility != includeForAccessibility()) {
11577                    notifySubtreeAccessibilityStateChangedIfNeeded();
11578                } else {
11579                    notifyViewAccessibilityStateChangedIfNeeded(
11580                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11581                }
11582            } else if ((changed & ENABLED_MASK) != 0) {
11583                notifyViewAccessibilityStateChangedIfNeeded(
11584                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11585            }
11586        }
11587    }
11588
11589    /**
11590     * Change the view's z order in the tree, so it's on top of other sibling
11591     * views. This ordering change may affect layout, if the parent container
11592     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
11593     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
11594     * method should be followed by calls to {@link #requestLayout()} and
11595     * {@link View#invalidate()} on the view's parent to force the parent to redraw
11596     * with the new child ordering.
11597     *
11598     * @see ViewGroup#bringChildToFront(View)
11599     */
11600    public void bringToFront() {
11601        if (mParent != null) {
11602            mParent.bringChildToFront(this);
11603        }
11604    }
11605
11606    /**
11607     * This is called in response to an internal scroll in this view (i.e., the
11608     * view scrolled its own contents). This is typically as a result of
11609     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
11610     * called.
11611     *
11612     * @param l Current horizontal scroll origin.
11613     * @param t Current vertical scroll origin.
11614     * @param oldl Previous horizontal scroll origin.
11615     * @param oldt Previous vertical scroll origin.
11616     */
11617    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
11618        notifySubtreeAccessibilityStateChangedIfNeeded();
11619
11620        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
11621            postSendViewScrolledAccessibilityEventCallback();
11622        }
11623
11624        mBackgroundSizeChanged = true;
11625        if (mForegroundInfo != null) {
11626            mForegroundInfo.mBoundsChanged = true;
11627        }
11628
11629        final AttachInfo ai = mAttachInfo;
11630        if (ai != null) {
11631            ai.mViewScrollChanged = true;
11632        }
11633
11634        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
11635            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
11636        }
11637    }
11638
11639    /**
11640     * Interface definition for a callback to be invoked when the scroll
11641     * X or Y positions of a view change.
11642     * <p>
11643     * <b>Note:</b> Some views handle scrolling independently from View and may
11644     * have their own separate listeners for scroll-type events. For example,
11645     * {@link android.widget.ListView ListView} allows clients to register an
11646     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
11647     * to listen for changes in list scroll position.
11648     *
11649     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
11650     */
11651    public interface OnScrollChangeListener {
11652        /**
11653         * Called when the scroll position of a view changes.
11654         *
11655         * @param v The view whose scroll position has changed.
11656         * @param scrollX Current horizontal scroll origin.
11657         * @param scrollY Current vertical scroll origin.
11658         * @param oldScrollX Previous horizontal scroll origin.
11659         * @param oldScrollY Previous vertical scroll origin.
11660         */
11661        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
11662    }
11663
11664    /**
11665     * Interface definition for a callback to be invoked when the layout bounds of a view
11666     * changes due to layout processing.
11667     */
11668    public interface OnLayoutChangeListener {
11669        /**
11670         * Called when the layout bounds of a view changes due to layout processing.
11671         *
11672         * @param v The view whose bounds have changed.
11673         * @param left The new value of the view's left property.
11674         * @param top The new value of the view's top property.
11675         * @param right The new value of the view's right property.
11676         * @param bottom The new value of the view's bottom property.
11677         * @param oldLeft The previous value of the view's left property.
11678         * @param oldTop The previous value of the view's top property.
11679         * @param oldRight The previous value of the view's right property.
11680         * @param oldBottom The previous value of the view's bottom property.
11681         */
11682        void onLayoutChange(View v, int left, int top, int right, int bottom,
11683            int oldLeft, int oldTop, int oldRight, int oldBottom);
11684    }
11685
11686    /**
11687     * This is called during layout when the size of this view has changed. If
11688     * you were just added to the view hierarchy, you're called with the old
11689     * values of 0.
11690     *
11691     * @param w Current width of this view.
11692     * @param h Current height of this view.
11693     * @param oldw Old width of this view.
11694     * @param oldh Old height of this view.
11695     */
11696    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
11697    }
11698
11699    /**
11700     * Called by draw to draw the child views. This may be overridden
11701     * by derived classes to gain control just before its children are drawn
11702     * (but after its own view has been drawn).
11703     * @param canvas the canvas on which to draw the view
11704     */
11705    protected void dispatchDraw(Canvas canvas) {
11706
11707    }
11708
11709    /**
11710     * Gets the parent of this view. Note that the parent is a
11711     * ViewParent and not necessarily a View.
11712     *
11713     * @return Parent of this view.
11714     */
11715    public final ViewParent getParent() {
11716        return mParent;
11717    }
11718
11719    /**
11720     * Set the horizontal scrolled position of your view. This will cause a call to
11721     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11722     * invalidated.
11723     * @param value the x position to scroll to
11724     */
11725    public void setScrollX(int value) {
11726        scrollTo(value, mScrollY);
11727    }
11728
11729    /**
11730     * Set the vertical scrolled position of your view. This will cause a call to
11731     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11732     * invalidated.
11733     * @param value the y position to scroll to
11734     */
11735    public void setScrollY(int value) {
11736        scrollTo(mScrollX, value);
11737    }
11738
11739    /**
11740     * Return the scrolled left position of this view. This is the left edge of
11741     * the displayed part of your view. You do not need to draw any pixels
11742     * farther left, since those are outside of the frame of your view on
11743     * screen.
11744     *
11745     * @return The left edge of the displayed part of your view, in pixels.
11746     */
11747    public final int getScrollX() {
11748        return mScrollX;
11749    }
11750
11751    /**
11752     * Return the scrolled top position of this view. This is the top edge of
11753     * the displayed part of your view. You do not need to draw any pixels above
11754     * it, since those are outside of the frame of your view on screen.
11755     *
11756     * @return The top edge of the displayed part of your view, in pixels.
11757     */
11758    public final int getScrollY() {
11759        return mScrollY;
11760    }
11761
11762    /**
11763     * Return the width of the your view.
11764     *
11765     * @return The width of your view, in pixels.
11766     */
11767    @ViewDebug.ExportedProperty(category = "layout")
11768    public final int getWidth() {
11769        return mRight - mLeft;
11770    }
11771
11772    /**
11773     * Return the height of your view.
11774     *
11775     * @return The height of your view, in pixels.
11776     */
11777    @ViewDebug.ExportedProperty(category = "layout")
11778    public final int getHeight() {
11779        return mBottom - mTop;
11780    }
11781
11782    /**
11783     * Return the visible drawing bounds of your view. Fills in the output
11784     * rectangle with the values from getScrollX(), getScrollY(),
11785     * getWidth(), and getHeight(). These bounds do not account for any
11786     * transformation properties currently set on the view, such as
11787     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11788     *
11789     * @param outRect The (scrolled) drawing bounds of the view.
11790     */
11791    public void getDrawingRect(Rect outRect) {
11792        outRect.left = mScrollX;
11793        outRect.top = mScrollY;
11794        outRect.right = mScrollX + (mRight - mLeft);
11795        outRect.bottom = mScrollY + (mBottom - mTop);
11796    }
11797
11798    /**
11799     * Like {@link #getMeasuredWidthAndState()}, but only returns the
11800     * raw width component (that is the result is masked by
11801     * {@link #MEASURED_SIZE_MASK}).
11802     *
11803     * @return The raw measured width of this view.
11804     */
11805    public final int getMeasuredWidth() {
11806        return mMeasuredWidth & MEASURED_SIZE_MASK;
11807    }
11808
11809    /**
11810     * Return the full width measurement information for this view as computed
11811     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11812     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11813     * This should be used during measurement and layout calculations only. Use
11814     * {@link #getWidth()} to see how wide a view is after layout.
11815     *
11816     * @return The measured width of this view as a bit mask.
11817     */
11818    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11819            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11820                    name = "MEASURED_STATE_TOO_SMALL"),
11821    })
11822    public final int getMeasuredWidthAndState() {
11823        return mMeasuredWidth;
11824    }
11825
11826    /**
11827     * Like {@link #getMeasuredHeightAndState()}, but only returns the
11828     * raw width component (that is the result is masked by
11829     * {@link #MEASURED_SIZE_MASK}).
11830     *
11831     * @return The raw measured height of this view.
11832     */
11833    public final int getMeasuredHeight() {
11834        return mMeasuredHeight & MEASURED_SIZE_MASK;
11835    }
11836
11837    /**
11838     * Return the full height measurement information for this view as computed
11839     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11840     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11841     * This should be used during measurement and layout calculations only. Use
11842     * {@link #getHeight()} to see how wide a view is after layout.
11843     *
11844     * @return The measured width of this view as a bit mask.
11845     */
11846    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11847            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11848                    name = "MEASURED_STATE_TOO_SMALL"),
11849    })
11850    public final int getMeasuredHeightAndState() {
11851        return mMeasuredHeight;
11852    }
11853
11854    /**
11855     * Return only the state bits of {@link #getMeasuredWidthAndState()}
11856     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11857     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11858     * and the height component is at the shifted bits
11859     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11860     */
11861    public final int getMeasuredState() {
11862        return (mMeasuredWidth&MEASURED_STATE_MASK)
11863                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11864                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11865    }
11866
11867    /**
11868     * The transform matrix of this view, which is calculated based on the current
11869     * rotation, scale, and pivot properties.
11870     *
11871     * @see #getRotation()
11872     * @see #getScaleX()
11873     * @see #getScaleY()
11874     * @see #getPivotX()
11875     * @see #getPivotY()
11876     * @return The current transform matrix for the view
11877     */
11878    public Matrix getMatrix() {
11879        ensureTransformationInfo();
11880        final Matrix matrix = mTransformationInfo.mMatrix;
11881        mRenderNode.getMatrix(matrix);
11882        return matrix;
11883    }
11884
11885    /**
11886     * Returns true if the transform matrix is the identity matrix.
11887     * Recomputes the matrix if necessary.
11888     *
11889     * @return True if the transform matrix is the identity matrix, false otherwise.
11890     */
11891    final boolean hasIdentityMatrix() {
11892        return mRenderNode.hasIdentityMatrix();
11893    }
11894
11895    void ensureTransformationInfo() {
11896        if (mTransformationInfo == null) {
11897            mTransformationInfo = new TransformationInfo();
11898        }
11899    }
11900
11901    /**
11902     * Utility method to retrieve the inverse of the current mMatrix property.
11903     * We cache the matrix to avoid recalculating it when transform properties
11904     * have not changed.
11905     *
11906     * @return The inverse of the current matrix of this view.
11907     * @hide
11908     */
11909    public final Matrix getInverseMatrix() {
11910        ensureTransformationInfo();
11911        if (mTransformationInfo.mInverseMatrix == null) {
11912            mTransformationInfo.mInverseMatrix = new Matrix();
11913        }
11914        final Matrix matrix = mTransformationInfo.mInverseMatrix;
11915        mRenderNode.getInverseMatrix(matrix);
11916        return matrix;
11917    }
11918
11919    /**
11920     * Gets the distance along the Z axis from the camera to this view.
11921     *
11922     * @see #setCameraDistance(float)
11923     *
11924     * @return The distance along the Z axis.
11925     */
11926    public float getCameraDistance() {
11927        final float dpi = mResources.getDisplayMetrics().densityDpi;
11928        return -(mRenderNode.getCameraDistance() * dpi);
11929    }
11930
11931    /**
11932     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11933     * views are drawn) from the camera to this view. The camera's distance
11934     * affects 3D transformations, for instance rotations around the X and Y
11935     * axis. If the rotationX or rotationY properties are changed and this view is
11936     * large (more than half the size of the screen), it is recommended to always
11937     * use a camera distance that's greater than the height (X axis rotation) or
11938     * the width (Y axis rotation) of this view.</p>
11939     *
11940     * <p>The distance of the camera from the view plane can have an affect on the
11941     * perspective distortion of the view when it is rotated around the x or y axis.
11942     * For example, a large distance will result in a large viewing angle, and there
11943     * will not be much perspective distortion of the view as it rotates. A short
11944     * distance may cause much more perspective distortion upon rotation, and can
11945     * also result in some drawing artifacts if the rotated view ends up partially
11946     * behind the camera (which is why the recommendation is to use a distance at
11947     * least as far as the size of the view, if the view is to be rotated.)</p>
11948     *
11949     * <p>The distance is expressed in "depth pixels." The default distance depends
11950     * on the screen density. For instance, on a medium density display, the
11951     * default distance is 1280. On a high density display, the default distance
11952     * is 1920.</p>
11953     *
11954     * <p>If you want to specify a distance that leads to visually consistent
11955     * results across various densities, use the following formula:</p>
11956     * <pre>
11957     * float scale = context.getResources().getDisplayMetrics().density;
11958     * view.setCameraDistance(distance * scale);
11959     * </pre>
11960     *
11961     * <p>The density scale factor of a high density display is 1.5,
11962     * and 1920 = 1280 * 1.5.</p>
11963     *
11964     * @param distance The distance in "depth pixels", if negative the opposite
11965     *        value is used
11966     *
11967     * @see #setRotationX(float)
11968     * @see #setRotationY(float)
11969     */
11970    public void setCameraDistance(float distance) {
11971        final float dpi = mResources.getDisplayMetrics().densityDpi;
11972
11973        invalidateViewProperty(true, false);
11974        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11975        invalidateViewProperty(false, false);
11976
11977        invalidateParentIfNeededAndWasQuickRejected();
11978    }
11979
11980    /**
11981     * The degrees that the view is rotated around the pivot point.
11982     *
11983     * @see #setRotation(float)
11984     * @see #getPivotX()
11985     * @see #getPivotY()
11986     *
11987     * @return The degrees of rotation.
11988     */
11989    @ViewDebug.ExportedProperty(category = "drawing")
11990    public float getRotation() {
11991        return mRenderNode.getRotation();
11992    }
11993
11994    /**
11995     * Sets the degrees that the view is rotated around the pivot point. Increasing values
11996     * result in clockwise rotation.
11997     *
11998     * @param rotation The degrees of rotation.
11999     *
12000     * @see #getRotation()
12001     * @see #getPivotX()
12002     * @see #getPivotY()
12003     * @see #setRotationX(float)
12004     * @see #setRotationY(float)
12005     *
12006     * @attr ref android.R.styleable#View_rotation
12007     */
12008    public void setRotation(float rotation) {
12009        if (rotation != getRotation()) {
12010            // Double-invalidation is necessary to capture view's old and new areas
12011            invalidateViewProperty(true, false);
12012            mRenderNode.setRotation(rotation);
12013            invalidateViewProperty(false, true);
12014
12015            invalidateParentIfNeededAndWasQuickRejected();
12016            notifySubtreeAccessibilityStateChangedIfNeeded();
12017        }
12018    }
12019
12020    /**
12021     * The degrees that the view is rotated around the vertical axis through the pivot point.
12022     *
12023     * @see #getPivotX()
12024     * @see #getPivotY()
12025     * @see #setRotationY(float)
12026     *
12027     * @return The degrees of Y rotation.
12028     */
12029    @ViewDebug.ExportedProperty(category = "drawing")
12030    public float getRotationY() {
12031        return mRenderNode.getRotationY();
12032    }
12033
12034    /**
12035     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
12036     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
12037     * down the y axis.
12038     *
12039     * When rotating large views, it is recommended to adjust the camera distance
12040     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12041     *
12042     * @param rotationY The degrees of Y rotation.
12043     *
12044     * @see #getRotationY()
12045     * @see #getPivotX()
12046     * @see #getPivotY()
12047     * @see #setRotation(float)
12048     * @see #setRotationX(float)
12049     * @see #setCameraDistance(float)
12050     *
12051     * @attr ref android.R.styleable#View_rotationY
12052     */
12053    public void setRotationY(float rotationY) {
12054        if (rotationY != getRotationY()) {
12055            invalidateViewProperty(true, false);
12056            mRenderNode.setRotationY(rotationY);
12057            invalidateViewProperty(false, true);
12058
12059            invalidateParentIfNeededAndWasQuickRejected();
12060            notifySubtreeAccessibilityStateChangedIfNeeded();
12061        }
12062    }
12063
12064    /**
12065     * The degrees that the view is rotated around the horizontal axis through the pivot point.
12066     *
12067     * @see #getPivotX()
12068     * @see #getPivotY()
12069     * @see #setRotationX(float)
12070     *
12071     * @return The degrees of X rotation.
12072     */
12073    @ViewDebug.ExportedProperty(category = "drawing")
12074    public float getRotationX() {
12075        return mRenderNode.getRotationX();
12076    }
12077
12078    /**
12079     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
12080     * Increasing values result in clockwise rotation from the viewpoint of looking down the
12081     * x axis.
12082     *
12083     * When rotating large views, it is recommended to adjust the camera distance
12084     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12085     *
12086     * @param rotationX The degrees of X rotation.
12087     *
12088     * @see #getRotationX()
12089     * @see #getPivotX()
12090     * @see #getPivotY()
12091     * @see #setRotation(float)
12092     * @see #setRotationY(float)
12093     * @see #setCameraDistance(float)
12094     *
12095     * @attr ref android.R.styleable#View_rotationX
12096     */
12097    public void setRotationX(float rotationX) {
12098        if (rotationX != getRotationX()) {
12099            invalidateViewProperty(true, false);
12100            mRenderNode.setRotationX(rotationX);
12101            invalidateViewProperty(false, true);
12102
12103            invalidateParentIfNeededAndWasQuickRejected();
12104            notifySubtreeAccessibilityStateChangedIfNeeded();
12105        }
12106    }
12107
12108    /**
12109     * The amount that the view is scaled in x around the pivot point, as a proportion of
12110     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
12111     *
12112     * <p>By default, this is 1.0f.
12113     *
12114     * @see #getPivotX()
12115     * @see #getPivotY()
12116     * @return The scaling factor.
12117     */
12118    @ViewDebug.ExportedProperty(category = "drawing")
12119    public float getScaleX() {
12120        return mRenderNode.getScaleX();
12121    }
12122
12123    /**
12124     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
12125     * the view's unscaled width. A value of 1 means that no scaling is applied.
12126     *
12127     * @param scaleX The scaling factor.
12128     * @see #getPivotX()
12129     * @see #getPivotY()
12130     *
12131     * @attr ref android.R.styleable#View_scaleX
12132     */
12133    public void setScaleX(float scaleX) {
12134        if (scaleX != getScaleX()) {
12135            invalidateViewProperty(true, false);
12136            mRenderNode.setScaleX(scaleX);
12137            invalidateViewProperty(false, true);
12138
12139            invalidateParentIfNeededAndWasQuickRejected();
12140            notifySubtreeAccessibilityStateChangedIfNeeded();
12141        }
12142    }
12143
12144    /**
12145     * The amount that the view is scaled in y around the pivot point, as a proportion of
12146     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
12147     *
12148     * <p>By default, this is 1.0f.
12149     *
12150     * @see #getPivotX()
12151     * @see #getPivotY()
12152     * @return The scaling factor.
12153     */
12154    @ViewDebug.ExportedProperty(category = "drawing")
12155    public float getScaleY() {
12156        return mRenderNode.getScaleY();
12157    }
12158
12159    /**
12160     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
12161     * the view's unscaled width. A value of 1 means that no scaling is applied.
12162     *
12163     * @param scaleY The scaling factor.
12164     * @see #getPivotX()
12165     * @see #getPivotY()
12166     *
12167     * @attr ref android.R.styleable#View_scaleY
12168     */
12169    public void setScaleY(float scaleY) {
12170        if (scaleY != getScaleY()) {
12171            invalidateViewProperty(true, false);
12172            mRenderNode.setScaleY(scaleY);
12173            invalidateViewProperty(false, true);
12174
12175            invalidateParentIfNeededAndWasQuickRejected();
12176            notifySubtreeAccessibilityStateChangedIfNeeded();
12177        }
12178    }
12179
12180    /**
12181     * The x location of the point around which the view is {@link #setRotation(float) rotated}
12182     * and {@link #setScaleX(float) scaled}.
12183     *
12184     * @see #getRotation()
12185     * @see #getScaleX()
12186     * @see #getScaleY()
12187     * @see #getPivotY()
12188     * @return The x location of the pivot point.
12189     *
12190     * @attr ref android.R.styleable#View_transformPivotX
12191     */
12192    @ViewDebug.ExportedProperty(category = "drawing")
12193    public float getPivotX() {
12194        return mRenderNode.getPivotX();
12195    }
12196
12197    /**
12198     * Sets the x location of the point around which the view is
12199     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
12200     * By default, the pivot point is centered on the object.
12201     * Setting this property disables this behavior and causes the view to use only the
12202     * explicitly set pivotX and pivotY values.
12203     *
12204     * @param pivotX The x location of the pivot point.
12205     * @see #getRotation()
12206     * @see #getScaleX()
12207     * @see #getScaleY()
12208     * @see #getPivotY()
12209     *
12210     * @attr ref android.R.styleable#View_transformPivotX
12211     */
12212    public void setPivotX(float pivotX) {
12213        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
12214            invalidateViewProperty(true, false);
12215            mRenderNode.setPivotX(pivotX);
12216            invalidateViewProperty(false, true);
12217
12218            invalidateParentIfNeededAndWasQuickRejected();
12219        }
12220    }
12221
12222    /**
12223     * The y location of the point around which the view is {@link #setRotation(float) rotated}
12224     * and {@link #setScaleY(float) scaled}.
12225     *
12226     * @see #getRotation()
12227     * @see #getScaleX()
12228     * @see #getScaleY()
12229     * @see #getPivotY()
12230     * @return The y location of the pivot point.
12231     *
12232     * @attr ref android.R.styleable#View_transformPivotY
12233     */
12234    @ViewDebug.ExportedProperty(category = "drawing")
12235    public float getPivotY() {
12236        return mRenderNode.getPivotY();
12237    }
12238
12239    /**
12240     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
12241     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
12242     * Setting this property disables this behavior and causes the view to use only the
12243     * explicitly set pivotX and pivotY values.
12244     *
12245     * @param pivotY The y location of the pivot point.
12246     * @see #getRotation()
12247     * @see #getScaleX()
12248     * @see #getScaleY()
12249     * @see #getPivotY()
12250     *
12251     * @attr ref android.R.styleable#View_transformPivotY
12252     */
12253    public void setPivotY(float pivotY) {
12254        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
12255            invalidateViewProperty(true, false);
12256            mRenderNode.setPivotY(pivotY);
12257            invalidateViewProperty(false, true);
12258
12259            invalidateParentIfNeededAndWasQuickRejected();
12260        }
12261    }
12262
12263    /**
12264     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
12265     * completely transparent and 1 means the view is completely opaque.
12266     *
12267     * <p>By default this is 1.0f.
12268     * @return The opacity of the view.
12269     */
12270    @ViewDebug.ExportedProperty(category = "drawing")
12271    public float getAlpha() {
12272        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
12273    }
12274
12275    /**
12276     * Sets the behavior for overlapping rendering for this view (see {@link
12277     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
12278     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
12279     * providing the value which is then used internally. That is, when {@link
12280     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
12281     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
12282     * instead.
12283     *
12284     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
12285     * instead of that returned by {@link #hasOverlappingRendering()}.
12286     *
12287     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
12288     */
12289    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
12290        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
12291        if (hasOverlappingRendering) {
12292            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12293        } else {
12294            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12295        }
12296    }
12297
12298    /**
12299     * Returns the value for overlapping rendering that is used internally. This is either
12300     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
12301     * the return value of {@link #hasOverlappingRendering()}, otherwise.
12302     *
12303     * @return The value for overlapping rendering being used internally.
12304     */
12305    public final boolean getHasOverlappingRendering() {
12306        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
12307                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
12308                hasOverlappingRendering();
12309    }
12310
12311    /**
12312     * Returns whether this View has content which overlaps.
12313     *
12314     * <p>This function, intended to be overridden by specific View types, is an optimization when
12315     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
12316     * an offscreen buffer and then composited into place, which can be expensive. If the view has
12317     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
12318     * directly. An example of overlapping rendering is a TextView with a background image, such as
12319     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
12320     * ImageView with only the foreground image. The default implementation returns true; subclasses
12321     * should override if they have cases which can be optimized.</p>
12322     *
12323     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
12324     * necessitates that a View return true if it uses the methods internally without passing the
12325     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
12326     *
12327     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
12328     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
12329     *
12330     * @return true if the content in this view might overlap, false otherwise.
12331     */
12332    @ViewDebug.ExportedProperty(category = "drawing")
12333    public boolean hasOverlappingRendering() {
12334        return true;
12335    }
12336
12337    /**
12338     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
12339     * completely transparent and 1 means the view is completely opaque.
12340     *
12341     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
12342     * can have significant performance implications, especially for large views. It is best to use
12343     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
12344     *
12345     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
12346     * strongly recommended for performance reasons to either override
12347     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
12348     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
12349     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
12350     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
12351     * of rendering cost, even for simple or small views. Starting with
12352     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
12353     * applied to the view at the rendering level.</p>
12354     *
12355     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
12356     * responsible for applying the opacity itself.</p>
12357     *
12358     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
12359     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
12360     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
12361     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
12362     *
12363     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
12364     * value will clip a View to its bounds, unless the View returns <code>false</code> from
12365     * {@link #hasOverlappingRendering}.</p>
12366     *
12367     * @param alpha The opacity of the view.
12368     *
12369     * @see #hasOverlappingRendering()
12370     * @see #setLayerType(int, android.graphics.Paint)
12371     *
12372     * @attr ref android.R.styleable#View_alpha
12373     */
12374    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
12375        ensureTransformationInfo();
12376        if (mTransformationInfo.mAlpha != alpha) {
12377            // Report visibility changes, which can affect children, to accessibility
12378            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
12379                notifySubtreeAccessibilityStateChangedIfNeeded();
12380            }
12381            mTransformationInfo.mAlpha = alpha;
12382            if (onSetAlpha((int) (alpha * 255))) {
12383                mPrivateFlags |= PFLAG_ALPHA_SET;
12384                // subclass is handling alpha - don't optimize rendering cache invalidation
12385                invalidateParentCaches();
12386                invalidate(true);
12387            } else {
12388                mPrivateFlags &= ~PFLAG_ALPHA_SET;
12389                invalidateViewProperty(true, false);
12390                mRenderNode.setAlpha(getFinalAlpha());
12391            }
12392        }
12393    }
12394
12395    /**
12396     * Faster version of setAlpha() which performs the same steps except there are
12397     * no calls to invalidate(). The caller of this function should perform proper invalidation
12398     * on the parent and this object. The return value indicates whether the subclass handles
12399     * alpha (the return value for onSetAlpha()).
12400     *
12401     * @param alpha The new value for the alpha property
12402     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
12403     *         the new value for the alpha property is different from the old value
12404     */
12405    boolean setAlphaNoInvalidation(float alpha) {
12406        ensureTransformationInfo();
12407        if (mTransformationInfo.mAlpha != alpha) {
12408            mTransformationInfo.mAlpha = alpha;
12409            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
12410            if (subclassHandlesAlpha) {
12411                mPrivateFlags |= PFLAG_ALPHA_SET;
12412                return true;
12413            } else {
12414                mPrivateFlags &= ~PFLAG_ALPHA_SET;
12415                mRenderNode.setAlpha(getFinalAlpha());
12416            }
12417        }
12418        return false;
12419    }
12420
12421    /**
12422     * This property is hidden and intended only for use by the Fade transition, which
12423     * animates it to produce a visual translucency that does not side-effect (or get
12424     * affected by) the real alpha property. This value is composited with the other
12425     * alpha value (and the AlphaAnimation value, when that is present) to produce
12426     * a final visual translucency result, which is what is passed into the DisplayList.
12427     *
12428     * @hide
12429     */
12430    public void setTransitionAlpha(float alpha) {
12431        ensureTransformationInfo();
12432        if (mTransformationInfo.mTransitionAlpha != alpha) {
12433            mTransformationInfo.mTransitionAlpha = alpha;
12434            mPrivateFlags &= ~PFLAG_ALPHA_SET;
12435            invalidateViewProperty(true, false);
12436            mRenderNode.setAlpha(getFinalAlpha());
12437        }
12438    }
12439
12440    /**
12441     * Calculates the visual alpha of this view, which is a combination of the actual
12442     * alpha value and the transitionAlpha value (if set).
12443     */
12444    private float getFinalAlpha() {
12445        if (mTransformationInfo != null) {
12446            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
12447        }
12448        return 1;
12449    }
12450
12451    /**
12452     * This property is hidden and intended only for use by the Fade transition, which
12453     * animates it to produce a visual translucency that does not side-effect (or get
12454     * affected by) the real alpha property. This value is composited with the other
12455     * alpha value (and the AlphaAnimation value, when that is present) to produce
12456     * a final visual translucency result, which is what is passed into the DisplayList.
12457     *
12458     * @hide
12459     */
12460    @ViewDebug.ExportedProperty(category = "drawing")
12461    public float getTransitionAlpha() {
12462        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
12463    }
12464
12465    /**
12466     * Top position of this view relative to its parent.
12467     *
12468     * @return The top of this view, in pixels.
12469     */
12470    @ViewDebug.CapturedViewProperty
12471    public final int getTop() {
12472        return mTop;
12473    }
12474
12475    /**
12476     * Sets the top position of this view relative to its parent. This method is meant to be called
12477     * by the layout system and should not generally be called otherwise, because the property
12478     * may be changed at any time by the layout.
12479     *
12480     * @param top The top of this view, in pixels.
12481     */
12482    public final void setTop(int top) {
12483        if (top != mTop) {
12484            final boolean matrixIsIdentity = hasIdentityMatrix();
12485            if (matrixIsIdentity) {
12486                if (mAttachInfo != null) {
12487                    int minTop;
12488                    int yLoc;
12489                    if (top < mTop) {
12490                        minTop = top;
12491                        yLoc = top - mTop;
12492                    } else {
12493                        minTop = mTop;
12494                        yLoc = 0;
12495                    }
12496                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
12497                }
12498            } else {
12499                // Double-invalidation is necessary to capture view's old and new areas
12500                invalidate(true);
12501            }
12502
12503            int width = mRight - mLeft;
12504            int oldHeight = mBottom - mTop;
12505
12506            mTop = top;
12507            mRenderNode.setTop(mTop);
12508
12509            sizeChange(width, mBottom - mTop, width, oldHeight);
12510
12511            if (!matrixIsIdentity) {
12512                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12513                invalidate(true);
12514            }
12515            mBackgroundSizeChanged = true;
12516            if (mForegroundInfo != null) {
12517                mForegroundInfo.mBoundsChanged = true;
12518            }
12519            invalidateParentIfNeeded();
12520            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12521                // View was rejected last time it was drawn by its parent; this may have changed
12522                invalidateParentIfNeeded();
12523            }
12524        }
12525    }
12526
12527    /**
12528     * Bottom position of this view relative to its parent.
12529     *
12530     * @return The bottom of this view, in pixels.
12531     */
12532    @ViewDebug.CapturedViewProperty
12533    public final int getBottom() {
12534        return mBottom;
12535    }
12536
12537    /**
12538     * True if this view has changed since the last time being drawn.
12539     *
12540     * @return The dirty state of this view.
12541     */
12542    public boolean isDirty() {
12543        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
12544    }
12545
12546    /**
12547     * Sets the bottom position of this view relative to its parent. This method is meant to be
12548     * called by the layout system and should not generally be called otherwise, because the
12549     * property may be changed at any time by the layout.
12550     *
12551     * @param bottom The bottom of this view, in pixels.
12552     */
12553    public final void setBottom(int bottom) {
12554        if (bottom != mBottom) {
12555            final boolean matrixIsIdentity = hasIdentityMatrix();
12556            if (matrixIsIdentity) {
12557                if (mAttachInfo != null) {
12558                    int maxBottom;
12559                    if (bottom < mBottom) {
12560                        maxBottom = mBottom;
12561                    } else {
12562                        maxBottom = bottom;
12563                    }
12564                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
12565                }
12566            } else {
12567                // Double-invalidation is necessary to capture view's old and new areas
12568                invalidate(true);
12569            }
12570
12571            int width = mRight - mLeft;
12572            int oldHeight = mBottom - mTop;
12573
12574            mBottom = bottom;
12575            mRenderNode.setBottom(mBottom);
12576
12577            sizeChange(width, mBottom - mTop, width, oldHeight);
12578
12579            if (!matrixIsIdentity) {
12580                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12581                invalidate(true);
12582            }
12583            mBackgroundSizeChanged = true;
12584            if (mForegroundInfo != null) {
12585                mForegroundInfo.mBoundsChanged = true;
12586            }
12587            invalidateParentIfNeeded();
12588            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12589                // View was rejected last time it was drawn by its parent; this may have changed
12590                invalidateParentIfNeeded();
12591            }
12592        }
12593    }
12594
12595    /**
12596     * Left position of this view relative to its parent.
12597     *
12598     * @return The left edge of this view, in pixels.
12599     */
12600    @ViewDebug.CapturedViewProperty
12601    public final int getLeft() {
12602        return mLeft;
12603    }
12604
12605    /**
12606     * Sets the left position of this view relative to its parent. This method is meant to be called
12607     * by the layout system and should not generally be called otherwise, because the property
12608     * may be changed at any time by the layout.
12609     *
12610     * @param left The left of this view, in pixels.
12611     */
12612    public final void setLeft(int left) {
12613        if (left != mLeft) {
12614            final boolean matrixIsIdentity = hasIdentityMatrix();
12615            if (matrixIsIdentity) {
12616                if (mAttachInfo != null) {
12617                    int minLeft;
12618                    int xLoc;
12619                    if (left < mLeft) {
12620                        minLeft = left;
12621                        xLoc = left - mLeft;
12622                    } else {
12623                        minLeft = mLeft;
12624                        xLoc = 0;
12625                    }
12626                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
12627                }
12628            } else {
12629                // Double-invalidation is necessary to capture view's old and new areas
12630                invalidate(true);
12631            }
12632
12633            int oldWidth = mRight - mLeft;
12634            int height = mBottom - mTop;
12635
12636            mLeft = left;
12637            mRenderNode.setLeft(left);
12638
12639            sizeChange(mRight - mLeft, height, oldWidth, height);
12640
12641            if (!matrixIsIdentity) {
12642                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12643                invalidate(true);
12644            }
12645            mBackgroundSizeChanged = true;
12646            if (mForegroundInfo != null) {
12647                mForegroundInfo.mBoundsChanged = true;
12648            }
12649            invalidateParentIfNeeded();
12650            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12651                // View was rejected last time it was drawn by its parent; this may have changed
12652                invalidateParentIfNeeded();
12653            }
12654        }
12655    }
12656
12657    /**
12658     * Right position of this view relative to its parent.
12659     *
12660     * @return The right edge of this view, in pixels.
12661     */
12662    @ViewDebug.CapturedViewProperty
12663    public final int getRight() {
12664        return mRight;
12665    }
12666
12667    /**
12668     * Sets the right position of this view relative to its parent. This method is meant to be called
12669     * by the layout system and should not generally be called otherwise, because the property
12670     * may be changed at any time by the layout.
12671     *
12672     * @param right The right of this view, in pixels.
12673     */
12674    public final void setRight(int right) {
12675        if (right != mRight) {
12676            final boolean matrixIsIdentity = hasIdentityMatrix();
12677            if (matrixIsIdentity) {
12678                if (mAttachInfo != null) {
12679                    int maxRight;
12680                    if (right < mRight) {
12681                        maxRight = mRight;
12682                    } else {
12683                        maxRight = right;
12684                    }
12685                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
12686                }
12687            } else {
12688                // Double-invalidation is necessary to capture view's old and new areas
12689                invalidate(true);
12690            }
12691
12692            int oldWidth = mRight - mLeft;
12693            int height = mBottom - mTop;
12694
12695            mRight = right;
12696            mRenderNode.setRight(mRight);
12697
12698            sizeChange(mRight - mLeft, height, oldWidth, height);
12699
12700            if (!matrixIsIdentity) {
12701                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12702                invalidate(true);
12703            }
12704            mBackgroundSizeChanged = true;
12705            if (mForegroundInfo != null) {
12706                mForegroundInfo.mBoundsChanged = true;
12707            }
12708            invalidateParentIfNeeded();
12709            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12710                // View was rejected last time it was drawn by its parent; this may have changed
12711                invalidateParentIfNeeded();
12712            }
12713        }
12714    }
12715
12716    /**
12717     * The visual x position of this view, in pixels. This is equivalent to the
12718     * {@link #setTranslationX(float) translationX} property plus the current
12719     * {@link #getLeft() left} property.
12720     *
12721     * @return The visual x position of this view, in pixels.
12722     */
12723    @ViewDebug.ExportedProperty(category = "drawing")
12724    public float getX() {
12725        return mLeft + getTranslationX();
12726    }
12727
12728    /**
12729     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
12730     * {@link #setTranslationX(float) translationX} property to be the difference between
12731     * the x value passed in and the current {@link #getLeft() left} property.
12732     *
12733     * @param x The visual x position of this view, in pixels.
12734     */
12735    public void setX(float x) {
12736        setTranslationX(x - mLeft);
12737    }
12738
12739    /**
12740     * The visual y position of this view, in pixels. This is equivalent to the
12741     * {@link #setTranslationY(float) translationY} property plus the current
12742     * {@link #getTop() top} property.
12743     *
12744     * @return The visual y position of this view, in pixels.
12745     */
12746    @ViewDebug.ExportedProperty(category = "drawing")
12747    public float getY() {
12748        return mTop + getTranslationY();
12749    }
12750
12751    /**
12752     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
12753     * {@link #setTranslationY(float) translationY} property to be the difference between
12754     * the y value passed in and the current {@link #getTop() top} property.
12755     *
12756     * @param y The visual y position of this view, in pixels.
12757     */
12758    public void setY(float y) {
12759        setTranslationY(y - mTop);
12760    }
12761
12762    /**
12763     * The visual z position of this view, in pixels. This is equivalent to the
12764     * {@link #setTranslationZ(float) translationZ} property plus the current
12765     * {@link #getElevation() elevation} property.
12766     *
12767     * @return The visual z position of this view, in pixels.
12768     */
12769    @ViewDebug.ExportedProperty(category = "drawing")
12770    public float getZ() {
12771        return getElevation() + getTranslationZ();
12772    }
12773
12774    /**
12775     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
12776     * {@link #setTranslationZ(float) translationZ} property to be the difference between
12777     * the x value passed in and the current {@link #getElevation() elevation} property.
12778     *
12779     * @param z The visual z position of this view, in pixels.
12780     */
12781    public void setZ(float z) {
12782        setTranslationZ(z - getElevation());
12783    }
12784
12785    /**
12786     * The base elevation of this view relative to its parent, in pixels.
12787     *
12788     * @return The base depth position of the view, in pixels.
12789     */
12790    @ViewDebug.ExportedProperty(category = "drawing")
12791    public float getElevation() {
12792        return mRenderNode.getElevation();
12793    }
12794
12795    /**
12796     * Sets the base elevation of this view, in pixels.
12797     *
12798     * @attr ref android.R.styleable#View_elevation
12799     */
12800    public void setElevation(float elevation) {
12801        if (elevation != getElevation()) {
12802            invalidateViewProperty(true, false);
12803            mRenderNode.setElevation(elevation);
12804            invalidateViewProperty(false, true);
12805
12806            invalidateParentIfNeededAndWasQuickRejected();
12807        }
12808    }
12809
12810    /**
12811     * The horizontal location of this view relative to its {@link #getLeft() left} position.
12812     * This position is post-layout, in addition to wherever the object's
12813     * layout placed it.
12814     *
12815     * @return The horizontal position of this view relative to its left position, in pixels.
12816     */
12817    @ViewDebug.ExportedProperty(category = "drawing")
12818    public float getTranslationX() {
12819        return mRenderNode.getTranslationX();
12820    }
12821
12822    /**
12823     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12824     * This effectively positions the object post-layout, in addition to wherever the object's
12825     * layout placed it.
12826     *
12827     * @param translationX The horizontal position of this view relative to its left position,
12828     * in pixels.
12829     *
12830     * @attr ref android.R.styleable#View_translationX
12831     */
12832    public void setTranslationX(float translationX) {
12833        if (translationX != getTranslationX()) {
12834            invalidateViewProperty(true, false);
12835            mRenderNode.setTranslationX(translationX);
12836            invalidateViewProperty(false, true);
12837
12838            invalidateParentIfNeededAndWasQuickRejected();
12839            notifySubtreeAccessibilityStateChangedIfNeeded();
12840        }
12841    }
12842
12843    /**
12844     * The vertical location of this view relative to its {@link #getTop() top} position.
12845     * This position is post-layout, in addition to wherever the object's
12846     * layout placed it.
12847     *
12848     * @return The vertical position of this view relative to its top position,
12849     * in pixels.
12850     */
12851    @ViewDebug.ExportedProperty(category = "drawing")
12852    public float getTranslationY() {
12853        return mRenderNode.getTranslationY();
12854    }
12855
12856    /**
12857     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12858     * This effectively positions the object post-layout, in addition to wherever the object's
12859     * layout placed it.
12860     *
12861     * @param translationY The vertical position of this view relative to its top position,
12862     * in pixels.
12863     *
12864     * @attr ref android.R.styleable#View_translationY
12865     */
12866    public void setTranslationY(float translationY) {
12867        if (translationY != getTranslationY()) {
12868            invalidateViewProperty(true, false);
12869            mRenderNode.setTranslationY(translationY);
12870            invalidateViewProperty(false, true);
12871
12872            invalidateParentIfNeededAndWasQuickRejected();
12873            notifySubtreeAccessibilityStateChangedIfNeeded();
12874        }
12875    }
12876
12877    /**
12878     * The depth location of this view relative to its {@link #getElevation() elevation}.
12879     *
12880     * @return The depth of this view relative to its elevation.
12881     */
12882    @ViewDebug.ExportedProperty(category = "drawing")
12883    public float getTranslationZ() {
12884        return mRenderNode.getTranslationZ();
12885    }
12886
12887    /**
12888     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12889     *
12890     * @attr ref android.R.styleable#View_translationZ
12891     */
12892    public void setTranslationZ(float translationZ) {
12893        if (translationZ != getTranslationZ()) {
12894            invalidateViewProperty(true, false);
12895            mRenderNode.setTranslationZ(translationZ);
12896            invalidateViewProperty(false, true);
12897
12898            invalidateParentIfNeededAndWasQuickRejected();
12899        }
12900    }
12901
12902    /** @hide */
12903    public void setAnimationMatrix(Matrix matrix) {
12904        invalidateViewProperty(true, false);
12905        mRenderNode.setAnimationMatrix(matrix);
12906        invalidateViewProperty(false, true);
12907
12908        invalidateParentIfNeededAndWasQuickRejected();
12909    }
12910
12911    /**
12912     * Returns the current StateListAnimator if exists.
12913     *
12914     * @return StateListAnimator or null if it does not exists
12915     * @see    #setStateListAnimator(android.animation.StateListAnimator)
12916     */
12917    public StateListAnimator getStateListAnimator() {
12918        return mStateListAnimator;
12919    }
12920
12921    /**
12922     * Attaches the provided StateListAnimator to this View.
12923     * <p>
12924     * Any previously attached StateListAnimator will be detached.
12925     *
12926     * @param stateListAnimator The StateListAnimator to update the view
12927     * @see {@link android.animation.StateListAnimator}
12928     */
12929    public void setStateListAnimator(StateListAnimator stateListAnimator) {
12930        if (mStateListAnimator == stateListAnimator) {
12931            return;
12932        }
12933        if (mStateListAnimator != null) {
12934            mStateListAnimator.setTarget(null);
12935        }
12936        mStateListAnimator = stateListAnimator;
12937        if (stateListAnimator != null) {
12938            stateListAnimator.setTarget(this);
12939            if (isAttachedToWindow()) {
12940                stateListAnimator.setState(getDrawableState());
12941            }
12942        }
12943    }
12944
12945    /**
12946     * Returns whether the Outline should be used to clip the contents of the View.
12947     * <p>
12948     * Note that this flag will only be respected if the View's Outline returns true from
12949     * {@link Outline#canClip()}.
12950     *
12951     * @see #setOutlineProvider(ViewOutlineProvider)
12952     * @see #setClipToOutline(boolean)
12953     */
12954    public final boolean getClipToOutline() {
12955        return mRenderNode.getClipToOutline();
12956    }
12957
12958    /**
12959     * Sets whether the View's Outline should be used to clip the contents of the View.
12960     * <p>
12961     * Only a single non-rectangular clip can be applied on a View at any time.
12962     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12963     * circular reveal} animation take priority over Outline clipping, and
12964     * child Outline clipping takes priority over Outline clipping done by a
12965     * parent.
12966     * <p>
12967     * Note that this flag will only be respected if the View's Outline returns true from
12968     * {@link Outline#canClip()}.
12969     *
12970     * @see #setOutlineProvider(ViewOutlineProvider)
12971     * @see #getClipToOutline()
12972     */
12973    public void setClipToOutline(boolean clipToOutline) {
12974        damageInParent();
12975        if (getClipToOutline() != clipToOutline) {
12976            mRenderNode.setClipToOutline(clipToOutline);
12977        }
12978    }
12979
12980    // correspond to the enum values of View_outlineProvider
12981    private static final int PROVIDER_BACKGROUND = 0;
12982    private static final int PROVIDER_NONE = 1;
12983    private static final int PROVIDER_BOUNDS = 2;
12984    private static final int PROVIDER_PADDED_BOUNDS = 3;
12985    private void setOutlineProviderFromAttribute(int providerInt) {
12986        switch (providerInt) {
12987            case PROVIDER_BACKGROUND:
12988                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12989                break;
12990            case PROVIDER_NONE:
12991                setOutlineProvider(null);
12992                break;
12993            case PROVIDER_BOUNDS:
12994                setOutlineProvider(ViewOutlineProvider.BOUNDS);
12995                break;
12996            case PROVIDER_PADDED_BOUNDS:
12997                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12998                break;
12999        }
13000    }
13001
13002    /**
13003     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
13004     * the shape of the shadow it casts, and enables outline clipping.
13005     * <p>
13006     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
13007     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
13008     * outline provider with this method allows this behavior to be overridden.
13009     * <p>
13010     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
13011     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
13012     * <p>
13013     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
13014     *
13015     * @see #setClipToOutline(boolean)
13016     * @see #getClipToOutline()
13017     * @see #getOutlineProvider()
13018     */
13019    public void setOutlineProvider(ViewOutlineProvider provider) {
13020        mOutlineProvider = provider;
13021        invalidateOutline();
13022    }
13023
13024    /**
13025     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
13026     * that defines the shape of the shadow it casts, and enables outline clipping.
13027     *
13028     * @see #setOutlineProvider(ViewOutlineProvider)
13029     */
13030    public ViewOutlineProvider getOutlineProvider() {
13031        return mOutlineProvider;
13032    }
13033
13034    /**
13035     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
13036     *
13037     * @see #setOutlineProvider(ViewOutlineProvider)
13038     */
13039    public void invalidateOutline() {
13040        rebuildOutline();
13041
13042        notifySubtreeAccessibilityStateChangedIfNeeded();
13043        invalidateViewProperty(false, false);
13044    }
13045
13046    /**
13047     * Internal version of {@link #invalidateOutline()} which invalidates the
13048     * outline without invalidating the view itself. This is intended to be called from
13049     * within methods in the View class itself which are the result of the view being
13050     * invalidated already. For example, when we are drawing the background of a View,
13051     * we invalidate the outline in case it changed in the meantime, but we do not
13052     * need to invalidate the view because we're already drawing the background as part
13053     * of drawing the view in response to an earlier invalidation of the view.
13054     */
13055    private void rebuildOutline() {
13056        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
13057        if (mAttachInfo == null) return;
13058
13059        if (mOutlineProvider == null) {
13060            // no provider, remove outline
13061            mRenderNode.setOutline(null);
13062        } else {
13063            final Outline outline = mAttachInfo.mTmpOutline;
13064            outline.setEmpty();
13065            outline.setAlpha(1.0f);
13066
13067            mOutlineProvider.getOutline(this, outline);
13068            mRenderNode.setOutline(outline);
13069        }
13070    }
13071
13072    /**
13073     * HierarchyViewer only
13074     *
13075     * @hide
13076     */
13077    @ViewDebug.ExportedProperty(category = "drawing")
13078    public boolean hasShadow() {
13079        return mRenderNode.hasShadow();
13080    }
13081
13082
13083    /** @hide */
13084    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
13085        mRenderNode.setRevealClip(shouldClip, x, y, radius);
13086        invalidateViewProperty(false, false);
13087    }
13088
13089    /**
13090     * Hit rectangle in parent's coordinates
13091     *
13092     * @param outRect The hit rectangle of the view.
13093     */
13094    public void getHitRect(Rect outRect) {
13095        if (hasIdentityMatrix() || mAttachInfo == null) {
13096            outRect.set(mLeft, mTop, mRight, mBottom);
13097        } else {
13098            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
13099            tmpRect.set(0, 0, getWidth(), getHeight());
13100            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
13101            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
13102                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
13103        }
13104    }
13105
13106    /**
13107     * Determines whether the given point, in local coordinates is inside the view.
13108     */
13109    /*package*/ final boolean pointInView(float localX, float localY) {
13110        return pointInView(localX, localY, 0);
13111    }
13112
13113    /**
13114     * Utility method to determine whether the given point, in local coordinates,
13115     * is inside the view, where the area of the view is expanded by the slop factor.
13116     * This method is called while processing touch-move events to determine if the event
13117     * is still within the view.
13118     *
13119     * @hide
13120     */
13121    public boolean pointInView(float localX, float localY, float slop) {
13122        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
13123                localY < ((mBottom - mTop) + slop);
13124    }
13125
13126    /**
13127     * When a view has focus and the user navigates away from it, the next view is searched for
13128     * starting from the rectangle filled in by this method.
13129     *
13130     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
13131     * of the view.  However, if your view maintains some idea of internal selection,
13132     * such as a cursor, or a selected row or column, you should override this method and
13133     * fill in a more specific rectangle.
13134     *
13135     * @param r The rectangle to fill in, in this view's coordinates.
13136     */
13137    public void getFocusedRect(Rect r) {
13138        getDrawingRect(r);
13139    }
13140
13141    /**
13142     * If some part of this view is not clipped by any of its parents, then
13143     * return that area in r in global (root) coordinates. To convert r to local
13144     * coordinates (without taking possible View rotations into account), offset
13145     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
13146     * If the view is completely clipped or translated out, return false.
13147     *
13148     * @param r If true is returned, r holds the global coordinates of the
13149     *        visible portion of this view.
13150     * @param globalOffset If true is returned, globalOffset holds the dx,dy
13151     *        between this view and its root. globalOffet may be null.
13152     * @return true if r is non-empty (i.e. part of the view is visible at the
13153     *         root level.
13154     */
13155    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
13156        int width = mRight - mLeft;
13157        int height = mBottom - mTop;
13158        if (width > 0 && height > 0) {
13159            r.set(0, 0, width, height);
13160            if (globalOffset != null) {
13161                globalOffset.set(-mScrollX, -mScrollY);
13162            }
13163            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
13164        }
13165        return false;
13166    }
13167
13168    public final boolean getGlobalVisibleRect(Rect r) {
13169        return getGlobalVisibleRect(r, null);
13170    }
13171
13172    public final boolean getLocalVisibleRect(Rect r) {
13173        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
13174        if (getGlobalVisibleRect(r, offset)) {
13175            r.offset(-offset.x, -offset.y); // make r local
13176            return true;
13177        }
13178        return false;
13179    }
13180
13181    /**
13182     * Offset this view's vertical location by the specified number of pixels.
13183     *
13184     * @param offset the number of pixels to offset the view by
13185     */
13186    public void offsetTopAndBottom(int offset) {
13187        if (offset != 0) {
13188            final boolean matrixIsIdentity = hasIdentityMatrix();
13189            if (matrixIsIdentity) {
13190                if (isHardwareAccelerated()) {
13191                    invalidateViewProperty(false, false);
13192                } else {
13193                    final ViewParent p = mParent;
13194                    if (p != null && mAttachInfo != null) {
13195                        final Rect r = mAttachInfo.mTmpInvalRect;
13196                        int minTop;
13197                        int maxBottom;
13198                        int yLoc;
13199                        if (offset < 0) {
13200                            minTop = mTop + offset;
13201                            maxBottom = mBottom;
13202                            yLoc = offset;
13203                        } else {
13204                            minTop = mTop;
13205                            maxBottom = mBottom + offset;
13206                            yLoc = 0;
13207                        }
13208                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
13209                        p.invalidateChild(this, r);
13210                    }
13211                }
13212            } else {
13213                invalidateViewProperty(false, false);
13214            }
13215
13216            mTop += offset;
13217            mBottom += offset;
13218            mRenderNode.offsetTopAndBottom(offset);
13219            if (isHardwareAccelerated()) {
13220                invalidateViewProperty(false, false);
13221                invalidateParentIfNeededAndWasQuickRejected();
13222            } else {
13223                if (!matrixIsIdentity) {
13224                    invalidateViewProperty(false, true);
13225                }
13226                invalidateParentIfNeeded();
13227            }
13228            notifySubtreeAccessibilityStateChangedIfNeeded();
13229        }
13230    }
13231
13232    /**
13233     * Offset this view's horizontal location by the specified amount of pixels.
13234     *
13235     * @param offset the number of pixels to offset the view by
13236     */
13237    public void offsetLeftAndRight(int offset) {
13238        if (offset != 0) {
13239            final boolean matrixIsIdentity = hasIdentityMatrix();
13240            if (matrixIsIdentity) {
13241                if (isHardwareAccelerated()) {
13242                    invalidateViewProperty(false, false);
13243                } else {
13244                    final ViewParent p = mParent;
13245                    if (p != null && mAttachInfo != null) {
13246                        final Rect r = mAttachInfo.mTmpInvalRect;
13247                        int minLeft;
13248                        int maxRight;
13249                        if (offset < 0) {
13250                            minLeft = mLeft + offset;
13251                            maxRight = mRight;
13252                        } else {
13253                            minLeft = mLeft;
13254                            maxRight = mRight + offset;
13255                        }
13256                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
13257                        p.invalidateChild(this, r);
13258                    }
13259                }
13260            } else {
13261                invalidateViewProperty(false, false);
13262            }
13263
13264            mLeft += offset;
13265            mRight += offset;
13266            mRenderNode.offsetLeftAndRight(offset);
13267            if (isHardwareAccelerated()) {
13268                invalidateViewProperty(false, false);
13269                invalidateParentIfNeededAndWasQuickRejected();
13270            } else {
13271                if (!matrixIsIdentity) {
13272                    invalidateViewProperty(false, true);
13273                }
13274                invalidateParentIfNeeded();
13275            }
13276            notifySubtreeAccessibilityStateChangedIfNeeded();
13277        }
13278    }
13279
13280    /**
13281     * Get the LayoutParams associated with this view. All views should have
13282     * layout parameters. These supply parameters to the <i>parent</i> of this
13283     * view specifying how it should be arranged. There are many subclasses of
13284     * ViewGroup.LayoutParams, and these correspond to the different subclasses
13285     * of ViewGroup that are responsible for arranging their children.
13286     *
13287     * This method may return null if this View is not attached to a parent
13288     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
13289     * was not invoked successfully. When a View is attached to a parent
13290     * ViewGroup, this method must not return null.
13291     *
13292     * @return The LayoutParams associated with this view, or null if no
13293     *         parameters have been set yet
13294     */
13295    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
13296    public ViewGroup.LayoutParams getLayoutParams() {
13297        return mLayoutParams;
13298    }
13299
13300    /**
13301     * Set the layout parameters associated with this view. These supply
13302     * parameters to the <i>parent</i> of this view specifying how it should be
13303     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
13304     * correspond to the different subclasses of ViewGroup that are responsible
13305     * for arranging their children.
13306     *
13307     * @param params The layout parameters for this view, cannot be null
13308     */
13309    public void setLayoutParams(ViewGroup.LayoutParams params) {
13310        if (params == null) {
13311            throw new NullPointerException("Layout parameters cannot be null");
13312        }
13313        mLayoutParams = params;
13314        resolveLayoutParams();
13315        if (mParent instanceof ViewGroup) {
13316            ((ViewGroup) mParent).onSetLayoutParams(this, params);
13317        }
13318        requestLayout();
13319    }
13320
13321    /**
13322     * Resolve the layout parameters depending on the resolved layout direction
13323     *
13324     * @hide
13325     */
13326    public void resolveLayoutParams() {
13327        if (mLayoutParams != null) {
13328            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
13329        }
13330    }
13331
13332    /**
13333     * Set the scrolled position of your view. This will cause a call to
13334     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13335     * invalidated.
13336     * @param x the x position to scroll to
13337     * @param y the y position to scroll to
13338     */
13339    public void scrollTo(int x, int y) {
13340        if (mScrollX != x || mScrollY != y) {
13341            int oldX = mScrollX;
13342            int oldY = mScrollY;
13343            mScrollX = x;
13344            mScrollY = y;
13345            invalidateParentCaches();
13346            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
13347            if (!awakenScrollBars()) {
13348                postInvalidateOnAnimation();
13349            }
13350        }
13351    }
13352
13353    /**
13354     * Move the scrolled position of your view. This will cause a call to
13355     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13356     * invalidated.
13357     * @param x the amount of pixels to scroll by horizontally
13358     * @param y the amount of pixels to scroll by vertically
13359     */
13360    public void scrollBy(int x, int y) {
13361        scrollTo(mScrollX + x, mScrollY + y);
13362    }
13363
13364    /**
13365     * <p>Trigger the scrollbars to draw. When invoked this method starts an
13366     * animation to fade the scrollbars out after a default delay. If a subclass
13367     * provides animated scrolling, the start delay should equal the duration
13368     * of the scrolling animation.</p>
13369     *
13370     * <p>The animation starts only if at least one of the scrollbars is
13371     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
13372     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13373     * this method returns true, and false otherwise. If the animation is
13374     * started, this method calls {@link #invalidate()}; in that case the
13375     * caller should not call {@link #invalidate()}.</p>
13376     *
13377     * <p>This method should be invoked every time a subclass directly updates
13378     * the scroll parameters.</p>
13379     *
13380     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
13381     * and {@link #scrollTo(int, int)}.</p>
13382     *
13383     * @return true if the animation is played, false otherwise
13384     *
13385     * @see #awakenScrollBars(int)
13386     * @see #scrollBy(int, int)
13387     * @see #scrollTo(int, int)
13388     * @see #isHorizontalScrollBarEnabled()
13389     * @see #isVerticalScrollBarEnabled()
13390     * @see #setHorizontalScrollBarEnabled(boolean)
13391     * @see #setVerticalScrollBarEnabled(boolean)
13392     */
13393    protected boolean awakenScrollBars() {
13394        return mScrollCache != null &&
13395                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
13396    }
13397
13398    /**
13399     * Trigger the scrollbars to draw.
13400     * This method differs from awakenScrollBars() only in its default duration.
13401     * initialAwakenScrollBars() will show the scroll bars for longer than
13402     * usual to give the user more of a chance to notice them.
13403     *
13404     * @return true if the animation is played, false otherwise.
13405     */
13406    private boolean initialAwakenScrollBars() {
13407        return mScrollCache != null &&
13408                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
13409    }
13410
13411    /**
13412     * <p>
13413     * Trigger the scrollbars to draw. When invoked this method starts an
13414     * animation to fade the scrollbars out after a fixed delay. If a subclass
13415     * provides animated scrolling, the start delay should equal the duration of
13416     * the scrolling animation.
13417     * </p>
13418     *
13419     * <p>
13420     * The animation starts only if at least one of the scrollbars is enabled,
13421     * as specified by {@link #isHorizontalScrollBarEnabled()} and
13422     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13423     * this method returns true, and false otherwise. If the animation is
13424     * started, this method calls {@link #invalidate()}; in that case the caller
13425     * should not call {@link #invalidate()}.
13426     * </p>
13427     *
13428     * <p>
13429     * This method should be invoked every time a subclass directly updates the
13430     * scroll parameters.
13431     * </p>
13432     *
13433     * @param startDelay the delay, in milliseconds, after which the animation
13434     *        should start; when the delay is 0, the animation starts
13435     *        immediately
13436     * @return true if the animation is played, false otherwise
13437     *
13438     * @see #scrollBy(int, int)
13439     * @see #scrollTo(int, int)
13440     * @see #isHorizontalScrollBarEnabled()
13441     * @see #isVerticalScrollBarEnabled()
13442     * @see #setHorizontalScrollBarEnabled(boolean)
13443     * @see #setVerticalScrollBarEnabled(boolean)
13444     */
13445    protected boolean awakenScrollBars(int startDelay) {
13446        return awakenScrollBars(startDelay, true);
13447    }
13448
13449    /**
13450     * <p>
13451     * Trigger the scrollbars to draw. When invoked this method starts an
13452     * animation to fade the scrollbars out after a fixed delay. If a subclass
13453     * provides animated scrolling, the start delay should equal the duration of
13454     * the scrolling animation.
13455     * </p>
13456     *
13457     * <p>
13458     * The animation starts only if at least one of the scrollbars is enabled,
13459     * as specified by {@link #isHorizontalScrollBarEnabled()} and
13460     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13461     * this method returns true, and false otherwise. If the animation is
13462     * started, this method calls {@link #invalidate()} if the invalidate parameter
13463     * is set to true; in that case the caller
13464     * should not call {@link #invalidate()}.
13465     * </p>
13466     *
13467     * <p>
13468     * This method should be invoked every time a subclass directly updates the
13469     * scroll parameters.
13470     * </p>
13471     *
13472     * @param startDelay the delay, in milliseconds, after which the animation
13473     *        should start; when the delay is 0, the animation starts
13474     *        immediately
13475     *
13476     * @param invalidate Whether this method should call invalidate
13477     *
13478     * @return true if the animation is played, false otherwise
13479     *
13480     * @see #scrollBy(int, int)
13481     * @see #scrollTo(int, int)
13482     * @see #isHorizontalScrollBarEnabled()
13483     * @see #isVerticalScrollBarEnabled()
13484     * @see #setHorizontalScrollBarEnabled(boolean)
13485     * @see #setVerticalScrollBarEnabled(boolean)
13486     */
13487    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
13488        final ScrollabilityCache scrollCache = mScrollCache;
13489
13490        if (scrollCache == null || !scrollCache.fadeScrollBars) {
13491            return false;
13492        }
13493
13494        if (scrollCache.scrollBar == null) {
13495            scrollCache.scrollBar = new ScrollBarDrawable();
13496            scrollCache.scrollBar.setState(getDrawableState());
13497            scrollCache.scrollBar.setCallback(this);
13498        }
13499
13500        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
13501
13502            if (invalidate) {
13503                // Invalidate to show the scrollbars
13504                postInvalidateOnAnimation();
13505            }
13506
13507            if (scrollCache.state == ScrollabilityCache.OFF) {
13508                // FIXME: this is copied from WindowManagerService.
13509                // We should get this value from the system when it
13510                // is possible to do so.
13511                final int KEY_REPEAT_FIRST_DELAY = 750;
13512                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
13513            }
13514
13515            // Tell mScrollCache when we should start fading. This may
13516            // extend the fade start time if one was already scheduled
13517            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
13518            scrollCache.fadeStartTime = fadeStartTime;
13519            scrollCache.state = ScrollabilityCache.ON;
13520
13521            // Schedule our fader to run, unscheduling any old ones first
13522            if (mAttachInfo != null) {
13523                mAttachInfo.mHandler.removeCallbacks(scrollCache);
13524                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
13525            }
13526
13527            return true;
13528        }
13529
13530        return false;
13531    }
13532
13533    /**
13534     * Do not invalidate views which are not visible and which are not running an animation. They
13535     * will not get drawn and they should not set dirty flags as if they will be drawn
13536     */
13537    private boolean skipInvalidate() {
13538        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
13539                (!(mParent instanceof ViewGroup) ||
13540                        !((ViewGroup) mParent).isViewTransitioning(this));
13541    }
13542
13543    /**
13544     * Mark the area defined by dirty as needing to be drawn. If the view is
13545     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13546     * point in the future.
13547     * <p>
13548     * This must be called from a UI thread. To call from a non-UI thread, call
13549     * {@link #postInvalidate()}.
13550     * <p>
13551     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
13552     * {@code dirty}.
13553     *
13554     * @param dirty the rectangle representing the bounds of the dirty region
13555     */
13556    public void invalidate(Rect dirty) {
13557        final int scrollX = mScrollX;
13558        final int scrollY = mScrollY;
13559        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
13560                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
13561    }
13562
13563    /**
13564     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
13565     * coordinates of the dirty rect are relative to the view. If the view is
13566     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13567     * point in the future.
13568     * <p>
13569     * This must be called from a UI thread. To call from a non-UI thread, call
13570     * {@link #postInvalidate()}.
13571     *
13572     * @param l the left position of the dirty region
13573     * @param t the top position of the dirty region
13574     * @param r the right position of the dirty region
13575     * @param b the bottom position of the dirty region
13576     */
13577    public void invalidate(int l, int t, int r, int b) {
13578        final int scrollX = mScrollX;
13579        final int scrollY = mScrollY;
13580        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
13581    }
13582
13583    /**
13584     * Invalidate the whole view. If the view is visible,
13585     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
13586     * the future.
13587     * <p>
13588     * This must be called from a UI thread. To call from a non-UI thread, call
13589     * {@link #postInvalidate()}.
13590     */
13591    public void invalidate() {
13592        invalidate(true);
13593    }
13594
13595    /**
13596     * This is where the invalidate() work actually happens. A full invalidate()
13597     * causes the drawing cache to be invalidated, but this function can be
13598     * called with invalidateCache set to false to skip that invalidation step
13599     * for cases that do not need it (for example, a component that remains at
13600     * the same dimensions with the same content).
13601     *
13602     * @param invalidateCache Whether the drawing cache for this view should be
13603     *            invalidated as well. This is usually true for a full
13604     *            invalidate, but may be set to false if the View's contents or
13605     *            dimensions have not changed.
13606     */
13607    void invalidate(boolean invalidateCache) {
13608        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
13609    }
13610
13611    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
13612            boolean fullInvalidate) {
13613        if (mGhostView != null) {
13614            mGhostView.invalidate(true);
13615            return;
13616        }
13617
13618        if (skipInvalidate()) {
13619            return;
13620        }
13621
13622        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
13623                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
13624                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
13625                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
13626            if (fullInvalidate) {
13627                mLastIsOpaque = isOpaque();
13628                mPrivateFlags &= ~PFLAG_DRAWN;
13629            }
13630
13631            mPrivateFlags |= PFLAG_DIRTY;
13632
13633            if (invalidateCache) {
13634                mPrivateFlags |= PFLAG_INVALIDATED;
13635                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13636            }
13637
13638            // Propagate the damage rectangle to the parent view.
13639            final AttachInfo ai = mAttachInfo;
13640            final ViewParent p = mParent;
13641            if (p != null && ai != null && l < r && t < b) {
13642                final Rect damage = ai.mTmpInvalRect;
13643                damage.set(l, t, r, b);
13644                p.invalidateChild(this, damage);
13645            }
13646
13647            // Damage the entire projection receiver, if necessary.
13648            if (mBackground != null && mBackground.isProjected()) {
13649                final View receiver = getProjectionReceiver();
13650                if (receiver != null) {
13651                    receiver.damageInParent();
13652                }
13653            }
13654
13655            // Damage the entire IsolatedZVolume receiving this view's shadow.
13656            if (isHardwareAccelerated() && getZ() != 0) {
13657                damageShadowReceiver();
13658            }
13659        }
13660    }
13661
13662    /**
13663     * @return this view's projection receiver, or {@code null} if none exists
13664     */
13665    private View getProjectionReceiver() {
13666        ViewParent p = getParent();
13667        while (p != null && p instanceof View) {
13668            final View v = (View) p;
13669            if (v.isProjectionReceiver()) {
13670                return v;
13671            }
13672            p = p.getParent();
13673        }
13674
13675        return null;
13676    }
13677
13678    /**
13679     * @return whether the view is a projection receiver
13680     */
13681    private boolean isProjectionReceiver() {
13682        return mBackground != null;
13683    }
13684
13685    /**
13686     * Damage area of the screen that can be covered by this View's shadow.
13687     *
13688     * This method will guarantee that any changes to shadows cast by a View
13689     * are damaged on the screen for future redraw.
13690     */
13691    private void damageShadowReceiver() {
13692        final AttachInfo ai = mAttachInfo;
13693        if (ai != null) {
13694            ViewParent p = getParent();
13695            if (p != null && p instanceof ViewGroup) {
13696                final ViewGroup vg = (ViewGroup) p;
13697                vg.damageInParent();
13698            }
13699        }
13700    }
13701
13702    /**
13703     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
13704     * set any flags or handle all of the cases handled by the default invalidation methods.
13705     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
13706     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
13707     * walk up the hierarchy, transforming the dirty rect as necessary.
13708     *
13709     * The method also handles normal invalidation logic if display list properties are not
13710     * being used in this view. The invalidateParent and forceRedraw flags are used by that
13711     * backup approach, to handle these cases used in the various property-setting methods.
13712     *
13713     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
13714     * are not being used in this view
13715     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
13716     * list properties are not being used in this view
13717     */
13718    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
13719        if (!isHardwareAccelerated()
13720                || !mRenderNode.isValid()
13721                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
13722            if (invalidateParent) {
13723                invalidateParentCaches();
13724            }
13725            if (forceRedraw) {
13726                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13727            }
13728            invalidate(false);
13729        } else {
13730            damageInParent();
13731        }
13732        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
13733            damageShadowReceiver();
13734        }
13735    }
13736
13737    /**
13738     * Tells the parent view to damage this view's bounds.
13739     *
13740     * @hide
13741     */
13742    protected void damageInParent() {
13743        final AttachInfo ai = mAttachInfo;
13744        final ViewParent p = mParent;
13745        if (p != null && ai != null) {
13746            final Rect r = ai.mTmpInvalRect;
13747            r.set(0, 0, mRight - mLeft, mBottom - mTop);
13748            if (mParent instanceof ViewGroup) {
13749                ((ViewGroup) mParent).damageChild(this, r);
13750            } else {
13751                mParent.invalidateChild(this, r);
13752            }
13753        }
13754    }
13755
13756    /**
13757     * Utility method to transform a given Rect by the current matrix of this view.
13758     */
13759    void transformRect(final Rect rect) {
13760        if (!getMatrix().isIdentity()) {
13761            RectF boundingRect = mAttachInfo.mTmpTransformRect;
13762            boundingRect.set(rect);
13763            getMatrix().mapRect(boundingRect);
13764            rect.set((int) Math.floor(boundingRect.left),
13765                    (int) Math.floor(boundingRect.top),
13766                    (int) Math.ceil(boundingRect.right),
13767                    (int) Math.ceil(boundingRect.bottom));
13768        }
13769    }
13770
13771    /**
13772     * Used to indicate that the parent of this view should clear its caches. This functionality
13773     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13774     * which is necessary when various parent-managed properties of the view change, such as
13775     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
13776     * clears the parent caches and does not causes an invalidate event.
13777     *
13778     * @hide
13779     */
13780    protected void invalidateParentCaches() {
13781        if (mParent instanceof View) {
13782            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
13783        }
13784    }
13785
13786    /**
13787     * Used to indicate that the parent of this view should be invalidated. This functionality
13788     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13789     * which is necessary when various parent-managed properties of the view change, such as
13790     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
13791     * an invalidation event to the parent.
13792     *
13793     * @hide
13794     */
13795    protected void invalidateParentIfNeeded() {
13796        if (isHardwareAccelerated() && mParent instanceof View) {
13797            ((View) mParent).invalidate(true);
13798        }
13799    }
13800
13801    /**
13802     * @hide
13803     */
13804    protected void invalidateParentIfNeededAndWasQuickRejected() {
13805        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
13806            // View was rejected last time it was drawn by its parent; this may have changed
13807            invalidateParentIfNeeded();
13808        }
13809    }
13810
13811    /**
13812     * Indicates whether this View is opaque. An opaque View guarantees that it will
13813     * draw all the pixels overlapping its bounds using a fully opaque color.
13814     *
13815     * Subclasses of View should override this method whenever possible to indicate
13816     * whether an instance is opaque. Opaque Views are treated in a special way by
13817     * the View hierarchy, possibly allowing it to perform optimizations during
13818     * invalidate/draw passes.
13819     *
13820     * @return True if this View is guaranteed to be fully opaque, false otherwise.
13821     */
13822    @ViewDebug.ExportedProperty(category = "drawing")
13823    public boolean isOpaque() {
13824        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13825                getFinalAlpha() >= 1.0f;
13826    }
13827
13828    /**
13829     * @hide
13830     */
13831    protected void computeOpaqueFlags() {
13832        // Opaque if:
13833        //   - Has a background
13834        //   - Background is opaque
13835        //   - Doesn't have scrollbars or scrollbars overlay
13836
13837        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13838            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13839        } else {
13840            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13841        }
13842
13843        final int flags = mViewFlags;
13844        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13845                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13846                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13847            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13848        } else {
13849            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13850        }
13851    }
13852
13853    /**
13854     * @hide
13855     */
13856    protected boolean hasOpaqueScrollbars() {
13857        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13858    }
13859
13860    /**
13861     * @return A handler associated with the thread running the View. This
13862     * handler can be used to pump events in the UI events queue.
13863     */
13864    public Handler getHandler() {
13865        final AttachInfo attachInfo = mAttachInfo;
13866        if (attachInfo != null) {
13867            return attachInfo.mHandler;
13868        }
13869        return null;
13870    }
13871
13872    /**
13873     * Returns the queue of runnable for this view.
13874     *
13875     * @return the queue of runnables for this view
13876     */
13877    private HandlerActionQueue getRunQueue() {
13878        if (mRunQueue == null) {
13879            mRunQueue = new HandlerActionQueue();
13880        }
13881        return mRunQueue;
13882    }
13883
13884    /**
13885     * Gets the view root associated with the View.
13886     * @return The view root, or null if none.
13887     * @hide
13888     */
13889    public ViewRootImpl getViewRootImpl() {
13890        if (mAttachInfo != null) {
13891            return mAttachInfo.mViewRootImpl;
13892        }
13893        return null;
13894    }
13895
13896    /**
13897     * @hide
13898     */
13899    public ThreadedRenderer getHardwareRenderer() {
13900        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
13901    }
13902
13903    /**
13904     * <p>Causes the Runnable to be added to the message queue.
13905     * The runnable will be run on the user interface thread.</p>
13906     *
13907     * @param action The Runnable that will be executed.
13908     *
13909     * @return Returns true if the Runnable was successfully placed in to the
13910     *         message queue.  Returns false on failure, usually because the
13911     *         looper processing the message queue is exiting.
13912     *
13913     * @see #postDelayed
13914     * @see #removeCallbacks
13915     */
13916    public boolean post(Runnable action) {
13917        final AttachInfo attachInfo = mAttachInfo;
13918        if (attachInfo != null) {
13919            return attachInfo.mHandler.post(action);
13920        }
13921
13922        // Postpone the runnable until we know on which thread it needs to run.
13923        // Assume that the runnable will be successfully placed after attach.
13924        getRunQueue().post(action);
13925        return true;
13926    }
13927
13928    /**
13929     * <p>Causes the Runnable to be added to the message queue, to be run
13930     * after the specified amount of time elapses.
13931     * The runnable will be run on the user interface thread.</p>
13932     *
13933     * @param action The Runnable that will be executed.
13934     * @param delayMillis The delay (in milliseconds) until the Runnable
13935     *        will be executed.
13936     *
13937     * @return true if the Runnable was successfully placed in to the
13938     *         message queue.  Returns false on failure, usually because the
13939     *         looper processing the message queue is exiting.  Note that a
13940     *         result of true does not mean the Runnable will be processed --
13941     *         if the looper is quit before the delivery time of the message
13942     *         occurs then the message will be dropped.
13943     *
13944     * @see #post
13945     * @see #removeCallbacks
13946     */
13947    public boolean postDelayed(Runnable action, long delayMillis) {
13948        final AttachInfo attachInfo = mAttachInfo;
13949        if (attachInfo != null) {
13950            return attachInfo.mHandler.postDelayed(action, delayMillis);
13951        }
13952
13953        // Postpone the runnable until we know on which thread it needs to run.
13954        // Assume that the runnable will be successfully placed after attach.
13955        getRunQueue().postDelayed(action, delayMillis);
13956        return true;
13957    }
13958
13959    /**
13960     * <p>Causes the Runnable to execute on the next animation time step.
13961     * The runnable will be run on the user interface thread.</p>
13962     *
13963     * @param action The Runnable that will be executed.
13964     *
13965     * @see #postOnAnimationDelayed
13966     * @see #removeCallbacks
13967     */
13968    public void postOnAnimation(Runnable action) {
13969        final AttachInfo attachInfo = mAttachInfo;
13970        if (attachInfo != null) {
13971            attachInfo.mViewRootImpl.mChoreographer.postCallback(
13972                    Choreographer.CALLBACK_ANIMATION, action, null);
13973        } else {
13974            // Postpone the runnable until we know
13975            // on which thread it needs to run.
13976            getRunQueue().post(action);
13977        }
13978    }
13979
13980    /**
13981     * <p>Causes the Runnable to execute on the next animation time step,
13982     * after the specified amount of time elapses.
13983     * The runnable will be run on the user interface thread.</p>
13984     *
13985     * @param action The Runnable that will be executed.
13986     * @param delayMillis The delay (in milliseconds) until the Runnable
13987     *        will be executed.
13988     *
13989     * @see #postOnAnimation
13990     * @see #removeCallbacks
13991     */
13992    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13993        final AttachInfo attachInfo = mAttachInfo;
13994        if (attachInfo != null) {
13995            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13996                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13997        } else {
13998            // Postpone the runnable until we know
13999            // on which thread it needs to run.
14000            getRunQueue().postDelayed(action, delayMillis);
14001        }
14002    }
14003
14004    /**
14005     * <p>Removes the specified Runnable from the message queue.</p>
14006     *
14007     * @param action The Runnable to remove from the message handling queue
14008     *
14009     * @return true if this view could ask the Handler to remove the Runnable,
14010     *         false otherwise. When the returned value is true, the Runnable
14011     *         may or may not have been actually removed from the message queue
14012     *         (for instance, if the Runnable was not in the queue already.)
14013     *
14014     * @see #post
14015     * @see #postDelayed
14016     * @see #postOnAnimation
14017     * @see #postOnAnimationDelayed
14018     */
14019    public boolean removeCallbacks(Runnable action) {
14020        if (action != null) {
14021            final AttachInfo attachInfo = mAttachInfo;
14022            if (attachInfo != null) {
14023                attachInfo.mHandler.removeCallbacks(action);
14024                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14025                        Choreographer.CALLBACK_ANIMATION, action, null);
14026            }
14027            getRunQueue().removeCallbacks(action);
14028        }
14029        return true;
14030    }
14031
14032    /**
14033     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
14034     * Use this to invalidate the View from a non-UI thread.</p>
14035     *
14036     * <p>This method can be invoked from outside of the UI thread
14037     * only when this View is attached to a window.</p>
14038     *
14039     * @see #invalidate()
14040     * @see #postInvalidateDelayed(long)
14041     */
14042    public void postInvalidate() {
14043        postInvalidateDelayed(0);
14044    }
14045
14046    /**
14047     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14048     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
14049     *
14050     * <p>This method can be invoked from outside of the UI thread
14051     * only when this View is attached to a window.</p>
14052     *
14053     * @param left The left coordinate of the rectangle to invalidate.
14054     * @param top The top coordinate of the rectangle to invalidate.
14055     * @param right The right coordinate of the rectangle to invalidate.
14056     * @param bottom The bottom coordinate of the rectangle to invalidate.
14057     *
14058     * @see #invalidate(int, int, int, int)
14059     * @see #invalidate(Rect)
14060     * @see #postInvalidateDelayed(long, int, int, int, int)
14061     */
14062    public void postInvalidate(int left, int top, int right, int bottom) {
14063        postInvalidateDelayed(0, left, top, right, bottom);
14064    }
14065
14066    /**
14067     * <p>Cause an invalidate to happen on a subsequent cycle through the event
14068     * loop. Waits for the specified amount of time.</p>
14069     *
14070     * <p>This method can be invoked from outside of the UI thread
14071     * only when this View is attached to a window.</p>
14072     *
14073     * @param delayMilliseconds the duration in milliseconds to delay the
14074     *         invalidation by
14075     *
14076     * @see #invalidate()
14077     * @see #postInvalidate()
14078     */
14079    public void postInvalidateDelayed(long delayMilliseconds) {
14080        // We try only with the AttachInfo because there's no point in invalidating
14081        // if we are not attached to our window
14082        final AttachInfo attachInfo = mAttachInfo;
14083        if (attachInfo != null) {
14084            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
14085        }
14086    }
14087
14088    /**
14089     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14090     * through the event loop. Waits for the specified amount of time.</p>
14091     *
14092     * <p>This method can be invoked from outside of the UI thread
14093     * only when this View is attached to a window.</p>
14094     *
14095     * @param delayMilliseconds the duration in milliseconds to delay the
14096     *         invalidation by
14097     * @param left The left coordinate of the rectangle to invalidate.
14098     * @param top The top coordinate of the rectangle to invalidate.
14099     * @param right The right coordinate of the rectangle to invalidate.
14100     * @param bottom The bottom coordinate of the rectangle to invalidate.
14101     *
14102     * @see #invalidate(int, int, int, int)
14103     * @see #invalidate(Rect)
14104     * @see #postInvalidate(int, int, int, int)
14105     */
14106    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
14107            int right, int bottom) {
14108
14109        // We try only with the AttachInfo because there's no point in invalidating
14110        // if we are not attached to our window
14111        final AttachInfo attachInfo = mAttachInfo;
14112        if (attachInfo != null) {
14113            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14114            info.target = this;
14115            info.left = left;
14116            info.top = top;
14117            info.right = right;
14118            info.bottom = bottom;
14119
14120            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
14121        }
14122    }
14123
14124    /**
14125     * <p>Cause an invalidate to happen on the next animation time step, typically the
14126     * next display frame.</p>
14127     *
14128     * <p>This method can be invoked from outside of the UI thread
14129     * only when this View is attached to a window.</p>
14130     *
14131     * @see #invalidate()
14132     */
14133    public void postInvalidateOnAnimation() {
14134        // We try only with the AttachInfo because there's no point in invalidating
14135        // if we are not attached to our window
14136        final AttachInfo attachInfo = mAttachInfo;
14137        if (attachInfo != null) {
14138            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
14139        }
14140    }
14141
14142    /**
14143     * <p>Cause an invalidate of the specified area to happen on the next animation
14144     * time step, typically the next display frame.</p>
14145     *
14146     * <p>This method can be invoked from outside of the UI thread
14147     * only when this View is attached to a window.</p>
14148     *
14149     * @param left The left coordinate of the rectangle to invalidate.
14150     * @param top The top coordinate of the rectangle to invalidate.
14151     * @param right The right coordinate of the rectangle to invalidate.
14152     * @param bottom The bottom coordinate of the rectangle to invalidate.
14153     *
14154     * @see #invalidate(int, int, int, int)
14155     * @see #invalidate(Rect)
14156     */
14157    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
14158        // We try only with the AttachInfo because there's no point in invalidating
14159        // if we are not attached to our window
14160        final AttachInfo attachInfo = mAttachInfo;
14161        if (attachInfo != null) {
14162            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14163            info.target = this;
14164            info.left = left;
14165            info.top = top;
14166            info.right = right;
14167            info.bottom = bottom;
14168
14169            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
14170        }
14171    }
14172
14173    /**
14174     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
14175     * This event is sent at most once every
14176     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
14177     */
14178    private void postSendViewScrolledAccessibilityEventCallback() {
14179        if (mSendViewScrolledAccessibilityEvent == null) {
14180            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
14181        }
14182        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
14183            mSendViewScrolledAccessibilityEvent.mIsPending = true;
14184            postDelayed(mSendViewScrolledAccessibilityEvent,
14185                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
14186        }
14187    }
14188
14189    /**
14190     * Called by a parent to request that a child update its values for mScrollX
14191     * and mScrollY if necessary. This will typically be done if the child is
14192     * animating a scroll using a {@link android.widget.Scroller Scroller}
14193     * object.
14194     */
14195    public void computeScroll() {
14196    }
14197
14198    /**
14199     * <p>Indicate whether the horizontal edges are faded when the view is
14200     * scrolled horizontally.</p>
14201     *
14202     * @return true if the horizontal edges should are faded on scroll, false
14203     *         otherwise
14204     *
14205     * @see #setHorizontalFadingEdgeEnabled(boolean)
14206     *
14207     * @attr ref android.R.styleable#View_requiresFadingEdge
14208     */
14209    public boolean isHorizontalFadingEdgeEnabled() {
14210        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
14211    }
14212
14213    /**
14214     * <p>Define whether the horizontal edges should be faded when this view
14215     * is scrolled horizontally.</p>
14216     *
14217     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
14218     *                                    be faded when the view is scrolled
14219     *                                    horizontally
14220     *
14221     * @see #isHorizontalFadingEdgeEnabled()
14222     *
14223     * @attr ref android.R.styleable#View_requiresFadingEdge
14224     */
14225    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
14226        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
14227            if (horizontalFadingEdgeEnabled) {
14228                initScrollCache();
14229            }
14230
14231            mViewFlags ^= FADING_EDGE_HORIZONTAL;
14232        }
14233    }
14234
14235    /**
14236     * <p>Indicate whether the vertical edges are faded when the view is
14237     * scrolled horizontally.</p>
14238     *
14239     * @return true if the vertical edges should are faded on scroll, false
14240     *         otherwise
14241     *
14242     * @see #setVerticalFadingEdgeEnabled(boolean)
14243     *
14244     * @attr ref android.R.styleable#View_requiresFadingEdge
14245     */
14246    public boolean isVerticalFadingEdgeEnabled() {
14247        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
14248    }
14249
14250    /**
14251     * <p>Define whether the vertical edges should be faded when this view
14252     * is scrolled vertically.</p>
14253     *
14254     * @param verticalFadingEdgeEnabled true if the vertical edges should
14255     *                                  be faded when the view is scrolled
14256     *                                  vertically
14257     *
14258     * @see #isVerticalFadingEdgeEnabled()
14259     *
14260     * @attr ref android.R.styleable#View_requiresFadingEdge
14261     */
14262    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
14263        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
14264            if (verticalFadingEdgeEnabled) {
14265                initScrollCache();
14266            }
14267
14268            mViewFlags ^= FADING_EDGE_VERTICAL;
14269        }
14270    }
14271
14272    /**
14273     * Returns the strength, or intensity, of the top faded edge. The strength is
14274     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14275     * returns 0.0 or 1.0 but no value in between.
14276     *
14277     * Subclasses should override this method to provide a smoother fade transition
14278     * when scrolling occurs.
14279     *
14280     * @return the intensity of the top fade as a float between 0.0f and 1.0f
14281     */
14282    protected float getTopFadingEdgeStrength() {
14283        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
14284    }
14285
14286    /**
14287     * Returns the strength, or intensity, of the bottom faded edge. The strength is
14288     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14289     * returns 0.0 or 1.0 but no value in between.
14290     *
14291     * Subclasses should override this method to provide a smoother fade transition
14292     * when scrolling occurs.
14293     *
14294     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
14295     */
14296    protected float getBottomFadingEdgeStrength() {
14297        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
14298                computeVerticalScrollRange() ? 1.0f : 0.0f;
14299    }
14300
14301    /**
14302     * Returns the strength, or intensity, of the left faded edge. The strength is
14303     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14304     * returns 0.0 or 1.0 but no value in between.
14305     *
14306     * Subclasses should override this method to provide a smoother fade transition
14307     * when scrolling occurs.
14308     *
14309     * @return the intensity of the left fade as a float between 0.0f and 1.0f
14310     */
14311    protected float getLeftFadingEdgeStrength() {
14312        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
14313    }
14314
14315    /**
14316     * Returns the strength, or intensity, of the right faded edge. The strength is
14317     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14318     * returns 0.0 or 1.0 but no value in between.
14319     *
14320     * Subclasses should override this method to provide a smoother fade transition
14321     * when scrolling occurs.
14322     *
14323     * @return the intensity of the right fade as a float between 0.0f and 1.0f
14324     */
14325    protected float getRightFadingEdgeStrength() {
14326        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
14327                computeHorizontalScrollRange() ? 1.0f : 0.0f;
14328    }
14329
14330    /**
14331     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
14332     * scrollbar is not drawn by default.</p>
14333     *
14334     * @return true if the horizontal scrollbar should be painted, false
14335     *         otherwise
14336     *
14337     * @see #setHorizontalScrollBarEnabled(boolean)
14338     */
14339    public boolean isHorizontalScrollBarEnabled() {
14340        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14341    }
14342
14343    /**
14344     * <p>Define whether the horizontal scrollbar should be drawn or not. The
14345     * scrollbar is not drawn by default.</p>
14346     *
14347     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
14348     *                                   be painted
14349     *
14350     * @see #isHorizontalScrollBarEnabled()
14351     */
14352    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
14353        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
14354            mViewFlags ^= SCROLLBARS_HORIZONTAL;
14355            computeOpaqueFlags();
14356            resolvePadding();
14357        }
14358    }
14359
14360    /**
14361     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
14362     * scrollbar is not drawn by default.</p>
14363     *
14364     * @return true if the vertical scrollbar should be painted, false
14365     *         otherwise
14366     *
14367     * @see #setVerticalScrollBarEnabled(boolean)
14368     */
14369    public boolean isVerticalScrollBarEnabled() {
14370        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
14371    }
14372
14373    /**
14374     * <p>Define whether the vertical scrollbar should be drawn or not. The
14375     * scrollbar is not drawn by default.</p>
14376     *
14377     * @param verticalScrollBarEnabled true if the vertical scrollbar should
14378     *                                 be painted
14379     *
14380     * @see #isVerticalScrollBarEnabled()
14381     */
14382    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
14383        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
14384            mViewFlags ^= SCROLLBARS_VERTICAL;
14385            computeOpaqueFlags();
14386            resolvePadding();
14387        }
14388    }
14389
14390    /**
14391     * @hide
14392     */
14393    protected void recomputePadding() {
14394        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14395    }
14396
14397    /**
14398     * Define whether scrollbars will fade when the view is not scrolling.
14399     *
14400     * @param fadeScrollbars whether to enable fading
14401     *
14402     * @attr ref android.R.styleable#View_fadeScrollbars
14403     */
14404    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
14405        initScrollCache();
14406        final ScrollabilityCache scrollabilityCache = mScrollCache;
14407        scrollabilityCache.fadeScrollBars = fadeScrollbars;
14408        if (fadeScrollbars) {
14409            scrollabilityCache.state = ScrollabilityCache.OFF;
14410        } else {
14411            scrollabilityCache.state = ScrollabilityCache.ON;
14412        }
14413    }
14414
14415    /**
14416     *
14417     * Returns true if scrollbars will fade when this view is not scrolling
14418     *
14419     * @return true if scrollbar fading is enabled
14420     *
14421     * @attr ref android.R.styleable#View_fadeScrollbars
14422     */
14423    public boolean isScrollbarFadingEnabled() {
14424        return mScrollCache != null && mScrollCache.fadeScrollBars;
14425    }
14426
14427    /**
14428     *
14429     * Returns the delay before scrollbars fade.
14430     *
14431     * @return the delay before scrollbars fade
14432     *
14433     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14434     */
14435    public int getScrollBarDefaultDelayBeforeFade() {
14436        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
14437                mScrollCache.scrollBarDefaultDelayBeforeFade;
14438    }
14439
14440    /**
14441     * Define the delay before scrollbars fade.
14442     *
14443     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
14444     *
14445     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14446     */
14447    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
14448        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
14449    }
14450
14451    /**
14452     *
14453     * Returns the scrollbar fade duration.
14454     *
14455     * @return the scrollbar fade duration
14456     *
14457     * @attr ref android.R.styleable#View_scrollbarFadeDuration
14458     */
14459    public int getScrollBarFadeDuration() {
14460        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
14461                mScrollCache.scrollBarFadeDuration;
14462    }
14463
14464    /**
14465     * Define the scrollbar fade duration.
14466     *
14467     * @param scrollBarFadeDuration - the scrollbar fade duration
14468     *
14469     * @attr ref android.R.styleable#View_scrollbarFadeDuration
14470     */
14471    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
14472        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
14473    }
14474
14475    /**
14476     *
14477     * Returns the scrollbar size.
14478     *
14479     * @return the scrollbar size
14480     *
14481     * @attr ref android.R.styleable#View_scrollbarSize
14482     */
14483    public int getScrollBarSize() {
14484        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
14485                mScrollCache.scrollBarSize;
14486    }
14487
14488    /**
14489     * Define the scrollbar size.
14490     *
14491     * @param scrollBarSize - the scrollbar size
14492     *
14493     * @attr ref android.R.styleable#View_scrollbarSize
14494     */
14495    public void setScrollBarSize(int scrollBarSize) {
14496        getScrollCache().scrollBarSize = scrollBarSize;
14497    }
14498
14499    /**
14500     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
14501     * inset. When inset, they add to the padding of the view. And the scrollbars
14502     * can be drawn inside the padding area or on the edge of the view. For example,
14503     * if a view has a background drawable and you want to draw the scrollbars
14504     * inside the padding specified by the drawable, you can use
14505     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
14506     * appear at the edge of the view, ignoring the padding, then you can use
14507     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
14508     * @param style the style of the scrollbars. Should be one of
14509     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
14510     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
14511     * @see #SCROLLBARS_INSIDE_OVERLAY
14512     * @see #SCROLLBARS_INSIDE_INSET
14513     * @see #SCROLLBARS_OUTSIDE_OVERLAY
14514     * @see #SCROLLBARS_OUTSIDE_INSET
14515     *
14516     * @attr ref android.R.styleable#View_scrollbarStyle
14517     */
14518    public void setScrollBarStyle(@ScrollBarStyle int style) {
14519        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
14520            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
14521            computeOpaqueFlags();
14522            resolvePadding();
14523        }
14524    }
14525
14526    /**
14527     * <p>Returns the current scrollbar style.</p>
14528     * @return the current scrollbar style
14529     * @see #SCROLLBARS_INSIDE_OVERLAY
14530     * @see #SCROLLBARS_INSIDE_INSET
14531     * @see #SCROLLBARS_OUTSIDE_OVERLAY
14532     * @see #SCROLLBARS_OUTSIDE_INSET
14533     *
14534     * @attr ref android.R.styleable#View_scrollbarStyle
14535     */
14536    @ViewDebug.ExportedProperty(mapping = {
14537            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
14538            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
14539            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
14540            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
14541    })
14542    @ScrollBarStyle
14543    public int getScrollBarStyle() {
14544        return mViewFlags & SCROLLBARS_STYLE_MASK;
14545    }
14546
14547    /**
14548     * <p>Compute the horizontal range that the horizontal scrollbar
14549     * represents.</p>
14550     *
14551     * <p>The range is expressed in arbitrary units that must be the same as the
14552     * units used by {@link #computeHorizontalScrollExtent()} and
14553     * {@link #computeHorizontalScrollOffset()}.</p>
14554     *
14555     * <p>The default range is the drawing width of this view.</p>
14556     *
14557     * @return the total horizontal range represented by the horizontal
14558     *         scrollbar
14559     *
14560     * @see #computeHorizontalScrollExtent()
14561     * @see #computeHorizontalScrollOffset()
14562     * @see android.widget.ScrollBarDrawable
14563     */
14564    protected int computeHorizontalScrollRange() {
14565        return getWidth();
14566    }
14567
14568    /**
14569     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
14570     * within the horizontal range. This value is used to compute the position
14571     * of the thumb within the scrollbar's track.</p>
14572     *
14573     * <p>The range is expressed in arbitrary units that must be the same as the
14574     * units used by {@link #computeHorizontalScrollRange()} and
14575     * {@link #computeHorizontalScrollExtent()}.</p>
14576     *
14577     * <p>The default offset is the scroll offset of this view.</p>
14578     *
14579     * @return the horizontal offset of the scrollbar's thumb
14580     *
14581     * @see #computeHorizontalScrollRange()
14582     * @see #computeHorizontalScrollExtent()
14583     * @see android.widget.ScrollBarDrawable
14584     */
14585    protected int computeHorizontalScrollOffset() {
14586        return mScrollX;
14587    }
14588
14589    /**
14590     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
14591     * within the horizontal range. This value is used to compute the length
14592     * of the thumb within the scrollbar's track.</p>
14593     *
14594     * <p>The range is expressed in arbitrary units that must be the same as the
14595     * units used by {@link #computeHorizontalScrollRange()} and
14596     * {@link #computeHorizontalScrollOffset()}.</p>
14597     *
14598     * <p>The default extent is the drawing width of this view.</p>
14599     *
14600     * @return the horizontal extent of the scrollbar's thumb
14601     *
14602     * @see #computeHorizontalScrollRange()
14603     * @see #computeHorizontalScrollOffset()
14604     * @see android.widget.ScrollBarDrawable
14605     */
14606    protected int computeHorizontalScrollExtent() {
14607        return getWidth();
14608    }
14609
14610    /**
14611     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
14612     *
14613     * <p>The range is expressed in arbitrary units that must be the same as the
14614     * units used by {@link #computeVerticalScrollExtent()} and
14615     * {@link #computeVerticalScrollOffset()}.</p>
14616     *
14617     * @return the total vertical range represented by the vertical scrollbar
14618     *
14619     * <p>The default range is the drawing height of this view.</p>
14620     *
14621     * @see #computeVerticalScrollExtent()
14622     * @see #computeVerticalScrollOffset()
14623     * @see android.widget.ScrollBarDrawable
14624     */
14625    protected int computeVerticalScrollRange() {
14626        return getHeight();
14627    }
14628
14629    /**
14630     * <p>Compute the vertical offset of the vertical scrollbar's thumb
14631     * within the horizontal range. This value is used to compute the position
14632     * of the thumb within the scrollbar's track.</p>
14633     *
14634     * <p>The range is expressed in arbitrary units that must be the same as the
14635     * units used by {@link #computeVerticalScrollRange()} and
14636     * {@link #computeVerticalScrollExtent()}.</p>
14637     *
14638     * <p>The default offset is the scroll offset of this view.</p>
14639     *
14640     * @return the vertical offset of the scrollbar's thumb
14641     *
14642     * @see #computeVerticalScrollRange()
14643     * @see #computeVerticalScrollExtent()
14644     * @see android.widget.ScrollBarDrawable
14645     */
14646    protected int computeVerticalScrollOffset() {
14647        return mScrollY;
14648    }
14649
14650    /**
14651     * <p>Compute the vertical extent of the vertical scrollbar's thumb
14652     * within the vertical range. This value is used to compute the length
14653     * of the thumb within the scrollbar's track.</p>
14654     *
14655     * <p>The range is expressed in arbitrary units that must be the same as the
14656     * units used by {@link #computeVerticalScrollRange()} and
14657     * {@link #computeVerticalScrollOffset()}.</p>
14658     *
14659     * <p>The default extent is the drawing height of this view.</p>
14660     *
14661     * @return the vertical extent of the scrollbar's thumb
14662     *
14663     * @see #computeVerticalScrollRange()
14664     * @see #computeVerticalScrollOffset()
14665     * @see android.widget.ScrollBarDrawable
14666     */
14667    protected int computeVerticalScrollExtent() {
14668        return getHeight();
14669    }
14670
14671    /**
14672     * Check if this view can be scrolled horizontally in a certain direction.
14673     *
14674     * @param direction Negative to check scrolling left, positive to check scrolling right.
14675     * @return true if this view can be scrolled in the specified direction, false otherwise.
14676     */
14677    public boolean canScrollHorizontally(int direction) {
14678        final int offset = computeHorizontalScrollOffset();
14679        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
14680        if (range == 0) return false;
14681        if (direction < 0) {
14682            return offset > 0;
14683        } else {
14684            return offset < range - 1;
14685        }
14686    }
14687
14688    /**
14689     * Check if this view can be scrolled vertically in a certain direction.
14690     *
14691     * @param direction Negative to check scrolling up, positive to check scrolling down.
14692     * @return true if this view can be scrolled in the specified direction, false otherwise.
14693     */
14694    public boolean canScrollVertically(int direction) {
14695        final int offset = computeVerticalScrollOffset();
14696        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
14697        if (range == 0) return false;
14698        if (direction < 0) {
14699            return offset > 0;
14700        } else {
14701            return offset < range - 1;
14702        }
14703    }
14704
14705    void getScrollIndicatorBounds(@NonNull Rect out) {
14706        out.left = mScrollX;
14707        out.right = mScrollX + mRight - mLeft;
14708        out.top = mScrollY;
14709        out.bottom = mScrollY + mBottom - mTop;
14710    }
14711
14712    private void onDrawScrollIndicators(Canvas c) {
14713        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
14714            // No scroll indicators enabled.
14715            return;
14716        }
14717
14718        final Drawable dr = mScrollIndicatorDrawable;
14719        if (dr == null) {
14720            // Scroll indicators aren't supported here.
14721            return;
14722        }
14723
14724        final int h = dr.getIntrinsicHeight();
14725        final int w = dr.getIntrinsicWidth();
14726        final Rect rect = mAttachInfo.mTmpInvalRect;
14727        getScrollIndicatorBounds(rect);
14728
14729        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
14730            final boolean canScrollUp = canScrollVertically(-1);
14731            if (canScrollUp) {
14732                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
14733                dr.draw(c);
14734            }
14735        }
14736
14737        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
14738            final boolean canScrollDown = canScrollVertically(1);
14739            if (canScrollDown) {
14740                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
14741                dr.draw(c);
14742            }
14743        }
14744
14745        final int leftRtl;
14746        final int rightRtl;
14747        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14748            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
14749            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
14750        } else {
14751            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
14752            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
14753        }
14754
14755        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
14756        if ((mPrivateFlags3 & leftMask) != 0) {
14757            final boolean canScrollLeft = canScrollHorizontally(-1);
14758            if (canScrollLeft) {
14759                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
14760                dr.draw(c);
14761            }
14762        }
14763
14764        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
14765        if ((mPrivateFlags3 & rightMask) != 0) {
14766            final boolean canScrollRight = canScrollHorizontally(1);
14767            if (canScrollRight) {
14768                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
14769                dr.draw(c);
14770            }
14771        }
14772    }
14773
14774    private void getHorizontalScrollBarBounds(Rect bounds) {
14775        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14776        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14777                && !isVerticalScrollBarHidden();
14778        final int size = getHorizontalScrollbarHeight();
14779        final int verticalScrollBarGap = drawVerticalScrollBar ?
14780                getVerticalScrollbarWidth() : 0;
14781        final int width = mRight - mLeft;
14782        final int height = mBottom - mTop;
14783        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
14784        bounds.left = mScrollX + (mPaddingLeft & inside);
14785        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14786        bounds.bottom = bounds.top + size;
14787    }
14788
14789    private void getVerticalScrollBarBounds(Rect bounds) {
14790        if (mRoundScrollbarRenderer == null) {
14791            getStraightVerticalScrollBarBounds(bounds);
14792        } else {
14793            getRoundVerticalScrollBarBounds(bounds);
14794        }
14795    }
14796
14797    private void getRoundVerticalScrollBarBounds(Rect bounds) {
14798        final int width = mRight - mLeft;
14799        final int height = mBottom - mTop;
14800        // Do not take padding into account as we always want the scrollbars
14801        // to hug the screen for round wearable devices.
14802        bounds.left = mScrollX;
14803        bounds.top = mScrollY;
14804        bounds.right = bounds.left + width;
14805        bounds.bottom = mScrollY + height;
14806    }
14807
14808    private void getStraightVerticalScrollBarBounds(Rect bounds) {
14809        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14810        final int size = getVerticalScrollbarWidth();
14811        int verticalScrollbarPosition = mVerticalScrollbarPosition;
14812        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14813            verticalScrollbarPosition = isLayoutRtl() ?
14814                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14815        }
14816        final int width = mRight - mLeft;
14817        final int height = mBottom - mTop;
14818        switch (verticalScrollbarPosition) {
14819            default:
14820            case SCROLLBAR_POSITION_RIGHT:
14821                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
14822                break;
14823            case SCROLLBAR_POSITION_LEFT:
14824                bounds.left = mScrollX + (mUserPaddingLeft & inside);
14825                break;
14826        }
14827        bounds.top = mScrollY + (mPaddingTop & inside);
14828        bounds.right = bounds.left + size;
14829        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
14830    }
14831
14832    /**
14833     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
14834     * scrollbars are painted only if they have been awakened first.</p>
14835     *
14836     * @param canvas the canvas on which to draw the scrollbars
14837     *
14838     * @see #awakenScrollBars(int)
14839     */
14840    protected final void onDrawScrollBars(Canvas canvas) {
14841        // scrollbars are drawn only when the animation is running
14842        final ScrollabilityCache cache = mScrollCache;
14843
14844        if (cache != null) {
14845
14846            int state = cache.state;
14847
14848            if (state == ScrollabilityCache.OFF) {
14849                return;
14850            }
14851
14852            boolean invalidate = false;
14853
14854            if (state == ScrollabilityCache.FADING) {
14855                // We're fading -- get our fade interpolation
14856                if (cache.interpolatorValues == null) {
14857                    cache.interpolatorValues = new float[1];
14858                }
14859
14860                float[] values = cache.interpolatorValues;
14861
14862                // Stops the animation if we're done
14863                if (cache.scrollBarInterpolator.timeToValues(values) ==
14864                        Interpolator.Result.FREEZE_END) {
14865                    cache.state = ScrollabilityCache.OFF;
14866                } else {
14867                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14868                }
14869
14870                // This will make the scroll bars inval themselves after
14871                // drawing. We only want this when we're fading so that
14872                // we prevent excessive redraws
14873                invalidate = true;
14874            } else {
14875                // We're just on -- but we may have been fading before so
14876                // reset alpha
14877                cache.scrollBar.mutate().setAlpha(255);
14878            }
14879
14880            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
14881            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
14882                    && !isVerticalScrollBarHidden();
14883
14884            // Fork out the scroll bar drawing for round wearable devices.
14885            if (mRoundScrollbarRenderer != null) {
14886                if (drawVerticalScrollBar) {
14887                    final Rect bounds = cache.mScrollBarBounds;
14888                    getVerticalScrollBarBounds(bounds);
14889                    mRoundScrollbarRenderer.drawRoundScrollbars(
14890                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
14891                    if (invalidate) {
14892                        invalidate();
14893                    }
14894                }
14895                // Do not draw horizontal scroll bars for round wearable devices.
14896            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14897                final ScrollBarDrawable scrollBar = cache.scrollBar;
14898
14899                if (drawHorizontalScrollBar) {
14900                    scrollBar.setParameters(computeHorizontalScrollRange(),
14901                            computeHorizontalScrollOffset(),
14902                            computeHorizontalScrollExtent(), false);
14903                    final Rect bounds = cache.mScrollBarBounds;
14904                    getHorizontalScrollBarBounds(bounds);
14905                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14906                            bounds.right, bounds.bottom);
14907                    if (invalidate) {
14908                        invalidate(bounds);
14909                    }
14910                }
14911
14912                if (drawVerticalScrollBar) {
14913                    scrollBar.setParameters(computeVerticalScrollRange(),
14914                            computeVerticalScrollOffset(),
14915                            computeVerticalScrollExtent(), true);
14916                    final Rect bounds = cache.mScrollBarBounds;
14917                    getVerticalScrollBarBounds(bounds);
14918                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
14919                            bounds.right, bounds.bottom);
14920                    if (invalidate) {
14921                        invalidate(bounds);
14922                    }
14923                }
14924            }
14925        }
14926    }
14927
14928    /**
14929     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14930     * FastScroller is visible.
14931     * @return whether to temporarily hide the vertical scrollbar
14932     * @hide
14933     */
14934    protected boolean isVerticalScrollBarHidden() {
14935        return false;
14936    }
14937
14938    /**
14939     * <p>Draw the horizontal scrollbar if
14940     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14941     *
14942     * @param canvas the canvas on which to draw the scrollbar
14943     * @param scrollBar the scrollbar's drawable
14944     *
14945     * @see #isHorizontalScrollBarEnabled()
14946     * @see #computeHorizontalScrollRange()
14947     * @see #computeHorizontalScrollExtent()
14948     * @see #computeHorizontalScrollOffset()
14949     * @see android.widget.ScrollBarDrawable
14950     * @hide
14951     */
14952    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14953            int l, int t, int r, int b) {
14954        scrollBar.setBounds(l, t, r, b);
14955        scrollBar.draw(canvas);
14956    }
14957
14958    /**
14959     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14960     * returns true.</p>
14961     *
14962     * @param canvas the canvas on which to draw the scrollbar
14963     * @param scrollBar the scrollbar's drawable
14964     *
14965     * @see #isVerticalScrollBarEnabled()
14966     * @see #computeVerticalScrollRange()
14967     * @see #computeVerticalScrollExtent()
14968     * @see #computeVerticalScrollOffset()
14969     * @see android.widget.ScrollBarDrawable
14970     * @hide
14971     */
14972    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14973            int l, int t, int r, int b) {
14974        scrollBar.setBounds(l, t, r, b);
14975        scrollBar.draw(canvas);
14976    }
14977
14978    /**
14979     * Implement this to do your drawing.
14980     *
14981     * @param canvas the canvas on which the background will be drawn
14982     */
14983    protected void onDraw(Canvas canvas) {
14984    }
14985
14986    /*
14987     * Caller is responsible for calling requestLayout if necessary.
14988     * (This allows addViewInLayout to not request a new layout.)
14989     */
14990    void assignParent(ViewParent parent) {
14991        if (mParent == null) {
14992            mParent = parent;
14993        } else if (parent == null) {
14994            mParent = null;
14995        } else {
14996            throw new RuntimeException("view " + this + " being added, but"
14997                    + " it already has a parent");
14998        }
14999    }
15000
15001    /**
15002     * This is called when the view is attached to a window.  At this point it
15003     * has a Surface and will start drawing.  Note that this function is
15004     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
15005     * however it may be called any time before the first onDraw -- including
15006     * before or after {@link #onMeasure(int, int)}.
15007     *
15008     * @see #onDetachedFromWindow()
15009     */
15010    @CallSuper
15011    protected void onAttachedToWindow() {
15012        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
15013            mParent.requestTransparentRegion(this);
15014        }
15015
15016        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15017
15018        jumpDrawablesToCurrentState();
15019
15020        resetSubtreeAccessibilityStateChanged();
15021
15022        // rebuild, since Outline not maintained while View is detached
15023        rebuildOutline();
15024
15025        if (isFocused()) {
15026            InputMethodManager imm = InputMethodManager.peekInstance();
15027            if (imm != null) {
15028                imm.focusIn(this);
15029            }
15030        }
15031    }
15032
15033    /**
15034     * Resolve all RTL related properties.
15035     *
15036     * @return true if resolution of RTL properties has been done
15037     *
15038     * @hide
15039     */
15040    public boolean resolveRtlPropertiesIfNeeded() {
15041        if (!needRtlPropertiesResolution()) return false;
15042
15043        // Order is important here: LayoutDirection MUST be resolved first
15044        if (!isLayoutDirectionResolved()) {
15045            resolveLayoutDirection();
15046            resolveLayoutParams();
15047        }
15048        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
15049        if (!isTextDirectionResolved()) {
15050            resolveTextDirection();
15051        }
15052        if (!isTextAlignmentResolved()) {
15053            resolveTextAlignment();
15054        }
15055        // Should resolve Drawables before Padding because we need the layout direction of the
15056        // Drawable to correctly resolve Padding.
15057        if (!areDrawablesResolved()) {
15058            resolveDrawables();
15059        }
15060        if (!isPaddingResolved()) {
15061            resolvePadding();
15062        }
15063        onRtlPropertiesChanged(getLayoutDirection());
15064        return true;
15065    }
15066
15067    /**
15068     * Reset resolution of all RTL related properties.
15069     *
15070     * @hide
15071     */
15072    public void resetRtlProperties() {
15073        resetResolvedLayoutDirection();
15074        resetResolvedTextDirection();
15075        resetResolvedTextAlignment();
15076        resetResolvedPadding();
15077        resetResolvedDrawables();
15078    }
15079
15080    /**
15081     * @see #onScreenStateChanged(int)
15082     */
15083    void dispatchScreenStateChanged(int screenState) {
15084        onScreenStateChanged(screenState);
15085    }
15086
15087    /**
15088     * This method is called whenever the state of the screen this view is
15089     * attached to changes. A state change will usually occurs when the screen
15090     * turns on or off (whether it happens automatically or the user does it
15091     * manually.)
15092     *
15093     * @param screenState The new state of the screen. Can be either
15094     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
15095     */
15096    public void onScreenStateChanged(int screenState) {
15097    }
15098
15099    /**
15100     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
15101     */
15102    private boolean hasRtlSupport() {
15103        return mContext.getApplicationInfo().hasRtlSupport();
15104    }
15105
15106    /**
15107     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
15108     * RTL not supported)
15109     */
15110    private boolean isRtlCompatibilityMode() {
15111        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
15112        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
15113    }
15114
15115    /**
15116     * @return true if RTL properties need resolution.
15117     *
15118     */
15119    private boolean needRtlPropertiesResolution() {
15120        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
15121    }
15122
15123    /**
15124     * Called when any RTL property (layout direction or text direction or text alignment) has
15125     * been changed.
15126     *
15127     * Subclasses need to override this method to take care of cached information that depends on the
15128     * resolved layout direction, or to inform child views that inherit their layout direction.
15129     *
15130     * The default implementation does nothing.
15131     *
15132     * @param layoutDirection the direction of the layout
15133     *
15134     * @see #LAYOUT_DIRECTION_LTR
15135     * @see #LAYOUT_DIRECTION_RTL
15136     */
15137    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
15138    }
15139
15140    /**
15141     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
15142     * that the parent directionality can and will be resolved before its children.
15143     *
15144     * @return true if resolution has been done, false otherwise.
15145     *
15146     * @hide
15147     */
15148    public boolean resolveLayoutDirection() {
15149        // Clear any previous layout direction resolution
15150        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15151
15152        if (hasRtlSupport()) {
15153            // Set resolved depending on layout direction
15154            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
15155                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
15156                case LAYOUT_DIRECTION_INHERIT:
15157                    // We cannot resolve yet. LTR is by default and let the resolution happen again
15158                    // later to get the correct resolved value
15159                    if (!canResolveLayoutDirection()) return false;
15160
15161                    // Parent has not yet resolved, LTR is still the default
15162                    try {
15163                        if (!mParent.isLayoutDirectionResolved()) return false;
15164
15165                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15166                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15167                        }
15168                    } catch (AbstractMethodError e) {
15169                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15170                                " does not fully implement ViewParent", e);
15171                    }
15172                    break;
15173                case LAYOUT_DIRECTION_RTL:
15174                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15175                    break;
15176                case LAYOUT_DIRECTION_LOCALE:
15177                    if((LAYOUT_DIRECTION_RTL ==
15178                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
15179                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15180                    }
15181                    break;
15182                default:
15183                    // Nothing to do, LTR by default
15184            }
15185        }
15186
15187        // Set to resolved
15188        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15189        return true;
15190    }
15191
15192    /**
15193     * Check if layout direction resolution can be done.
15194     *
15195     * @return true if layout direction resolution can be done otherwise return false.
15196     */
15197    public boolean canResolveLayoutDirection() {
15198        switch (getRawLayoutDirection()) {
15199            case LAYOUT_DIRECTION_INHERIT:
15200                if (mParent != null) {
15201                    try {
15202                        return mParent.canResolveLayoutDirection();
15203                    } catch (AbstractMethodError e) {
15204                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15205                                " does not fully implement ViewParent", e);
15206                    }
15207                }
15208                return false;
15209
15210            default:
15211                return true;
15212        }
15213    }
15214
15215    /**
15216     * Reset the resolved layout direction. Layout direction will be resolved during a call to
15217     * {@link #onMeasure(int, int)}.
15218     *
15219     * @hide
15220     */
15221    public void resetResolvedLayoutDirection() {
15222        // Reset the current resolved bits
15223        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15224    }
15225
15226    /**
15227     * @return true if the layout direction is inherited.
15228     *
15229     * @hide
15230     */
15231    public boolean isLayoutDirectionInherited() {
15232        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
15233    }
15234
15235    /**
15236     * @return true if layout direction has been resolved.
15237     */
15238    public boolean isLayoutDirectionResolved() {
15239        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15240    }
15241
15242    /**
15243     * Return if padding has been resolved
15244     *
15245     * @hide
15246     */
15247    boolean isPaddingResolved() {
15248        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
15249    }
15250
15251    /**
15252     * Resolves padding depending on layout direction, if applicable, and
15253     * recomputes internal padding values to adjust for scroll bars.
15254     *
15255     * @hide
15256     */
15257    public void resolvePadding() {
15258        final int resolvedLayoutDirection = getLayoutDirection();
15259
15260        if (!isRtlCompatibilityMode()) {
15261            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
15262            // If start / end padding are defined, they will be resolved (hence overriding) to
15263            // left / right or right / left depending on the resolved layout direction.
15264            // If start / end padding are not defined, use the left / right ones.
15265            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
15266                Rect padding = sThreadLocal.get();
15267                if (padding == null) {
15268                    padding = new Rect();
15269                    sThreadLocal.set(padding);
15270                }
15271                mBackground.getPadding(padding);
15272                if (!mLeftPaddingDefined) {
15273                    mUserPaddingLeftInitial = padding.left;
15274                }
15275                if (!mRightPaddingDefined) {
15276                    mUserPaddingRightInitial = padding.right;
15277                }
15278            }
15279            switch (resolvedLayoutDirection) {
15280                case LAYOUT_DIRECTION_RTL:
15281                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15282                        mUserPaddingRight = mUserPaddingStart;
15283                    } else {
15284                        mUserPaddingRight = mUserPaddingRightInitial;
15285                    }
15286                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15287                        mUserPaddingLeft = mUserPaddingEnd;
15288                    } else {
15289                        mUserPaddingLeft = mUserPaddingLeftInitial;
15290                    }
15291                    break;
15292                case LAYOUT_DIRECTION_LTR:
15293                default:
15294                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15295                        mUserPaddingLeft = mUserPaddingStart;
15296                    } else {
15297                        mUserPaddingLeft = mUserPaddingLeftInitial;
15298                    }
15299                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15300                        mUserPaddingRight = mUserPaddingEnd;
15301                    } else {
15302                        mUserPaddingRight = mUserPaddingRightInitial;
15303                    }
15304            }
15305
15306            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
15307        }
15308
15309        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15310        onRtlPropertiesChanged(resolvedLayoutDirection);
15311
15312        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
15313    }
15314
15315    /**
15316     * Reset the resolved layout direction.
15317     *
15318     * @hide
15319     */
15320    public void resetResolvedPadding() {
15321        resetResolvedPaddingInternal();
15322    }
15323
15324    /**
15325     * Used when we only want to reset *this* view's padding and not trigger overrides
15326     * in ViewGroup that reset children too.
15327     */
15328    void resetResolvedPaddingInternal() {
15329        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
15330    }
15331
15332    /**
15333     * This is called when the view is detached from a window.  At this point it
15334     * no longer has a surface for drawing.
15335     *
15336     * @see #onAttachedToWindow()
15337     */
15338    @CallSuper
15339    protected void onDetachedFromWindow() {
15340    }
15341
15342    /**
15343     * This is a framework-internal mirror of onDetachedFromWindow() that's called
15344     * after onDetachedFromWindow().
15345     *
15346     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
15347     * The super method should be called at the end of the overridden method to ensure
15348     * subclasses are destroyed first
15349     *
15350     * @hide
15351     */
15352    @CallSuper
15353    protected void onDetachedFromWindowInternal() {
15354        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
15355        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15356        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
15357
15358        removeUnsetPressCallback();
15359        removeLongPressCallback();
15360        removePerformClickCallback();
15361        removeSendViewScrolledAccessibilityEventCallback();
15362        stopNestedScroll();
15363
15364        // Anything that started animating right before detach should already
15365        // be in its final state when re-attached.
15366        jumpDrawablesToCurrentState();
15367
15368        destroyDrawingCache();
15369
15370        cleanupDraw();
15371        mCurrentAnimation = null;
15372    }
15373
15374    private void cleanupDraw() {
15375        resetDisplayList();
15376        if (mAttachInfo != null) {
15377            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
15378        }
15379    }
15380
15381    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
15382    }
15383
15384    /**
15385     * @return The number of times this view has been attached to a window
15386     */
15387    protected int getWindowAttachCount() {
15388        return mWindowAttachCount;
15389    }
15390
15391    /**
15392     * Retrieve a unique token identifying the window this view is attached to.
15393     * @return Return the window's token for use in
15394     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
15395     */
15396    public IBinder getWindowToken() {
15397        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
15398    }
15399
15400    /**
15401     * Retrieve the {@link WindowId} for the window this view is
15402     * currently attached to.
15403     */
15404    public WindowId getWindowId() {
15405        if (mAttachInfo == null) {
15406            return null;
15407        }
15408        if (mAttachInfo.mWindowId == null) {
15409            try {
15410                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
15411                        mAttachInfo.mWindowToken);
15412                mAttachInfo.mWindowId = new WindowId(
15413                        mAttachInfo.mIWindowId);
15414            } catch (RemoteException e) {
15415            }
15416        }
15417        return mAttachInfo.mWindowId;
15418    }
15419
15420    /**
15421     * Retrieve a unique token identifying the top-level "real" window of
15422     * the window that this view is attached to.  That is, this is like
15423     * {@link #getWindowToken}, except if the window this view in is a panel
15424     * window (attached to another containing window), then the token of
15425     * the containing window is returned instead.
15426     *
15427     * @return Returns the associated window token, either
15428     * {@link #getWindowToken()} or the containing window's token.
15429     */
15430    public IBinder getApplicationWindowToken() {
15431        AttachInfo ai = mAttachInfo;
15432        if (ai != null) {
15433            IBinder appWindowToken = ai.mPanelParentWindowToken;
15434            if (appWindowToken == null) {
15435                appWindowToken = ai.mWindowToken;
15436            }
15437            return appWindowToken;
15438        }
15439        return null;
15440    }
15441
15442    /**
15443     * Gets the logical display to which the view's window has been attached.
15444     *
15445     * @return The logical display, or null if the view is not currently attached to a window.
15446     */
15447    public Display getDisplay() {
15448        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
15449    }
15450
15451    /**
15452     * Retrieve private session object this view hierarchy is using to
15453     * communicate with the window manager.
15454     * @return the session object to communicate with the window manager
15455     */
15456    /*package*/ IWindowSession getWindowSession() {
15457        return mAttachInfo != null ? mAttachInfo.mSession : null;
15458    }
15459
15460    /**
15461     * Return the visibility value of the least visible component passed.
15462     */
15463    int combineVisibility(int vis1, int vis2) {
15464        // This works because VISIBLE < INVISIBLE < GONE.
15465        return Math.max(vis1, vis2);
15466    }
15467
15468    /**
15469     * @param info the {@link android.view.View.AttachInfo} to associated with
15470     *        this view
15471     */
15472    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
15473        mAttachInfo = info;
15474        if (mOverlay != null) {
15475            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
15476        }
15477        mWindowAttachCount++;
15478        // We will need to evaluate the drawable state at least once.
15479        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15480        if (mFloatingTreeObserver != null) {
15481            info.mTreeObserver.merge(mFloatingTreeObserver);
15482            mFloatingTreeObserver = null;
15483        }
15484
15485        registerPendingFrameMetricsObservers();
15486
15487        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
15488            mAttachInfo.mScrollContainers.add(this);
15489            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
15490        }
15491        // Transfer all pending runnables.
15492        if (mRunQueue != null) {
15493            mRunQueue.executeActions(info.mHandler);
15494            mRunQueue = null;
15495        }
15496        performCollectViewAttributes(mAttachInfo, visibility);
15497        onAttachedToWindow();
15498
15499        ListenerInfo li = mListenerInfo;
15500        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15501                li != null ? li.mOnAttachStateChangeListeners : null;
15502        if (listeners != null && listeners.size() > 0) {
15503            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15504            // perform the dispatching. The iterator is a safe guard against listeners that
15505            // could mutate the list by calling the various add/remove methods. This prevents
15506            // the array from being modified while we iterate it.
15507            for (OnAttachStateChangeListener listener : listeners) {
15508                listener.onViewAttachedToWindow(this);
15509            }
15510        }
15511
15512        int vis = info.mWindowVisibility;
15513        if (vis != GONE) {
15514            onWindowVisibilityChanged(vis);
15515            if (isShown()) {
15516                // Calling onVisibilityChanged directly here since the subtree will also
15517                // receive dispatchAttachedToWindow and this same call
15518                onVisibilityAggregated(vis == VISIBLE);
15519            }
15520        }
15521
15522        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
15523        // As all views in the subtree will already receive dispatchAttachedToWindow
15524        // traversing the subtree again here is not desired.
15525        onVisibilityChanged(this, visibility);
15526
15527        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
15528            // If nobody has evaluated the drawable state yet, then do it now.
15529            refreshDrawableState();
15530        }
15531        needGlobalAttributesUpdate(false);
15532    }
15533
15534    void dispatchDetachedFromWindow() {
15535        AttachInfo info = mAttachInfo;
15536        if (info != null) {
15537            int vis = info.mWindowVisibility;
15538            if (vis != GONE) {
15539                onWindowVisibilityChanged(GONE);
15540                if (isShown()) {
15541                    // Invoking onVisibilityAggregated directly here since the subtree
15542                    // will also receive detached from window
15543                    onVisibilityAggregated(false);
15544                }
15545            }
15546        }
15547
15548        onDetachedFromWindow();
15549        onDetachedFromWindowInternal();
15550
15551        InputMethodManager imm = InputMethodManager.peekInstance();
15552        if (imm != null) {
15553            imm.onViewDetachedFromWindow(this);
15554        }
15555
15556        ListenerInfo li = mListenerInfo;
15557        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15558                li != null ? li.mOnAttachStateChangeListeners : null;
15559        if (listeners != null && listeners.size() > 0) {
15560            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15561            // perform the dispatching. The iterator is a safe guard against listeners that
15562            // could mutate the list by calling the various add/remove methods. This prevents
15563            // the array from being modified while we iterate it.
15564            for (OnAttachStateChangeListener listener : listeners) {
15565                listener.onViewDetachedFromWindow(this);
15566            }
15567        }
15568
15569        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
15570            mAttachInfo.mScrollContainers.remove(this);
15571            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
15572        }
15573
15574        mAttachInfo = null;
15575        if (mOverlay != null) {
15576            mOverlay.getOverlayView().dispatchDetachedFromWindow();
15577        }
15578    }
15579
15580    /**
15581     * Cancel any deferred high-level input events that were previously posted to the event queue.
15582     *
15583     * <p>Many views post high-level events such as click handlers to the event queue
15584     * to run deferred in order to preserve a desired user experience - clearing visible
15585     * pressed states before executing, etc. This method will abort any events of this nature
15586     * that are currently in flight.</p>
15587     *
15588     * <p>Custom views that generate their own high-level deferred input events should override
15589     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
15590     *
15591     * <p>This will also cancel pending input events for any child views.</p>
15592     *
15593     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
15594     * This will not impact newer events posted after this call that may occur as a result of
15595     * lower-level input events still waiting in the queue. If you are trying to prevent
15596     * double-submitted  events for the duration of some sort of asynchronous transaction
15597     * you should also take other steps to protect against unexpected double inputs e.g. calling
15598     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
15599     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
15600     */
15601    public final void cancelPendingInputEvents() {
15602        dispatchCancelPendingInputEvents();
15603    }
15604
15605    /**
15606     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
15607     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
15608     */
15609    void dispatchCancelPendingInputEvents() {
15610        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
15611        onCancelPendingInputEvents();
15612        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
15613            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
15614                    " did not call through to super.onCancelPendingInputEvents()");
15615        }
15616    }
15617
15618    /**
15619     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
15620     * a parent view.
15621     *
15622     * <p>This method is responsible for removing any pending high-level input events that were
15623     * posted to the event queue to run later. Custom view classes that post their own deferred
15624     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
15625     * {@link android.os.Handler} should override this method, call
15626     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
15627     * </p>
15628     */
15629    public void onCancelPendingInputEvents() {
15630        removePerformClickCallback();
15631        cancelLongPress();
15632        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
15633    }
15634
15635    /**
15636     * Store this view hierarchy's frozen state into the given container.
15637     *
15638     * @param container The SparseArray in which to save the view's state.
15639     *
15640     * @see #restoreHierarchyState(android.util.SparseArray)
15641     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15642     * @see #onSaveInstanceState()
15643     */
15644    public void saveHierarchyState(SparseArray<Parcelable> container) {
15645        dispatchSaveInstanceState(container);
15646    }
15647
15648    /**
15649     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
15650     * this view and its children. May be overridden to modify how freezing happens to a
15651     * view's children; for example, some views may want to not store state for their children.
15652     *
15653     * @param container The SparseArray in which to save the view's state.
15654     *
15655     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15656     * @see #saveHierarchyState(android.util.SparseArray)
15657     * @see #onSaveInstanceState()
15658     */
15659    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
15660        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
15661            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15662            Parcelable state = onSaveInstanceState();
15663            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15664                throw new IllegalStateException(
15665                        "Derived class did not call super.onSaveInstanceState()");
15666            }
15667            if (state != null) {
15668                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
15669                // + ": " + state);
15670                container.put(mID, state);
15671            }
15672        }
15673    }
15674
15675    /**
15676     * Hook allowing a view to generate a representation of its internal state
15677     * that can later be used to create a new instance with that same state.
15678     * This state should only contain information that is not persistent or can
15679     * not be reconstructed later. For example, you will never store your
15680     * current position on screen because that will be computed again when a
15681     * new instance of the view is placed in its view hierarchy.
15682     * <p>
15683     * Some examples of things you may store here: the current cursor position
15684     * in a text view (but usually not the text itself since that is stored in a
15685     * content provider or other persistent storage), the currently selected
15686     * item in a list view.
15687     *
15688     * @return Returns a Parcelable object containing the view's current dynamic
15689     *         state, or null if there is nothing interesting to save. The
15690     *         default implementation returns null.
15691     * @see #onRestoreInstanceState(android.os.Parcelable)
15692     * @see #saveHierarchyState(android.util.SparseArray)
15693     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15694     * @see #setSaveEnabled(boolean)
15695     */
15696    @CallSuper
15697    protected Parcelable onSaveInstanceState() {
15698        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15699        if (mStartActivityRequestWho != null) {
15700            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
15701            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
15702            return state;
15703        }
15704        return BaseSavedState.EMPTY_STATE;
15705    }
15706
15707    /**
15708     * Restore this view hierarchy's frozen state from the given container.
15709     *
15710     * @param container The SparseArray which holds previously frozen states.
15711     *
15712     * @see #saveHierarchyState(android.util.SparseArray)
15713     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15714     * @see #onRestoreInstanceState(android.os.Parcelable)
15715     */
15716    public void restoreHierarchyState(SparseArray<Parcelable> container) {
15717        dispatchRestoreInstanceState(container);
15718    }
15719
15720    /**
15721     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
15722     * state for this view and its children. May be overridden to modify how restoring
15723     * happens to a view's children; for example, some views may want to not store state
15724     * for their children.
15725     *
15726     * @param container The SparseArray which holds previously saved state.
15727     *
15728     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15729     * @see #restoreHierarchyState(android.util.SparseArray)
15730     * @see #onRestoreInstanceState(android.os.Parcelable)
15731     */
15732    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
15733        if (mID != NO_ID) {
15734            Parcelable state = container.get(mID);
15735            if (state != null) {
15736                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
15737                // + ": " + state);
15738                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15739                onRestoreInstanceState(state);
15740                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15741                    throw new IllegalStateException(
15742                            "Derived class did not call super.onRestoreInstanceState()");
15743                }
15744            }
15745        }
15746    }
15747
15748    /**
15749     * Hook allowing a view to re-apply a representation of its internal state that had previously
15750     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
15751     * null state.
15752     *
15753     * @param state The frozen state that had previously been returned by
15754     *        {@link #onSaveInstanceState}.
15755     *
15756     * @see #onSaveInstanceState()
15757     * @see #restoreHierarchyState(android.util.SparseArray)
15758     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15759     */
15760    @CallSuper
15761    protected void onRestoreInstanceState(Parcelable state) {
15762        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15763        if (state != null && !(state instanceof AbsSavedState)) {
15764            throw new IllegalArgumentException("Wrong state class, expecting View State but "
15765                    + "received " + state.getClass().toString() + " instead. This usually happens "
15766                    + "when two views of different type have the same id in the same hierarchy. "
15767                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
15768                    + "other views do not use the same id.");
15769        }
15770        if (state != null && state instanceof BaseSavedState) {
15771            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
15772        }
15773    }
15774
15775    /**
15776     * <p>Return the time at which the drawing of the view hierarchy started.</p>
15777     *
15778     * @return the drawing start time in milliseconds
15779     */
15780    public long getDrawingTime() {
15781        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
15782    }
15783
15784    /**
15785     * <p>Enables or disables the duplication of the parent's state into this view. When
15786     * duplication is enabled, this view gets its drawable state from its parent rather
15787     * than from its own internal properties.</p>
15788     *
15789     * <p>Note: in the current implementation, setting this property to true after the
15790     * view was added to a ViewGroup might have no effect at all. This property should
15791     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
15792     *
15793     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
15794     * property is enabled, an exception will be thrown.</p>
15795     *
15796     * <p>Note: if the child view uses and updates additional states which are unknown to the
15797     * parent, these states should not be affected by this method.</p>
15798     *
15799     * @param enabled True to enable duplication of the parent's drawable state, false
15800     *                to disable it.
15801     *
15802     * @see #getDrawableState()
15803     * @see #isDuplicateParentStateEnabled()
15804     */
15805    public void setDuplicateParentStateEnabled(boolean enabled) {
15806        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
15807    }
15808
15809    /**
15810     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
15811     *
15812     * @return True if this view's drawable state is duplicated from the parent,
15813     *         false otherwise
15814     *
15815     * @see #getDrawableState()
15816     * @see #setDuplicateParentStateEnabled(boolean)
15817     */
15818    public boolean isDuplicateParentStateEnabled() {
15819        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
15820    }
15821
15822    /**
15823     * <p>Specifies the type of layer backing this view. The layer can be
15824     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15825     * {@link #LAYER_TYPE_HARDWARE}.</p>
15826     *
15827     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15828     * instance that controls how the layer is composed on screen. The following
15829     * properties of the paint are taken into account when composing the layer:</p>
15830     * <ul>
15831     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15832     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15833     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15834     * </ul>
15835     *
15836     * <p>If this view has an alpha value set to < 1.0 by calling
15837     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
15838     * by this view's alpha value.</p>
15839     *
15840     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
15841     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
15842     * for more information on when and how to use layers.</p>
15843     *
15844     * @param layerType The type of layer to use with this view, must be one of
15845     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15846     *        {@link #LAYER_TYPE_HARDWARE}
15847     * @param paint The paint used to compose the layer. This argument is optional
15848     *        and can be null. It is ignored when the layer type is
15849     *        {@link #LAYER_TYPE_NONE}
15850     *
15851     * @see #getLayerType()
15852     * @see #LAYER_TYPE_NONE
15853     * @see #LAYER_TYPE_SOFTWARE
15854     * @see #LAYER_TYPE_HARDWARE
15855     * @see #setAlpha(float)
15856     *
15857     * @attr ref android.R.styleable#View_layerType
15858     */
15859    public void setLayerType(int layerType, @Nullable Paint paint) {
15860        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15861            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15862                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15863        }
15864
15865        boolean typeChanged = mRenderNode.setLayerType(layerType);
15866
15867        if (!typeChanged) {
15868            setLayerPaint(paint);
15869            return;
15870        }
15871
15872        if (layerType != LAYER_TYPE_SOFTWARE) {
15873            // Destroy any previous software drawing cache if present
15874            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
15875            // drawing cache created in View#draw when drawing to a SW canvas.
15876            destroyDrawingCache();
15877        }
15878
15879        mLayerType = layerType;
15880        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
15881        mRenderNode.setLayerPaint(mLayerPaint);
15882
15883        // draw() behaves differently if we are on a layer, so we need to
15884        // invalidate() here
15885        invalidateParentCaches();
15886        invalidate(true);
15887    }
15888
15889    /**
15890     * Updates the {@link Paint} object used with the current layer (used only if the current
15891     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15892     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15893     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15894     * ensure that the view gets redrawn immediately.
15895     *
15896     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15897     * instance that controls how the layer is composed on screen. The following
15898     * properties of the paint are taken into account when composing the layer:</p>
15899     * <ul>
15900     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15901     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15902     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15903     * </ul>
15904     *
15905     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15906     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15907     *
15908     * @param paint The paint used to compose the layer. This argument is optional
15909     *        and can be null. It is ignored when the layer type is
15910     *        {@link #LAYER_TYPE_NONE}
15911     *
15912     * @see #setLayerType(int, android.graphics.Paint)
15913     */
15914    public void setLayerPaint(@Nullable Paint paint) {
15915        int layerType = getLayerType();
15916        if (layerType != LAYER_TYPE_NONE) {
15917            mLayerPaint = paint;
15918            if (layerType == LAYER_TYPE_HARDWARE) {
15919                if (mRenderNode.setLayerPaint(paint)) {
15920                    invalidateViewProperty(false, false);
15921                }
15922            } else {
15923                invalidate();
15924            }
15925        }
15926    }
15927
15928    /**
15929     * Indicates what type of layer is currently associated with this view. By default
15930     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15931     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15932     * for more information on the different types of layers.
15933     *
15934     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15935     *         {@link #LAYER_TYPE_HARDWARE}
15936     *
15937     * @see #setLayerType(int, android.graphics.Paint)
15938     * @see #buildLayer()
15939     * @see #LAYER_TYPE_NONE
15940     * @see #LAYER_TYPE_SOFTWARE
15941     * @see #LAYER_TYPE_HARDWARE
15942     */
15943    public int getLayerType() {
15944        return mLayerType;
15945    }
15946
15947    /**
15948     * Forces this view's layer to be created and this view to be rendered
15949     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15950     * invoking this method will have no effect.
15951     *
15952     * This method can for instance be used to render a view into its layer before
15953     * starting an animation. If this view is complex, rendering into the layer
15954     * before starting the animation will avoid skipping frames.
15955     *
15956     * @throws IllegalStateException If this view is not attached to a window
15957     *
15958     * @see #setLayerType(int, android.graphics.Paint)
15959     */
15960    public void buildLayer() {
15961        if (mLayerType == LAYER_TYPE_NONE) return;
15962
15963        final AttachInfo attachInfo = mAttachInfo;
15964        if (attachInfo == null) {
15965            throw new IllegalStateException("This view must be attached to a window first");
15966        }
15967
15968        if (getWidth() == 0 || getHeight() == 0) {
15969            return;
15970        }
15971
15972        switch (mLayerType) {
15973            case LAYER_TYPE_HARDWARE:
15974                updateDisplayListIfDirty();
15975                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
15976                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
15977                }
15978                break;
15979            case LAYER_TYPE_SOFTWARE:
15980                buildDrawingCache(true);
15981                break;
15982        }
15983    }
15984
15985    /**
15986     * Destroys all hardware rendering resources. This method is invoked
15987     * when the system needs to reclaim resources. Upon execution of this
15988     * method, you should free any OpenGL resources created by the view.
15989     *
15990     * Note: you <strong>must</strong> call
15991     * <code>super.destroyHardwareResources()</code> when overriding
15992     * this method.
15993     *
15994     * @hide
15995     */
15996    @CallSuper
15997    protected void destroyHardwareResources() {
15998        // Although the Layer will be destroyed by RenderNode, we want to release
15999        // the staging display list, which is also a signal to RenderNode that it's
16000        // safe to free its copy of the display list as it knows that we will
16001        // push an updated DisplayList if we try to draw again
16002        resetDisplayList();
16003    }
16004
16005    /**
16006     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
16007     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
16008     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
16009     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
16010     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
16011     * null.</p>
16012     *
16013     * <p>Enabling the drawing cache is similar to
16014     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
16015     * acceleration is turned off. When hardware acceleration is turned on, enabling the
16016     * drawing cache has no effect on rendering because the system uses a different mechanism
16017     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
16018     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
16019     * for information on how to enable software and hardware layers.</p>
16020     *
16021     * <p>This API can be used to manually generate
16022     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
16023     * {@link #getDrawingCache()}.</p>
16024     *
16025     * @param enabled true to enable the drawing cache, false otherwise
16026     *
16027     * @see #isDrawingCacheEnabled()
16028     * @see #getDrawingCache()
16029     * @see #buildDrawingCache()
16030     * @see #setLayerType(int, android.graphics.Paint)
16031     */
16032    public void setDrawingCacheEnabled(boolean enabled) {
16033        mCachingFailed = false;
16034        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
16035    }
16036
16037    /**
16038     * <p>Indicates whether the drawing cache is enabled for this view.</p>
16039     *
16040     * @return true if the drawing cache is enabled
16041     *
16042     * @see #setDrawingCacheEnabled(boolean)
16043     * @see #getDrawingCache()
16044     */
16045    @ViewDebug.ExportedProperty(category = "drawing")
16046    public boolean isDrawingCacheEnabled() {
16047        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
16048    }
16049
16050    /**
16051     * Debugging utility which recursively outputs the dirty state of a view and its
16052     * descendants.
16053     *
16054     * @hide
16055     */
16056    @SuppressWarnings({"UnusedDeclaration"})
16057    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
16058        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
16059                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
16060                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
16061                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
16062        if (clear) {
16063            mPrivateFlags &= clearMask;
16064        }
16065        if (this instanceof ViewGroup) {
16066            ViewGroup parent = (ViewGroup) this;
16067            final int count = parent.getChildCount();
16068            for (int i = 0; i < count; i++) {
16069                final View child = parent.getChildAt(i);
16070                child.outputDirtyFlags(indent + "  ", clear, clearMask);
16071            }
16072        }
16073    }
16074
16075    /**
16076     * This method is used by ViewGroup to cause its children to restore or recreate their
16077     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
16078     * to recreate its own display list, which would happen if it went through the normal
16079     * draw/dispatchDraw mechanisms.
16080     *
16081     * @hide
16082     */
16083    protected void dispatchGetDisplayList() {}
16084
16085    /**
16086     * A view that is not attached or hardware accelerated cannot create a display list.
16087     * This method checks these conditions and returns the appropriate result.
16088     *
16089     * @return true if view has the ability to create a display list, false otherwise.
16090     *
16091     * @hide
16092     */
16093    public boolean canHaveDisplayList() {
16094        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
16095    }
16096
16097    /**
16098     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
16099     * @hide
16100     */
16101    @NonNull
16102    public RenderNode updateDisplayListIfDirty() {
16103        final RenderNode renderNode = mRenderNode;
16104        if (!canHaveDisplayList()) {
16105            // can't populate RenderNode, don't try
16106            return renderNode;
16107        }
16108
16109        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
16110                || !renderNode.isValid()
16111                || (mRecreateDisplayList)) {
16112            // Don't need to recreate the display list, just need to tell our
16113            // children to restore/recreate theirs
16114            if (renderNode.isValid()
16115                    && !mRecreateDisplayList) {
16116                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16117                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16118                dispatchGetDisplayList();
16119
16120                return renderNode; // no work needed
16121            }
16122
16123            // If we got here, we're recreating it. Mark it as such to ensure that
16124            // we copy in child display lists into ours in drawChild()
16125            mRecreateDisplayList = true;
16126
16127            int width = mRight - mLeft;
16128            int height = mBottom - mTop;
16129            int layerType = getLayerType();
16130
16131            final DisplayListCanvas canvas = renderNode.start(width, height);
16132            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
16133
16134            try {
16135                if (layerType == LAYER_TYPE_SOFTWARE) {
16136                    buildDrawingCache(true);
16137                    Bitmap cache = getDrawingCache(true);
16138                    if (cache != null) {
16139                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
16140                    }
16141                } else {
16142                    computeScroll();
16143
16144                    canvas.translate(-mScrollX, -mScrollY);
16145                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16146                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16147
16148                    // Fast path for layouts with no backgrounds
16149                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16150                        dispatchDraw(canvas);
16151                        if (mOverlay != null && !mOverlay.isEmpty()) {
16152                            mOverlay.getOverlayView().draw(canvas);
16153                        }
16154                    } else {
16155                        draw(canvas);
16156                    }
16157                }
16158            } finally {
16159                renderNode.end(canvas);
16160                setDisplayListProperties(renderNode);
16161            }
16162        } else {
16163            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16164            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16165        }
16166        return renderNode;
16167    }
16168
16169    private void resetDisplayList() {
16170        if (mRenderNode.isValid()) {
16171            mRenderNode.discardDisplayList();
16172        }
16173
16174        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
16175            mBackgroundRenderNode.discardDisplayList();
16176        }
16177    }
16178
16179    /**
16180     * Called when the passed RenderNode is removed from the draw tree
16181     * @hide
16182     */
16183    public void onRenderNodeDetached(RenderNode renderNode) {
16184    }
16185
16186    /**
16187     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
16188     *
16189     * @return A non-scaled bitmap representing this view or null if cache is disabled.
16190     *
16191     * @see #getDrawingCache(boolean)
16192     */
16193    public Bitmap getDrawingCache() {
16194        return getDrawingCache(false);
16195    }
16196
16197    /**
16198     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
16199     * is null when caching is disabled. If caching is enabled and the cache is not ready,
16200     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
16201     * draw from the cache when the cache is enabled. To benefit from the cache, you must
16202     * request the drawing cache by calling this method and draw it on screen if the
16203     * returned bitmap is not null.</p>
16204     *
16205     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16206     * this method will create a bitmap of the same size as this view. Because this bitmap
16207     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16208     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16209     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16210     * size than the view. This implies that your application must be able to handle this
16211     * size.</p>
16212     *
16213     * @param autoScale Indicates whether the generated bitmap should be scaled based on
16214     *        the current density of the screen when the application is in compatibility
16215     *        mode.
16216     *
16217     * @return A bitmap representing this view or null if cache is disabled.
16218     *
16219     * @see #setDrawingCacheEnabled(boolean)
16220     * @see #isDrawingCacheEnabled()
16221     * @see #buildDrawingCache(boolean)
16222     * @see #destroyDrawingCache()
16223     */
16224    public Bitmap getDrawingCache(boolean autoScale) {
16225        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
16226            return null;
16227        }
16228        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
16229            buildDrawingCache(autoScale);
16230        }
16231        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
16232    }
16233
16234    /**
16235     * <p>Frees the resources used by the drawing cache. If you call
16236     * {@link #buildDrawingCache()} manually without calling
16237     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16238     * should cleanup the cache with this method afterwards.</p>
16239     *
16240     * @see #setDrawingCacheEnabled(boolean)
16241     * @see #buildDrawingCache()
16242     * @see #getDrawingCache()
16243     */
16244    public void destroyDrawingCache() {
16245        if (mDrawingCache != null) {
16246            mDrawingCache.recycle();
16247            mDrawingCache = null;
16248        }
16249        if (mUnscaledDrawingCache != null) {
16250            mUnscaledDrawingCache.recycle();
16251            mUnscaledDrawingCache = null;
16252        }
16253    }
16254
16255    /**
16256     * Setting a solid background color for the drawing cache's bitmaps will improve
16257     * performance and memory usage. Note, though that this should only be used if this
16258     * view will always be drawn on top of a solid color.
16259     *
16260     * @param color The background color to use for the drawing cache's bitmap
16261     *
16262     * @see #setDrawingCacheEnabled(boolean)
16263     * @see #buildDrawingCache()
16264     * @see #getDrawingCache()
16265     */
16266    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
16267        if (color != mDrawingCacheBackgroundColor) {
16268            mDrawingCacheBackgroundColor = color;
16269            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16270        }
16271    }
16272
16273    /**
16274     * @see #setDrawingCacheBackgroundColor(int)
16275     *
16276     * @return The background color to used for the drawing cache's bitmap
16277     */
16278    @ColorInt
16279    public int getDrawingCacheBackgroundColor() {
16280        return mDrawingCacheBackgroundColor;
16281    }
16282
16283    /**
16284     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
16285     *
16286     * @see #buildDrawingCache(boolean)
16287     */
16288    public void buildDrawingCache() {
16289        buildDrawingCache(false);
16290    }
16291
16292    /**
16293     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
16294     *
16295     * <p>If you call {@link #buildDrawingCache()} manually without calling
16296     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16297     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
16298     *
16299     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16300     * this method will create a bitmap of the same size as this view. Because this bitmap
16301     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16302     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16303     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16304     * size than the view. This implies that your application must be able to handle this
16305     * size.</p>
16306     *
16307     * <p>You should avoid calling this method when hardware acceleration is enabled. If
16308     * you do not need the drawing cache bitmap, calling this method will increase memory
16309     * usage and cause the view to be rendered in software once, thus negatively impacting
16310     * performance.</p>
16311     *
16312     * @see #getDrawingCache()
16313     * @see #destroyDrawingCache()
16314     */
16315    public void buildDrawingCache(boolean autoScale) {
16316        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
16317                mDrawingCache == null : mUnscaledDrawingCache == null)) {
16318            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
16319                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
16320                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
16321            }
16322            try {
16323                buildDrawingCacheImpl(autoScale);
16324            } finally {
16325                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
16326            }
16327        }
16328    }
16329
16330    /**
16331     * private, internal implementation of buildDrawingCache, used to enable tracing
16332     */
16333    private void buildDrawingCacheImpl(boolean autoScale) {
16334        mCachingFailed = false;
16335
16336        int width = mRight - mLeft;
16337        int height = mBottom - mTop;
16338
16339        final AttachInfo attachInfo = mAttachInfo;
16340        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
16341
16342        if (autoScale && scalingRequired) {
16343            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
16344            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
16345        }
16346
16347        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
16348        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
16349        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
16350
16351        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
16352        final long drawingCacheSize =
16353                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
16354        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
16355            if (width > 0 && height > 0) {
16356                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
16357                        + " too large to fit into a software layer (or drawing cache), needs "
16358                        + projectedBitmapSize + " bytes, only "
16359                        + drawingCacheSize + " available");
16360            }
16361            destroyDrawingCache();
16362            mCachingFailed = true;
16363            return;
16364        }
16365
16366        boolean clear = true;
16367        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
16368
16369        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
16370            Bitmap.Config quality;
16371            if (!opaque) {
16372                // Never pick ARGB_4444 because it looks awful
16373                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
16374                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
16375                    case DRAWING_CACHE_QUALITY_AUTO:
16376                    case DRAWING_CACHE_QUALITY_LOW:
16377                    case DRAWING_CACHE_QUALITY_HIGH:
16378                    default:
16379                        quality = Bitmap.Config.ARGB_8888;
16380                        break;
16381                }
16382            } else {
16383                // Optimization for translucent windows
16384                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
16385                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
16386            }
16387
16388            // Try to cleanup memory
16389            if (bitmap != null) bitmap.recycle();
16390
16391            try {
16392                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16393                        width, height, quality);
16394                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
16395                if (autoScale) {
16396                    mDrawingCache = bitmap;
16397                } else {
16398                    mUnscaledDrawingCache = bitmap;
16399                }
16400                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
16401            } catch (OutOfMemoryError e) {
16402                // If there is not enough memory to create the bitmap cache, just
16403                // ignore the issue as bitmap caches are not required to draw the
16404                // view hierarchy
16405                if (autoScale) {
16406                    mDrawingCache = null;
16407                } else {
16408                    mUnscaledDrawingCache = null;
16409                }
16410                mCachingFailed = true;
16411                return;
16412            }
16413
16414            clear = drawingCacheBackgroundColor != 0;
16415        }
16416
16417        Canvas canvas;
16418        if (attachInfo != null) {
16419            canvas = attachInfo.mCanvas;
16420            if (canvas == null) {
16421                canvas = new Canvas();
16422            }
16423            canvas.setBitmap(bitmap);
16424            // Temporarily clobber the cached Canvas in case one of our children
16425            // is also using a drawing cache. Without this, the children would
16426            // steal the canvas by attaching their own bitmap to it and bad, bad
16427            // thing would happen (invisible views, corrupted drawings, etc.)
16428            attachInfo.mCanvas = null;
16429        } else {
16430            // This case should hopefully never or seldom happen
16431            canvas = new Canvas(bitmap);
16432        }
16433
16434        if (clear) {
16435            bitmap.eraseColor(drawingCacheBackgroundColor);
16436        }
16437
16438        computeScroll();
16439        final int restoreCount = canvas.save();
16440
16441        if (autoScale && scalingRequired) {
16442            final float scale = attachInfo.mApplicationScale;
16443            canvas.scale(scale, scale);
16444        }
16445
16446        canvas.translate(-mScrollX, -mScrollY);
16447
16448        mPrivateFlags |= PFLAG_DRAWN;
16449        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
16450                mLayerType != LAYER_TYPE_NONE) {
16451            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
16452        }
16453
16454        // Fast path for layouts with no backgrounds
16455        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16456            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16457            dispatchDraw(canvas);
16458            if (mOverlay != null && !mOverlay.isEmpty()) {
16459                mOverlay.getOverlayView().draw(canvas);
16460            }
16461        } else {
16462            draw(canvas);
16463        }
16464
16465        canvas.restoreToCount(restoreCount);
16466        canvas.setBitmap(null);
16467
16468        if (attachInfo != null) {
16469            // Restore the cached Canvas for our siblings
16470            attachInfo.mCanvas = canvas;
16471        }
16472    }
16473
16474    /**
16475     * Create a snapshot of the view into a bitmap.  We should probably make
16476     * some form of this public, but should think about the API.
16477     *
16478     * @hide
16479     */
16480    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
16481        int width = mRight - mLeft;
16482        int height = mBottom - mTop;
16483
16484        final AttachInfo attachInfo = mAttachInfo;
16485        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
16486        width = (int) ((width * scale) + 0.5f);
16487        height = (int) ((height * scale) + 0.5f);
16488
16489        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16490                width > 0 ? width : 1, height > 0 ? height : 1, quality);
16491        if (bitmap == null) {
16492            throw new OutOfMemoryError();
16493        }
16494
16495        Resources resources = getResources();
16496        if (resources != null) {
16497            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
16498        }
16499
16500        Canvas canvas;
16501        if (attachInfo != null) {
16502            canvas = attachInfo.mCanvas;
16503            if (canvas == null) {
16504                canvas = new Canvas();
16505            }
16506            canvas.setBitmap(bitmap);
16507            // Temporarily clobber the cached Canvas in case one of our children
16508            // is also using a drawing cache. Without this, the children would
16509            // steal the canvas by attaching their own bitmap to it and bad, bad
16510            // things would happen (invisible views, corrupted drawings, etc.)
16511            attachInfo.mCanvas = null;
16512        } else {
16513            // This case should hopefully never or seldom happen
16514            canvas = new Canvas(bitmap);
16515        }
16516
16517        if ((backgroundColor & 0xff000000) != 0) {
16518            bitmap.eraseColor(backgroundColor);
16519        }
16520
16521        computeScroll();
16522        final int restoreCount = canvas.save();
16523        canvas.scale(scale, scale);
16524        canvas.translate(-mScrollX, -mScrollY);
16525
16526        // Temporarily remove the dirty mask
16527        int flags = mPrivateFlags;
16528        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16529
16530        // Fast path for layouts with no backgrounds
16531        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16532            dispatchDraw(canvas);
16533            if (mOverlay != null && !mOverlay.isEmpty()) {
16534                mOverlay.getOverlayView().draw(canvas);
16535            }
16536        } else {
16537            draw(canvas);
16538        }
16539
16540        mPrivateFlags = flags;
16541
16542        canvas.restoreToCount(restoreCount);
16543        canvas.setBitmap(null);
16544
16545        if (attachInfo != null) {
16546            // Restore the cached Canvas for our siblings
16547            attachInfo.mCanvas = canvas;
16548        }
16549
16550        return bitmap;
16551    }
16552
16553    /**
16554     * Indicates whether this View is currently in edit mode. A View is usually
16555     * in edit mode when displayed within a developer tool. For instance, if
16556     * this View is being drawn by a visual user interface builder, this method
16557     * should return true.
16558     *
16559     * Subclasses should check the return value of this method to provide
16560     * different behaviors if their normal behavior might interfere with the
16561     * host environment. For instance: the class spawns a thread in its
16562     * constructor, the drawing code relies on device-specific features, etc.
16563     *
16564     * This method is usually checked in the drawing code of custom widgets.
16565     *
16566     * @return True if this View is in edit mode, false otherwise.
16567     */
16568    public boolean isInEditMode() {
16569        return false;
16570    }
16571
16572    /**
16573     * If the View draws content inside its padding and enables fading edges,
16574     * it needs to support padding offsets. Padding offsets are added to the
16575     * fading edges to extend the length of the fade so that it covers pixels
16576     * drawn inside the padding.
16577     *
16578     * Subclasses of this class should override this method if they need
16579     * to draw content inside the padding.
16580     *
16581     * @return True if padding offset must be applied, false otherwise.
16582     *
16583     * @see #getLeftPaddingOffset()
16584     * @see #getRightPaddingOffset()
16585     * @see #getTopPaddingOffset()
16586     * @see #getBottomPaddingOffset()
16587     *
16588     * @since CURRENT
16589     */
16590    protected boolean isPaddingOffsetRequired() {
16591        return false;
16592    }
16593
16594    /**
16595     * Amount by which to extend the left fading region. Called only when
16596     * {@link #isPaddingOffsetRequired()} returns true.
16597     *
16598     * @return The left padding offset in pixels.
16599     *
16600     * @see #isPaddingOffsetRequired()
16601     *
16602     * @since CURRENT
16603     */
16604    protected int getLeftPaddingOffset() {
16605        return 0;
16606    }
16607
16608    /**
16609     * Amount by which to extend the right fading region. Called only when
16610     * {@link #isPaddingOffsetRequired()} returns true.
16611     *
16612     * @return The right padding offset in pixels.
16613     *
16614     * @see #isPaddingOffsetRequired()
16615     *
16616     * @since CURRENT
16617     */
16618    protected int getRightPaddingOffset() {
16619        return 0;
16620    }
16621
16622    /**
16623     * Amount by which to extend the top fading region. Called only when
16624     * {@link #isPaddingOffsetRequired()} returns true.
16625     *
16626     * @return The top padding offset in pixels.
16627     *
16628     * @see #isPaddingOffsetRequired()
16629     *
16630     * @since CURRENT
16631     */
16632    protected int getTopPaddingOffset() {
16633        return 0;
16634    }
16635
16636    /**
16637     * Amount by which to extend the bottom fading region. Called only when
16638     * {@link #isPaddingOffsetRequired()} returns true.
16639     *
16640     * @return The bottom padding offset in pixels.
16641     *
16642     * @see #isPaddingOffsetRequired()
16643     *
16644     * @since CURRENT
16645     */
16646    protected int getBottomPaddingOffset() {
16647        return 0;
16648    }
16649
16650    /**
16651     * @hide
16652     * @param offsetRequired
16653     */
16654    protected int getFadeTop(boolean offsetRequired) {
16655        int top = mPaddingTop;
16656        if (offsetRequired) top += getTopPaddingOffset();
16657        return top;
16658    }
16659
16660    /**
16661     * @hide
16662     * @param offsetRequired
16663     */
16664    protected int getFadeHeight(boolean offsetRequired) {
16665        int padding = mPaddingTop;
16666        if (offsetRequired) padding += getTopPaddingOffset();
16667        return mBottom - mTop - mPaddingBottom - padding;
16668    }
16669
16670    /**
16671     * <p>Indicates whether this view is attached to a hardware accelerated
16672     * window or not.</p>
16673     *
16674     * <p>Even if this method returns true, it does not mean that every call
16675     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
16676     * accelerated {@link android.graphics.Canvas}. For instance, if this view
16677     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
16678     * window is hardware accelerated,
16679     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
16680     * return false, and this method will return true.</p>
16681     *
16682     * @return True if the view is attached to a window and the window is
16683     *         hardware accelerated; false in any other case.
16684     */
16685    @ViewDebug.ExportedProperty(category = "drawing")
16686    public boolean isHardwareAccelerated() {
16687        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
16688    }
16689
16690    /**
16691     * Sets a rectangular area on this view to which the view will be clipped
16692     * when it is drawn. Setting the value to null will remove the clip bounds
16693     * and the view will draw normally, using its full bounds.
16694     *
16695     * @param clipBounds The rectangular area, in the local coordinates of
16696     * this view, to which future drawing operations will be clipped.
16697     */
16698    public void setClipBounds(Rect clipBounds) {
16699        if (clipBounds == mClipBounds
16700                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
16701            return;
16702        }
16703        if (clipBounds != null) {
16704            if (mClipBounds == null) {
16705                mClipBounds = new Rect(clipBounds);
16706            } else {
16707                mClipBounds.set(clipBounds);
16708            }
16709        } else {
16710            mClipBounds = null;
16711        }
16712        mRenderNode.setClipBounds(mClipBounds);
16713        invalidateViewProperty(false, false);
16714    }
16715
16716    /**
16717     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
16718     *
16719     * @return A copy of the current clip bounds if clip bounds are set,
16720     * otherwise null.
16721     */
16722    public Rect getClipBounds() {
16723        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
16724    }
16725
16726
16727    /**
16728     * Populates an output rectangle with the clip bounds of the view,
16729     * returning {@code true} if successful or {@code false} if the view's
16730     * clip bounds are {@code null}.
16731     *
16732     * @param outRect rectangle in which to place the clip bounds of the view
16733     * @return {@code true} if successful or {@code false} if the view's
16734     *         clip bounds are {@code null}
16735     */
16736    public boolean getClipBounds(Rect outRect) {
16737        if (mClipBounds != null) {
16738            outRect.set(mClipBounds);
16739            return true;
16740        }
16741        return false;
16742    }
16743
16744    /**
16745     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
16746     * case of an active Animation being run on the view.
16747     */
16748    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
16749            Animation a, boolean scalingRequired) {
16750        Transformation invalidationTransform;
16751        final int flags = parent.mGroupFlags;
16752        final boolean initialized = a.isInitialized();
16753        if (!initialized) {
16754            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
16755            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
16756            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
16757            onAnimationStart();
16758        }
16759
16760        final Transformation t = parent.getChildTransformation();
16761        boolean more = a.getTransformation(drawingTime, t, 1f);
16762        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
16763            if (parent.mInvalidationTransformation == null) {
16764                parent.mInvalidationTransformation = new Transformation();
16765            }
16766            invalidationTransform = parent.mInvalidationTransformation;
16767            a.getTransformation(drawingTime, invalidationTransform, 1f);
16768        } else {
16769            invalidationTransform = t;
16770        }
16771
16772        if (more) {
16773            if (!a.willChangeBounds()) {
16774                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
16775                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
16776                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
16777                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
16778                    // The child need to draw an animation, potentially offscreen, so
16779                    // make sure we do not cancel invalidate requests
16780                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16781                    parent.invalidate(mLeft, mTop, mRight, mBottom);
16782                }
16783            } else {
16784                if (parent.mInvalidateRegion == null) {
16785                    parent.mInvalidateRegion = new RectF();
16786                }
16787                final RectF region = parent.mInvalidateRegion;
16788                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
16789                        invalidationTransform);
16790
16791                // The child need to draw an animation, potentially offscreen, so
16792                // make sure we do not cancel invalidate requests
16793                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16794
16795                final int left = mLeft + (int) region.left;
16796                final int top = mTop + (int) region.top;
16797                parent.invalidate(left, top, left + (int) (region.width() + .5f),
16798                        top + (int) (region.height() + .5f));
16799            }
16800        }
16801        return more;
16802    }
16803
16804    /**
16805     * This method is called by getDisplayList() when a display list is recorded for a View.
16806     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
16807     */
16808    void setDisplayListProperties(RenderNode renderNode) {
16809        if (renderNode != null) {
16810            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
16811            renderNode.setClipToBounds(mParent instanceof ViewGroup
16812                    && ((ViewGroup) mParent).getClipChildren());
16813
16814            float alpha = 1;
16815            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
16816                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16817                ViewGroup parentVG = (ViewGroup) mParent;
16818                final Transformation t = parentVG.getChildTransformation();
16819                if (parentVG.getChildStaticTransformation(this, t)) {
16820                    final int transformType = t.getTransformationType();
16821                    if (transformType != Transformation.TYPE_IDENTITY) {
16822                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
16823                            alpha = t.getAlpha();
16824                        }
16825                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
16826                            renderNode.setStaticMatrix(t.getMatrix());
16827                        }
16828                    }
16829                }
16830            }
16831            if (mTransformationInfo != null) {
16832                alpha *= getFinalAlpha();
16833                if (alpha < 1) {
16834                    final int multipliedAlpha = (int) (255 * alpha);
16835                    if (onSetAlpha(multipliedAlpha)) {
16836                        alpha = 1;
16837                    }
16838                }
16839                renderNode.setAlpha(alpha);
16840            } else if (alpha < 1) {
16841                renderNode.setAlpha(alpha);
16842            }
16843        }
16844    }
16845
16846    /**
16847     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
16848     *
16849     * This is where the View specializes rendering behavior based on layer type,
16850     * and hardware acceleration.
16851     */
16852    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
16853        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
16854        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
16855         *
16856         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
16857         * HW accelerated, it can't handle drawing RenderNodes.
16858         */
16859        boolean drawingWithRenderNode = mAttachInfo != null
16860                && mAttachInfo.mHardwareAccelerated
16861                && hardwareAcceleratedCanvas;
16862
16863        boolean more = false;
16864        final boolean childHasIdentityMatrix = hasIdentityMatrix();
16865        final int parentFlags = parent.mGroupFlags;
16866
16867        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16868            parent.getChildTransformation().clear();
16869            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16870        }
16871
16872        Transformation transformToApply = null;
16873        boolean concatMatrix = false;
16874        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16875        final Animation a = getAnimation();
16876        if (a != null) {
16877            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16878            concatMatrix = a.willChangeTransformationMatrix();
16879            if (concatMatrix) {
16880                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16881            }
16882            transformToApply = parent.getChildTransformation();
16883        } else {
16884            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16885                // No longer animating: clear out old animation matrix
16886                mRenderNode.setAnimationMatrix(null);
16887                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16888            }
16889            if (!drawingWithRenderNode
16890                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16891                final Transformation t = parent.getChildTransformation();
16892                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16893                if (hasTransform) {
16894                    final int transformType = t.getTransformationType();
16895                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16896                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16897                }
16898            }
16899        }
16900
16901        concatMatrix |= !childHasIdentityMatrix;
16902
16903        // Sets the flag as early as possible to allow draw() implementations
16904        // to call invalidate() successfully when doing animations
16905        mPrivateFlags |= PFLAG_DRAWN;
16906
16907        if (!concatMatrix &&
16908                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16909                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16910                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16911                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16912            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16913            return more;
16914        }
16915        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16916
16917        if (hardwareAcceleratedCanvas) {
16918            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16919            // retain the flag's value temporarily in the mRecreateDisplayList flag
16920            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16921            mPrivateFlags &= ~PFLAG_INVALIDATED;
16922        }
16923
16924        RenderNode renderNode = null;
16925        Bitmap cache = null;
16926        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16927        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
16928             if (layerType != LAYER_TYPE_NONE) {
16929                 // If not drawing with RenderNode, treat HW layers as SW
16930                 layerType = LAYER_TYPE_SOFTWARE;
16931                 buildDrawingCache(true);
16932            }
16933            cache = getDrawingCache(true);
16934        }
16935
16936        if (drawingWithRenderNode) {
16937            // Delay getting the display list until animation-driven alpha values are
16938            // set up and possibly passed on to the view
16939            renderNode = updateDisplayListIfDirty();
16940            if (!renderNode.isValid()) {
16941                // Uncommon, but possible. If a view is removed from the hierarchy during the call
16942                // to getDisplayList(), the display list will be marked invalid and we should not
16943                // try to use it again.
16944                renderNode = null;
16945                drawingWithRenderNode = false;
16946            }
16947        }
16948
16949        int sx = 0;
16950        int sy = 0;
16951        if (!drawingWithRenderNode) {
16952            computeScroll();
16953            sx = mScrollX;
16954            sy = mScrollY;
16955        }
16956
16957        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16958        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16959
16960        int restoreTo = -1;
16961        if (!drawingWithRenderNode || transformToApply != null) {
16962            restoreTo = canvas.save();
16963        }
16964        if (offsetForScroll) {
16965            canvas.translate(mLeft - sx, mTop - sy);
16966        } else {
16967            if (!drawingWithRenderNode) {
16968                canvas.translate(mLeft, mTop);
16969            }
16970            if (scalingRequired) {
16971                if (drawingWithRenderNode) {
16972                    // TODO: Might not need this if we put everything inside the DL
16973                    restoreTo = canvas.save();
16974                }
16975                // mAttachInfo cannot be null, otherwise scalingRequired == false
16976                final float scale = 1.0f / mAttachInfo.mApplicationScale;
16977                canvas.scale(scale, scale);
16978            }
16979        }
16980
16981        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16982        if (transformToApply != null
16983                || alpha < 1
16984                || !hasIdentityMatrix()
16985                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16986            if (transformToApply != null || !childHasIdentityMatrix) {
16987                int transX = 0;
16988                int transY = 0;
16989
16990                if (offsetForScroll) {
16991                    transX = -sx;
16992                    transY = -sy;
16993                }
16994
16995                if (transformToApply != null) {
16996                    if (concatMatrix) {
16997                        if (drawingWithRenderNode) {
16998                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
16999                        } else {
17000                            // Undo the scroll translation, apply the transformation matrix,
17001                            // then redo the scroll translate to get the correct result.
17002                            canvas.translate(-transX, -transY);
17003                            canvas.concat(transformToApply.getMatrix());
17004                            canvas.translate(transX, transY);
17005                        }
17006                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17007                    }
17008
17009                    float transformAlpha = transformToApply.getAlpha();
17010                    if (transformAlpha < 1) {
17011                        alpha *= transformAlpha;
17012                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17013                    }
17014                }
17015
17016                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
17017                    canvas.translate(-transX, -transY);
17018                    canvas.concat(getMatrix());
17019                    canvas.translate(transX, transY);
17020                }
17021            }
17022
17023            // Deal with alpha if it is or used to be <1
17024            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17025                if (alpha < 1) {
17026                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17027                } else {
17028                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17029                }
17030                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17031                if (!drawingWithDrawingCache) {
17032                    final int multipliedAlpha = (int) (255 * alpha);
17033                    if (!onSetAlpha(multipliedAlpha)) {
17034                        if (drawingWithRenderNode) {
17035                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
17036                        } else if (layerType == LAYER_TYPE_NONE) {
17037                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
17038                                    multipliedAlpha);
17039                        }
17040                    } else {
17041                        // Alpha is handled by the child directly, clobber the layer's alpha
17042                        mPrivateFlags |= PFLAG_ALPHA_SET;
17043                    }
17044                }
17045            }
17046        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17047            onSetAlpha(255);
17048            mPrivateFlags &= ~PFLAG_ALPHA_SET;
17049        }
17050
17051        if (!drawingWithRenderNode) {
17052            // apply clips directly, since RenderNode won't do it for this draw
17053            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
17054                if (offsetForScroll) {
17055                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
17056                } else {
17057                    if (!scalingRequired || cache == null) {
17058                        canvas.clipRect(0, 0, getWidth(), getHeight());
17059                    } else {
17060                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
17061                    }
17062                }
17063            }
17064
17065            if (mClipBounds != null) {
17066                // clip bounds ignore scroll
17067                canvas.clipRect(mClipBounds);
17068            }
17069        }
17070
17071        if (!drawingWithDrawingCache) {
17072            if (drawingWithRenderNode) {
17073                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17074                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17075            } else {
17076                // Fast path for layouts with no backgrounds
17077                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17078                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17079                    dispatchDraw(canvas);
17080                } else {
17081                    draw(canvas);
17082                }
17083            }
17084        } else if (cache != null) {
17085            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17086            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
17087                // no layer paint, use temporary paint to draw bitmap
17088                Paint cachePaint = parent.mCachePaint;
17089                if (cachePaint == null) {
17090                    cachePaint = new Paint();
17091                    cachePaint.setDither(false);
17092                    parent.mCachePaint = cachePaint;
17093                }
17094                cachePaint.setAlpha((int) (alpha * 255));
17095                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
17096            } else {
17097                // use layer paint to draw the bitmap, merging the two alphas, but also restore
17098                int layerPaintAlpha = mLayerPaint.getAlpha();
17099                if (alpha < 1) {
17100                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
17101                }
17102                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
17103                if (alpha < 1) {
17104                    mLayerPaint.setAlpha(layerPaintAlpha);
17105                }
17106            }
17107        }
17108
17109        if (restoreTo >= 0) {
17110            canvas.restoreToCount(restoreTo);
17111        }
17112
17113        if (a != null && !more) {
17114            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
17115                onSetAlpha(255);
17116            }
17117            parent.finishAnimatingView(this, a);
17118        }
17119
17120        if (more && hardwareAcceleratedCanvas) {
17121            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17122                // alpha animations should cause the child to recreate its display list
17123                invalidate(true);
17124            }
17125        }
17126
17127        mRecreateDisplayList = false;
17128
17129        return more;
17130    }
17131
17132    /**
17133     * Manually render this view (and all of its children) to the given Canvas.
17134     * The view must have already done a full layout before this function is
17135     * called.  When implementing a view, implement
17136     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
17137     * If you do need to override this method, call the superclass version.
17138     *
17139     * @param canvas The Canvas to which the View is rendered.
17140     */
17141    @CallSuper
17142    public void draw(Canvas canvas) {
17143        final int privateFlags = mPrivateFlags;
17144        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
17145                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
17146        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
17147
17148        /*
17149         * Draw traversal performs several drawing steps which must be executed
17150         * in the appropriate order:
17151         *
17152         *      1. Draw the background
17153         *      2. If necessary, save the canvas' layers to prepare for fading
17154         *      3. Draw view's content
17155         *      4. Draw children
17156         *      5. If necessary, draw the fading edges and restore layers
17157         *      6. Draw decorations (scrollbars for instance)
17158         */
17159
17160        // Step 1, draw the background, if needed
17161        int saveCount;
17162
17163        if (!dirtyOpaque) {
17164            drawBackground(canvas);
17165        }
17166
17167        // skip step 2 & 5 if possible (common case)
17168        final int viewFlags = mViewFlags;
17169        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
17170        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
17171        if (!verticalEdges && !horizontalEdges) {
17172            // Step 3, draw the content
17173            if (!dirtyOpaque) onDraw(canvas);
17174
17175            // Step 4, draw the children
17176            dispatchDraw(canvas);
17177
17178            // Overlay is part of the content and draws beneath Foreground
17179            if (mOverlay != null && !mOverlay.isEmpty()) {
17180                mOverlay.getOverlayView().dispatchDraw(canvas);
17181            }
17182
17183            // Step 6, draw decorations (foreground, scrollbars)
17184            onDrawForeground(canvas);
17185
17186            // we're done...
17187            return;
17188        }
17189
17190        /*
17191         * Here we do the full fledged routine...
17192         * (this is an uncommon case where speed matters less,
17193         * this is why we repeat some of the tests that have been
17194         * done above)
17195         */
17196
17197        boolean drawTop = false;
17198        boolean drawBottom = false;
17199        boolean drawLeft = false;
17200        boolean drawRight = false;
17201
17202        float topFadeStrength = 0.0f;
17203        float bottomFadeStrength = 0.0f;
17204        float leftFadeStrength = 0.0f;
17205        float rightFadeStrength = 0.0f;
17206
17207        // Step 2, save the canvas' layers
17208        int paddingLeft = mPaddingLeft;
17209
17210        final boolean offsetRequired = isPaddingOffsetRequired();
17211        if (offsetRequired) {
17212            paddingLeft += getLeftPaddingOffset();
17213        }
17214
17215        int left = mScrollX + paddingLeft;
17216        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
17217        int top = mScrollY + getFadeTop(offsetRequired);
17218        int bottom = top + getFadeHeight(offsetRequired);
17219
17220        if (offsetRequired) {
17221            right += getRightPaddingOffset();
17222            bottom += getBottomPaddingOffset();
17223        }
17224
17225        final ScrollabilityCache scrollabilityCache = mScrollCache;
17226        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
17227        int length = (int) fadeHeight;
17228
17229        // clip the fade length if top and bottom fades overlap
17230        // overlapping fades produce odd-looking artifacts
17231        if (verticalEdges && (top + length > bottom - length)) {
17232            length = (bottom - top) / 2;
17233        }
17234
17235        // also clip horizontal fades if necessary
17236        if (horizontalEdges && (left + length > right - length)) {
17237            length = (right - left) / 2;
17238        }
17239
17240        if (verticalEdges) {
17241            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
17242            drawTop = topFadeStrength * fadeHeight > 1.0f;
17243            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
17244            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
17245        }
17246
17247        if (horizontalEdges) {
17248            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
17249            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
17250            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
17251            drawRight = rightFadeStrength * fadeHeight > 1.0f;
17252        }
17253
17254        saveCount = canvas.getSaveCount();
17255
17256        int solidColor = getSolidColor();
17257        if (solidColor == 0) {
17258            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
17259
17260            if (drawTop) {
17261                canvas.saveLayer(left, top, right, top + length, null, flags);
17262            }
17263
17264            if (drawBottom) {
17265                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
17266            }
17267
17268            if (drawLeft) {
17269                canvas.saveLayer(left, top, left + length, bottom, null, flags);
17270            }
17271
17272            if (drawRight) {
17273                canvas.saveLayer(right - length, top, right, bottom, null, flags);
17274            }
17275        } else {
17276            scrollabilityCache.setFadeColor(solidColor);
17277        }
17278
17279        // Step 3, draw the content
17280        if (!dirtyOpaque) onDraw(canvas);
17281
17282        // Step 4, draw the children
17283        dispatchDraw(canvas);
17284
17285        // Step 5, draw the fade effect and restore layers
17286        final Paint p = scrollabilityCache.paint;
17287        final Matrix matrix = scrollabilityCache.matrix;
17288        final Shader fade = scrollabilityCache.shader;
17289
17290        if (drawTop) {
17291            matrix.setScale(1, fadeHeight * topFadeStrength);
17292            matrix.postTranslate(left, top);
17293            fade.setLocalMatrix(matrix);
17294            p.setShader(fade);
17295            canvas.drawRect(left, top, right, top + length, p);
17296        }
17297
17298        if (drawBottom) {
17299            matrix.setScale(1, fadeHeight * bottomFadeStrength);
17300            matrix.postRotate(180);
17301            matrix.postTranslate(left, bottom);
17302            fade.setLocalMatrix(matrix);
17303            p.setShader(fade);
17304            canvas.drawRect(left, bottom - length, right, bottom, p);
17305        }
17306
17307        if (drawLeft) {
17308            matrix.setScale(1, fadeHeight * leftFadeStrength);
17309            matrix.postRotate(-90);
17310            matrix.postTranslate(left, top);
17311            fade.setLocalMatrix(matrix);
17312            p.setShader(fade);
17313            canvas.drawRect(left, top, left + length, bottom, p);
17314        }
17315
17316        if (drawRight) {
17317            matrix.setScale(1, fadeHeight * rightFadeStrength);
17318            matrix.postRotate(90);
17319            matrix.postTranslate(right, top);
17320            fade.setLocalMatrix(matrix);
17321            p.setShader(fade);
17322            canvas.drawRect(right - length, top, right, bottom, p);
17323        }
17324
17325        canvas.restoreToCount(saveCount);
17326
17327        // Overlay is part of the content and draws beneath Foreground
17328        if (mOverlay != null && !mOverlay.isEmpty()) {
17329            mOverlay.getOverlayView().dispatchDraw(canvas);
17330        }
17331
17332        // Step 6, draw decorations (foreground, scrollbars)
17333        onDrawForeground(canvas);
17334    }
17335
17336    /**
17337     * Draws the background onto the specified canvas.
17338     *
17339     * @param canvas Canvas on which to draw the background
17340     */
17341    private void drawBackground(Canvas canvas) {
17342        final Drawable background = mBackground;
17343        if (background == null) {
17344            return;
17345        }
17346
17347        setBackgroundBounds();
17348
17349        // Attempt to use a display list if requested.
17350        if (canvas.isHardwareAccelerated() && mAttachInfo != null
17351                && mAttachInfo.mHardwareRenderer != null) {
17352            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
17353
17354            final RenderNode renderNode = mBackgroundRenderNode;
17355            if (renderNode != null && renderNode.isValid()) {
17356                setBackgroundRenderNodeProperties(renderNode);
17357                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17358                return;
17359            }
17360        }
17361
17362        final int scrollX = mScrollX;
17363        final int scrollY = mScrollY;
17364        if ((scrollX | scrollY) == 0) {
17365            background.draw(canvas);
17366        } else {
17367            canvas.translate(scrollX, scrollY);
17368            background.draw(canvas);
17369            canvas.translate(-scrollX, -scrollY);
17370        }
17371    }
17372
17373    /**
17374     * Sets the correct background bounds and rebuilds the outline, if needed.
17375     * <p/>
17376     * This is called by LayoutLib.
17377     */
17378    void setBackgroundBounds() {
17379        if (mBackgroundSizeChanged && mBackground != null) {
17380            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
17381            mBackgroundSizeChanged = false;
17382            rebuildOutline();
17383        }
17384    }
17385
17386    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
17387        renderNode.setTranslationX(mScrollX);
17388        renderNode.setTranslationY(mScrollY);
17389    }
17390
17391    /**
17392     * Creates a new display list or updates the existing display list for the
17393     * specified Drawable.
17394     *
17395     * @param drawable Drawable for which to create a display list
17396     * @param renderNode Existing RenderNode, or {@code null}
17397     * @return A valid display list for the specified drawable
17398     */
17399    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
17400        if (renderNode == null) {
17401            renderNode = RenderNode.create(drawable.getClass().getName(), this);
17402        }
17403
17404        final Rect bounds = drawable.getBounds();
17405        final int width = bounds.width();
17406        final int height = bounds.height();
17407        final DisplayListCanvas canvas = renderNode.start(width, height);
17408
17409        // Reverse left/top translation done by drawable canvas, which will
17410        // instead be applied by rendernode's LTRB bounds below. This way, the
17411        // drawable's bounds match with its rendernode bounds and its content
17412        // will lie within those bounds in the rendernode tree.
17413        canvas.translate(-bounds.left, -bounds.top);
17414
17415        try {
17416            drawable.draw(canvas);
17417        } finally {
17418            renderNode.end(canvas);
17419        }
17420
17421        // Set up drawable properties that are view-independent.
17422        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
17423        renderNode.setProjectBackwards(drawable.isProjected());
17424        renderNode.setProjectionReceiver(true);
17425        renderNode.setClipToBounds(false);
17426        return renderNode;
17427    }
17428
17429    /**
17430     * Returns the overlay for this view, creating it if it does not yet exist.
17431     * Adding drawables to the overlay will cause them to be displayed whenever
17432     * the view itself is redrawn. Objects in the overlay should be actively
17433     * managed: remove them when they should not be displayed anymore. The
17434     * overlay will always have the same size as its host view.
17435     *
17436     * <p>Note: Overlays do not currently work correctly with {@link
17437     * SurfaceView} or {@link TextureView}; contents in overlays for these
17438     * types of views may not display correctly.</p>
17439     *
17440     * @return The ViewOverlay object for this view.
17441     * @see ViewOverlay
17442     */
17443    public ViewOverlay getOverlay() {
17444        if (mOverlay == null) {
17445            mOverlay = new ViewOverlay(mContext, this);
17446        }
17447        return mOverlay;
17448    }
17449
17450    /**
17451     * Override this if your view is known to always be drawn on top of a solid color background,
17452     * and needs to draw fading edges. Returning a non-zero color enables the view system to
17453     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
17454     * should be set to 0xFF.
17455     *
17456     * @see #setVerticalFadingEdgeEnabled(boolean)
17457     * @see #setHorizontalFadingEdgeEnabled(boolean)
17458     *
17459     * @return The known solid color background for this view, or 0 if the color may vary
17460     */
17461    @ViewDebug.ExportedProperty(category = "drawing")
17462    @ColorInt
17463    public int getSolidColor() {
17464        return 0;
17465    }
17466
17467    /**
17468     * Build a human readable string representation of the specified view flags.
17469     *
17470     * @param flags the view flags to convert to a string
17471     * @return a String representing the supplied flags
17472     */
17473    private static String printFlags(int flags) {
17474        String output = "";
17475        int numFlags = 0;
17476        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
17477            output += "TAKES_FOCUS";
17478            numFlags++;
17479        }
17480
17481        switch (flags & VISIBILITY_MASK) {
17482        case INVISIBLE:
17483            if (numFlags > 0) {
17484                output += " ";
17485            }
17486            output += "INVISIBLE";
17487            // USELESS HERE numFlags++;
17488            break;
17489        case GONE:
17490            if (numFlags > 0) {
17491                output += " ";
17492            }
17493            output += "GONE";
17494            // USELESS HERE numFlags++;
17495            break;
17496        default:
17497            break;
17498        }
17499        return output;
17500    }
17501
17502    /**
17503     * Build a human readable string representation of the specified private
17504     * view flags.
17505     *
17506     * @param privateFlags the private view flags to convert to a string
17507     * @return a String representing the supplied flags
17508     */
17509    private static String printPrivateFlags(int privateFlags) {
17510        String output = "";
17511        int numFlags = 0;
17512
17513        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
17514            output += "WANTS_FOCUS";
17515            numFlags++;
17516        }
17517
17518        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
17519            if (numFlags > 0) {
17520                output += " ";
17521            }
17522            output += "FOCUSED";
17523            numFlags++;
17524        }
17525
17526        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
17527            if (numFlags > 0) {
17528                output += " ";
17529            }
17530            output += "SELECTED";
17531            numFlags++;
17532        }
17533
17534        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
17535            if (numFlags > 0) {
17536                output += " ";
17537            }
17538            output += "IS_ROOT_NAMESPACE";
17539            numFlags++;
17540        }
17541
17542        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
17543            if (numFlags > 0) {
17544                output += " ";
17545            }
17546            output += "HAS_BOUNDS";
17547            numFlags++;
17548        }
17549
17550        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
17551            if (numFlags > 0) {
17552                output += " ";
17553            }
17554            output += "DRAWN";
17555            // USELESS HERE numFlags++;
17556        }
17557        return output;
17558    }
17559
17560    /**
17561     * <p>Indicates whether or not this view's layout will be requested during
17562     * the next hierarchy layout pass.</p>
17563     *
17564     * @return true if the layout will be forced during next layout pass
17565     */
17566    public boolean isLayoutRequested() {
17567        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
17568    }
17569
17570    /**
17571     * Return true if o is a ViewGroup that is laying out using optical bounds.
17572     * @hide
17573     */
17574    public static boolean isLayoutModeOptical(Object o) {
17575        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
17576    }
17577
17578    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
17579        Insets parentInsets = mParent instanceof View ?
17580                ((View) mParent).getOpticalInsets() : Insets.NONE;
17581        Insets childInsets = getOpticalInsets();
17582        return setFrame(
17583                left   + parentInsets.left - childInsets.left,
17584                top    + parentInsets.top  - childInsets.top,
17585                right  + parentInsets.left + childInsets.right,
17586                bottom + parentInsets.top  + childInsets.bottom);
17587    }
17588
17589    /**
17590     * Assign a size and position to a view and all of its
17591     * descendants
17592     *
17593     * <p>This is the second phase of the layout mechanism.
17594     * (The first is measuring). In this phase, each parent calls
17595     * layout on all of its children to position them.
17596     * This is typically done using the child measurements
17597     * that were stored in the measure pass().</p>
17598     *
17599     * <p>Derived classes should not override this method.
17600     * Derived classes with children should override
17601     * onLayout. In that method, they should
17602     * call layout on each of their children.</p>
17603     *
17604     * @param l Left position, relative to parent
17605     * @param t Top position, relative to parent
17606     * @param r Right position, relative to parent
17607     * @param b Bottom position, relative to parent
17608     */
17609    @SuppressWarnings({"unchecked"})
17610    public void layout(int l, int t, int r, int b) {
17611        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
17612            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
17613            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17614        }
17615
17616        int oldL = mLeft;
17617        int oldT = mTop;
17618        int oldB = mBottom;
17619        int oldR = mRight;
17620
17621        boolean changed = isLayoutModeOptical(mParent) ?
17622                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
17623
17624        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
17625            onLayout(changed, l, t, r, b);
17626
17627            if (shouldDrawRoundScrollbar()) {
17628                if(mRoundScrollbarRenderer == null) {
17629                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
17630                }
17631            } else {
17632                mRoundScrollbarRenderer = null;
17633            }
17634
17635            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
17636
17637            ListenerInfo li = mListenerInfo;
17638            if (li != null && li.mOnLayoutChangeListeners != null) {
17639                ArrayList<OnLayoutChangeListener> listenersCopy =
17640                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
17641                int numListeners = listenersCopy.size();
17642                for (int i = 0; i < numListeners; ++i) {
17643                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
17644                }
17645            }
17646        }
17647
17648        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
17649        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
17650    }
17651
17652    /**
17653     * Called from layout when this view should
17654     * assign a size and position to each of its children.
17655     *
17656     * Derived classes with children should override
17657     * this method and call layout on each of
17658     * their children.
17659     * @param changed This is a new size or position for this view
17660     * @param left Left position, relative to parent
17661     * @param top Top position, relative to parent
17662     * @param right Right position, relative to parent
17663     * @param bottom Bottom position, relative to parent
17664     */
17665    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
17666    }
17667
17668    /**
17669     * Assign a size and position to this view.
17670     *
17671     * This is called from layout.
17672     *
17673     * @param left Left position, relative to parent
17674     * @param top Top position, relative to parent
17675     * @param right Right position, relative to parent
17676     * @param bottom Bottom position, relative to parent
17677     * @return true if the new size and position are different than the
17678     *         previous ones
17679     * {@hide}
17680     */
17681    protected boolean setFrame(int left, int top, int right, int bottom) {
17682        boolean changed = false;
17683
17684        if (DBG) {
17685            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
17686                    + right + "," + bottom + ")");
17687        }
17688
17689        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
17690            changed = true;
17691
17692            // Remember our drawn bit
17693            int drawn = mPrivateFlags & PFLAG_DRAWN;
17694
17695            int oldWidth = mRight - mLeft;
17696            int oldHeight = mBottom - mTop;
17697            int newWidth = right - left;
17698            int newHeight = bottom - top;
17699            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
17700
17701            // Invalidate our old position
17702            invalidate(sizeChanged);
17703
17704            mLeft = left;
17705            mTop = top;
17706            mRight = right;
17707            mBottom = bottom;
17708            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
17709
17710            mPrivateFlags |= PFLAG_HAS_BOUNDS;
17711
17712
17713            if (sizeChanged) {
17714                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
17715            }
17716
17717            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
17718                // If we are visible, force the DRAWN bit to on so that
17719                // this invalidate will go through (at least to our parent).
17720                // This is because someone may have invalidated this view
17721                // before this call to setFrame came in, thereby clearing
17722                // the DRAWN bit.
17723                mPrivateFlags |= PFLAG_DRAWN;
17724                invalidate(sizeChanged);
17725                // parent display list may need to be recreated based on a change in the bounds
17726                // of any child
17727                invalidateParentCaches();
17728            }
17729
17730            // Reset drawn bit to original value (invalidate turns it off)
17731            mPrivateFlags |= drawn;
17732
17733            mBackgroundSizeChanged = true;
17734            if (mForegroundInfo != null) {
17735                mForegroundInfo.mBoundsChanged = true;
17736            }
17737
17738            notifySubtreeAccessibilityStateChangedIfNeeded();
17739        }
17740        return changed;
17741    }
17742
17743    /**
17744     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
17745     * @hide
17746     */
17747    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
17748        setFrame(left, top, right, bottom);
17749    }
17750
17751    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
17752        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
17753        if (mOverlay != null) {
17754            mOverlay.getOverlayView().setRight(newWidth);
17755            mOverlay.getOverlayView().setBottom(newHeight);
17756        }
17757        rebuildOutline();
17758    }
17759
17760    /**
17761     * Finalize inflating a view from XML.  This is called as the last phase
17762     * of inflation, after all child views have been added.
17763     *
17764     * <p>Even if the subclass overrides onFinishInflate, they should always be
17765     * sure to call the super method, so that we get called.
17766     */
17767    @CallSuper
17768    protected void onFinishInflate() {
17769    }
17770
17771    /**
17772     * Returns the resources associated with this view.
17773     *
17774     * @return Resources object.
17775     */
17776    public Resources getResources() {
17777        return mResources;
17778    }
17779
17780    /**
17781     * Invalidates the specified Drawable.
17782     *
17783     * @param drawable the drawable to invalidate
17784     */
17785    @Override
17786    public void invalidateDrawable(@NonNull Drawable drawable) {
17787        if (verifyDrawable(drawable)) {
17788            final Rect dirty = drawable.getDirtyBounds();
17789            final int scrollX = mScrollX;
17790            final int scrollY = mScrollY;
17791
17792            invalidate(dirty.left + scrollX, dirty.top + scrollY,
17793                    dirty.right + scrollX, dirty.bottom + scrollY);
17794            rebuildOutline();
17795        }
17796    }
17797
17798    /**
17799     * Schedules an action on a drawable to occur at a specified time.
17800     *
17801     * @param who the recipient of the action
17802     * @param what the action to run on the drawable
17803     * @param when the time at which the action must occur. Uses the
17804     *        {@link SystemClock#uptimeMillis} timebase.
17805     */
17806    @Override
17807    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
17808        if (verifyDrawable(who) && what != null) {
17809            final long delay = when - SystemClock.uptimeMillis();
17810            if (mAttachInfo != null) {
17811                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17812                        Choreographer.CALLBACK_ANIMATION, what, who,
17813                        Choreographer.subtractFrameDelay(delay));
17814            } else {
17815                // Postpone the runnable until we know
17816                // on which thread it needs to run.
17817                getRunQueue().postDelayed(what, delay);
17818            }
17819        }
17820    }
17821
17822    /**
17823     * Cancels a scheduled action on a drawable.
17824     *
17825     * @param who the recipient of the action
17826     * @param what the action to cancel
17827     */
17828    @Override
17829    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
17830        if (verifyDrawable(who) && what != null) {
17831            if (mAttachInfo != null) {
17832                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17833                        Choreographer.CALLBACK_ANIMATION, what, who);
17834            }
17835            getRunQueue().removeCallbacks(what);
17836        }
17837    }
17838
17839    /**
17840     * Unschedule any events associated with the given Drawable.  This can be
17841     * used when selecting a new Drawable into a view, so that the previous
17842     * one is completely unscheduled.
17843     *
17844     * @param who The Drawable to unschedule.
17845     *
17846     * @see #drawableStateChanged
17847     */
17848    public void unscheduleDrawable(Drawable who) {
17849        if (mAttachInfo != null && who != null) {
17850            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17851                    Choreographer.CALLBACK_ANIMATION, null, who);
17852        }
17853    }
17854
17855    /**
17856     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
17857     * that the View directionality can and will be resolved before its Drawables.
17858     *
17859     * Will call {@link View#onResolveDrawables} when resolution is done.
17860     *
17861     * @hide
17862     */
17863    protected void resolveDrawables() {
17864        // Drawables resolution may need to happen before resolving the layout direction (which is
17865        // done only during the measure() call).
17866        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
17867        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
17868        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
17869        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
17870        // direction to be resolved as its resolved value will be the same as its raw value.
17871        if (!isLayoutDirectionResolved() &&
17872                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17873            return;
17874        }
17875
17876        final int layoutDirection = isLayoutDirectionResolved() ?
17877                getLayoutDirection() : getRawLayoutDirection();
17878
17879        if (mBackground != null) {
17880            mBackground.setLayoutDirection(layoutDirection);
17881        }
17882        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17883            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17884        }
17885        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17886        onResolveDrawables(layoutDirection);
17887    }
17888
17889    boolean areDrawablesResolved() {
17890        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17891    }
17892
17893    /**
17894     * Called when layout direction has been resolved.
17895     *
17896     * The default implementation does nothing.
17897     *
17898     * @param layoutDirection The resolved layout direction.
17899     *
17900     * @see #LAYOUT_DIRECTION_LTR
17901     * @see #LAYOUT_DIRECTION_RTL
17902     *
17903     * @hide
17904     */
17905    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17906    }
17907
17908    /**
17909     * @hide
17910     */
17911    protected void resetResolvedDrawables() {
17912        resetResolvedDrawablesInternal();
17913    }
17914
17915    void resetResolvedDrawablesInternal() {
17916        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17917    }
17918
17919    /**
17920     * If your view subclass is displaying its own Drawable objects, it should
17921     * override this function and return true for any Drawable it is
17922     * displaying.  This allows animations for those drawables to be
17923     * scheduled.
17924     *
17925     * <p>Be sure to call through to the super class when overriding this
17926     * function.
17927     *
17928     * @param who The Drawable to verify.  Return true if it is one you are
17929     *            displaying, else return the result of calling through to the
17930     *            super class.
17931     *
17932     * @return boolean If true than the Drawable is being displayed in the
17933     *         view; else false and it is not allowed to animate.
17934     *
17935     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17936     * @see #drawableStateChanged()
17937     */
17938    @CallSuper
17939    protected boolean verifyDrawable(@NonNull Drawable who) {
17940        // Avoid verifying the scroll bar drawable so that we don't end up in
17941        // an invalidation loop. This effectively prevents the scroll bar
17942        // drawable from triggering invalidations and scheduling runnables.
17943        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17944    }
17945
17946    /**
17947     * This function is called whenever the state of the view changes in such
17948     * a way that it impacts the state of drawables being shown.
17949     * <p>
17950     * If the View has a StateListAnimator, it will also be called to run necessary state
17951     * change animations.
17952     * <p>
17953     * Be sure to call through to the superclass when overriding this function.
17954     *
17955     * @see Drawable#setState(int[])
17956     */
17957    @CallSuper
17958    protected void drawableStateChanged() {
17959        final int[] state = getDrawableState();
17960        boolean changed = false;
17961
17962        final Drawable bg = mBackground;
17963        if (bg != null && bg.isStateful()) {
17964            changed |= bg.setState(state);
17965        }
17966
17967        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17968        if (fg != null && fg.isStateful()) {
17969            changed |= fg.setState(state);
17970        }
17971
17972        if (mScrollCache != null) {
17973            final Drawable scrollBar = mScrollCache.scrollBar;
17974            if (scrollBar != null && scrollBar.isStateful()) {
17975                changed |= scrollBar.setState(state)
17976                        && mScrollCache.state != ScrollabilityCache.OFF;
17977            }
17978        }
17979
17980        if (mStateListAnimator != null) {
17981            mStateListAnimator.setState(state);
17982        }
17983
17984        if (changed) {
17985            invalidate();
17986        }
17987    }
17988
17989    /**
17990     * This function is called whenever the view hotspot changes and needs to
17991     * be propagated to drawables or child views managed by the view.
17992     * <p>
17993     * Dispatching to child views is handled by
17994     * {@link #dispatchDrawableHotspotChanged(float, float)}.
17995     * <p>
17996     * Be sure to call through to the superclass when overriding this function.
17997     *
17998     * @param x hotspot x coordinate
17999     * @param y hotspot y coordinate
18000     */
18001    @CallSuper
18002    public void drawableHotspotChanged(float x, float y) {
18003        if (mBackground != null) {
18004            mBackground.setHotspot(x, y);
18005        }
18006        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18007            mForegroundInfo.mDrawable.setHotspot(x, y);
18008        }
18009
18010        dispatchDrawableHotspotChanged(x, y);
18011    }
18012
18013    /**
18014     * Dispatches drawableHotspotChanged to all of this View's children.
18015     *
18016     * @param x hotspot x coordinate
18017     * @param y hotspot y coordinate
18018     * @see #drawableHotspotChanged(float, float)
18019     */
18020    public void dispatchDrawableHotspotChanged(float x, float y) {
18021    }
18022
18023    /**
18024     * Call this to force a view to update its drawable state. This will cause
18025     * drawableStateChanged to be called on this view. Views that are interested
18026     * in the new state should call getDrawableState.
18027     *
18028     * @see #drawableStateChanged
18029     * @see #getDrawableState
18030     */
18031    public void refreshDrawableState() {
18032        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
18033        drawableStateChanged();
18034
18035        ViewParent parent = mParent;
18036        if (parent != null) {
18037            parent.childDrawableStateChanged(this);
18038        }
18039    }
18040
18041    /**
18042     * Return an array of resource IDs of the drawable states representing the
18043     * current state of the view.
18044     *
18045     * @return The current drawable state
18046     *
18047     * @see Drawable#setState(int[])
18048     * @see #drawableStateChanged()
18049     * @see #onCreateDrawableState(int)
18050     */
18051    public final int[] getDrawableState() {
18052        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
18053            return mDrawableState;
18054        } else {
18055            mDrawableState = onCreateDrawableState(0);
18056            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
18057            return mDrawableState;
18058        }
18059    }
18060
18061    /**
18062     * Generate the new {@link android.graphics.drawable.Drawable} state for
18063     * this view. This is called by the view
18064     * system when the cached Drawable state is determined to be invalid.  To
18065     * retrieve the current state, you should use {@link #getDrawableState}.
18066     *
18067     * @param extraSpace if non-zero, this is the number of extra entries you
18068     * would like in the returned array in which you can place your own
18069     * states.
18070     *
18071     * @return Returns an array holding the current {@link Drawable} state of
18072     * the view.
18073     *
18074     * @see #mergeDrawableStates(int[], int[])
18075     */
18076    protected int[] onCreateDrawableState(int extraSpace) {
18077        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
18078                mParent instanceof View) {
18079            return ((View) mParent).onCreateDrawableState(extraSpace);
18080        }
18081
18082        int[] drawableState;
18083
18084        int privateFlags = mPrivateFlags;
18085
18086        int viewStateIndex = 0;
18087        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
18088        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
18089        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
18090        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
18091        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
18092        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
18093        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
18094                ThreadedRenderer.isAvailable()) {
18095            // This is set if HW acceleration is requested, even if the current
18096            // process doesn't allow it.  This is just to allow app preview
18097            // windows to better match their app.
18098            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
18099        }
18100        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
18101
18102        final int privateFlags2 = mPrivateFlags2;
18103        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
18104            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
18105        }
18106        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
18107            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
18108        }
18109
18110        drawableState = StateSet.get(viewStateIndex);
18111
18112        //noinspection ConstantIfStatement
18113        if (false) {
18114            Log.i("View", "drawableStateIndex=" + viewStateIndex);
18115            Log.i("View", toString()
18116                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
18117                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
18118                    + " fo=" + hasFocus()
18119                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
18120                    + " wf=" + hasWindowFocus()
18121                    + ": " + Arrays.toString(drawableState));
18122        }
18123
18124        if (extraSpace == 0) {
18125            return drawableState;
18126        }
18127
18128        final int[] fullState;
18129        if (drawableState != null) {
18130            fullState = new int[drawableState.length + extraSpace];
18131            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
18132        } else {
18133            fullState = new int[extraSpace];
18134        }
18135
18136        return fullState;
18137    }
18138
18139    /**
18140     * Merge your own state values in <var>additionalState</var> into the base
18141     * state values <var>baseState</var> that were returned by
18142     * {@link #onCreateDrawableState(int)}.
18143     *
18144     * @param baseState The base state values returned by
18145     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
18146     * own additional state values.
18147     *
18148     * @param additionalState The additional state values you would like
18149     * added to <var>baseState</var>; this array is not modified.
18150     *
18151     * @return As a convenience, the <var>baseState</var> array you originally
18152     * passed into the function is returned.
18153     *
18154     * @see #onCreateDrawableState(int)
18155     */
18156    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
18157        final int N = baseState.length;
18158        int i = N - 1;
18159        while (i >= 0 && baseState[i] == 0) {
18160            i--;
18161        }
18162        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
18163        return baseState;
18164    }
18165
18166    /**
18167     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
18168     * on all Drawable objects associated with this view.
18169     * <p>
18170     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
18171     * attached to this view.
18172     */
18173    @CallSuper
18174    public void jumpDrawablesToCurrentState() {
18175        if (mBackground != null) {
18176            mBackground.jumpToCurrentState();
18177        }
18178        if (mStateListAnimator != null) {
18179            mStateListAnimator.jumpToCurrentState();
18180        }
18181        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18182            mForegroundInfo.mDrawable.jumpToCurrentState();
18183        }
18184    }
18185
18186    /**
18187     * Sets the background color for this view.
18188     * @param color the color of the background
18189     */
18190    @RemotableViewMethod
18191    public void setBackgroundColor(@ColorInt int color) {
18192        if (mBackground instanceof ColorDrawable) {
18193            ((ColorDrawable) mBackground.mutate()).setColor(color);
18194            computeOpaqueFlags();
18195            mBackgroundResource = 0;
18196        } else {
18197            setBackground(new ColorDrawable(color));
18198        }
18199    }
18200
18201    /**
18202     * Set the background to a given resource. The resource should refer to
18203     * a Drawable object or 0 to remove the background.
18204     * @param resid The identifier of the resource.
18205     *
18206     * @attr ref android.R.styleable#View_background
18207     */
18208    @RemotableViewMethod
18209    public void setBackgroundResource(@DrawableRes int resid) {
18210        if (resid != 0 && resid == mBackgroundResource) {
18211            return;
18212        }
18213
18214        Drawable d = null;
18215        if (resid != 0) {
18216            d = mContext.getDrawable(resid);
18217        }
18218        setBackground(d);
18219
18220        mBackgroundResource = resid;
18221    }
18222
18223    /**
18224     * Set the background to a given Drawable, or remove the background. If the
18225     * background has padding, this View's padding is set to the background's
18226     * padding. However, when a background is removed, this View's padding isn't
18227     * touched. If setting the padding is desired, please use
18228     * {@link #setPadding(int, int, int, int)}.
18229     *
18230     * @param background The Drawable to use as the background, or null to remove the
18231     *        background
18232     */
18233    public void setBackground(Drawable background) {
18234        //noinspection deprecation
18235        setBackgroundDrawable(background);
18236    }
18237
18238    /**
18239     * @deprecated use {@link #setBackground(Drawable)} instead
18240     */
18241    @Deprecated
18242    public void setBackgroundDrawable(Drawable background) {
18243        computeOpaqueFlags();
18244
18245        if (background == mBackground) {
18246            return;
18247        }
18248
18249        boolean requestLayout = false;
18250
18251        mBackgroundResource = 0;
18252
18253        /*
18254         * Regardless of whether we're setting a new background or not, we want
18255         * to clear the previous drawable. setVisible first while we still have the callback set.
18256         */
18257        if (mBackground != null) {
18258            if (isAttachedToWindow()) {
18259                mBackground.setVisible(false, false);
18260            }
18261            mBackground.setCallback(null);
18262            unscheduleDrawable(mBackground);
18263        }
18264
18265        if (background != null) {
18266            Rect padding = sThreadLocal.get();
18267            if (padding == null) {
18268                padding = new Rect();
18269                sThreadLocal.set(padding);
18270            }
18271            resetResolvedDrawablesInternal();
18272            background.setLayoutDirection(getLayoutDirection());
18273            if (background.getPadding(padding)) {
18274                resetResolvedPaddingInternal();
18275                switch (background.getLayoutDirection()) {
18276                    case LAYOUT_DIRECTION_RTL:
18277                        mUserPaddingLeftInitial = padding.right;
18278                        mUserPaddingRightInitial = padding.left;
18279                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
18280                        break;
18281                    case LAYOUT_DIRECTION_LTR:
18282                    default:
18283                        mUserPaddingLeftInitial = padding.left;
18284                        mUserPaddingRightInitial = padding.right;
18285                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
18286                }
18287                mLeftPaddingDefined = false;
18288                mRightPaddingDefined = false;
18289            }
18290
18291            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
18292            // if it has a different minimum size, we should layout again
18293            if (mBackground == null
18294                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
18295                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
18296                requestLayout = true;
18297            }
18298
18299            // Set mBackground before we set this as the callback and start making other
18300            // background drawable state change calls. In particular, the setVisible call below
18301            // can result in drawables attempting to start animations or otherwise invalidate,
18302            // which requires the view set as the callback (us) to recognize the drawable as
18303            // belonging to it as per verifyDrawable.
18304            mBackground = background;
18305            if (background.isStateful()) {
18306                background.setState(getDrawableState());
18307            }
18308            if (isAttachedToWindow()) {
18309                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18310            }
18311
18312            applyBackgroundTint();
18313
18314            // Set callback last, since the view may still be initializing.
18315            background.setCallback(this);
18316
18317            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18318                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18319                requestLayout = true;
18320            }
18321        } else {
18322            /* Remove the background */
18323            mBackground = null;
18324            if ((mViewFlags & WILL_NOT_DRAW) != 0
18325                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
18326                mPrivateFlags |= PFLAG_SKIP_DRAW;
18327            }
18328
18329            /*
18330             * When the background is set, we try to apply its padding to this
18331             * View. When the background is removed, we don't touch this View's
18332             * padding. This is noted in the Javadocs. Hence, we don't need to
18333             * requestLayout(), the invalidate() below is sufficient.
18334             */
18335
18336            // The old background's minimum size could have affected this
18337            // View's layout, so let's requestLayout
18338            requestLayout = true;
18339        }
18340
18341        computeOpaqueFlags();
18342
18343        if (requestLayout) {
18344            requestLayout();
18345        }
18346
18347        mBackgroundSizeChanged = true;
18348        invalidate(true);
18349        invalidateOutline();
18350    }
18351
18352    /**
18353     * Gets the background drawable
18354     *
18355     * @return The drawable used as the background for this view, if any.
18356     *
18357     * @see #setBackground(Drawable)
18358     *
18359     * @attr ref android.R.styleable#View_background
18360     */
18361    public Drawable getBackground() {
18362        return mBackground;
18363    }
18364
18365    /**
18366     * Applies a tint to the background drawable. Does not modify the current tint
18367     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18368     * <p>
18369     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
18370     * mutate the drawable and apply the specified tint and tint mode using
18371     * {@link Drawable#setTintList(ColorStateList)}.
18372     *
18373     * @param tint the tint to apply, may be {@code null} to clear tint
18374     *
18375     * @attr ref android.R.styleable#View_backgroundTint
18376     * @see #getBackgroundTintList()
18377     * @see Drawable#setTintList(ColorStateList)
18378     */
18379    public void setBackgroundTintList(@Nullable ColorStateList tint) {
18380        if (mBackgroundTint == null) {
18381            mBackgroundTint = new TintInfo();
18382        }
18383        mBackgroundTint.mTintList = tint;
18384        mBackgroundTint.mHasTintList = true;
18385
18386        applyBackgroundTint();
18387    }
18388
18389    /**
18390     * Return the tint applied to the background drawable, if specified.
18391     *
18392     * @return the tint applied to the background drawable
18393     * @attr ref android.R.styleable#View_backgroundTint
18394     * @see #setBackgroundTintList(ColorStateList)
18395     */
18396    @Nullable
18397    public ColorStateList getBackgroundTintList() {
18398        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
18399    }
18400
18401    /**
18402     * Specifies the blending mode used to apply the tint specified by
18403     * {@link #setBackgroundTintList(ColorStateList)}} to the background
18404     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18405     *
18406     * @param tintMode the blending mode used to apply the tint, may be
18407     *                 {@code null} to clear tint
18408     * @attr ref android.R.styleable#View_backgroundTintMode
18409     * @see #getBackgroundTintMode()
18410     * @see Drawable#setTintMode(PorterDuff.Mode)
18411     */
18412    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18413        if (mBackgroundTint == null) {
18414            mBackgroundTint = new TintInfo();
18415        }
18416        mBackgroundTint.mTintMode = tintMode;
18417        mBackgroundTint.mHasTintMode = true;
18418
18419        applyBackgroundTint();
18420    }
18421
18422    /**
18423     * Return the blending mode used to apply the tint to the background
18424     * drawable, if specified.
18425     *
18426     * @return the blending mode used to apply the tint to the background
18427     *         drawable
18428     * @attr ref android.R.styleable#View_backgroundTintMode
18429     * @see #setBackgroundTintMode(PorterDuff.Mode)
18430     */
18431    @Nullable
18432    public PorterDuff.Mode getBackgroundTintMode() {
18433        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
18434    }
18435
18436    private void applyBackgroundTint() {
18437        if (mBackground != null && mBackgroundTint != null) {
18438            final TintInfo tintInfo = mBackgroundTint;
18439            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18440                mBackground = mBackground.mutate();
18441
18442                if (tintInfo.mHasTintList) {
18443                    mBackground.setTintList(tintInfo.mTintList);
18444                }
18445
18446                if (tintInfo.mHasTintMode) {
18447                    mBackground.setTintMode(tintInfo.mTintMode);
18448                }
18449
18450                // The drawable (or one of its children) may not have been
18451                // stateful before applying the tint, so let's try again.
18452                if (mBackground.isStateful()) {
18453                    mBackground.setState(getDrawableState());
18454                }
18455            }
18456        }
18457    }
18458
18459    /**
18460     * Returns the drawable used as the foreground of this View. The
18461     * foreground drawable, if non-null, is always drawn on top of the view's content.
18462     *
18463     * @return a Drawable or null if no foreground was set
18464     *
18465     * @see #onDrawForeground(Canvas)
18466     */
18467    public Drawable getForeground() {
18468        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18469    }
18470
18471    /**
18472     * Supply a Drawable that is to be rendered on top of all of the content in the view.
18473     *
18474     * @param foreground the Drawable to be drawn on top of the children
18475     *
18476     * @attr ref android.R.styleable#View_foreground
18477     */
18478    public void setForeground(Drawable foreground) {
18479        if (mForegroundInfo == null) {
18480            if (foreground == null) {
18481                // Nothing to do.
18482                return;
18483            }
18484            mForegroundInfo = new ForegroundInfo();
18485        }
18486
18487        if (foreground == mForegroundInfo.mDrawable) {
18488            // Nothing to do
18489            return;
18490        }
18491
18492        if (mForegroundInfo.mDrawable != null) {
18493            if (isAttachedToWindow()) {
18494                mForegroundInfo.mDrawable.setVisible(false, false);
18495            }
18496            mForegroundInfo.mDrawable.setCallback(null);
18497            unscheduleDrawable(mForegroundInfo.mDrawable);
18498        }
18499
18500        mForegroundInfo.mDrawable = foreground;
18501        mForegroundInfo.mBoundsChanged = true;
18502        if (foreground != null) {
18503            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18504                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18505            }
18506            foreground.setLayoutDirection(getLayoutDirection());
18507            if (foreground.isStateful()) {
18508                foreground.setState(getDrawableState());
18509            }
18510            applyForegroundTint();
18511            if (isAttachedToWindow()) {
18512                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18513            }
18514            // Set callback last, since the view may still be initializing.
18515            foreground.setCallback(this);
18516        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
18517            mPrivateFlags |= PFLAG_SKIP_DRAW;
18518        }
18519        requestLayout();
18520        invalidate();
18521    }
18522
18523    /**
18524     * Magic bit used to support features of framework-internal window decor implementation details.
18525     * This used to live exclusively in FrameLayout.
18526     *
18527     * @return true if the foreground should draw inside the padding region or false
18528     *         if it should draw inset by the view's padding
18529     * @hide internal use only; only used by FrameLayout and internal screen layouts.
18530     */
18531    public boolean isForegroundInsidePadding() {
18532        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
18533    }
18534
18535    /**
18536     * Describes how the foreground is positioned.
18537     *
18538     * @return foreground gravity.
18539     *
18540     * @see #setForegroundGravity(int)
18541     *
18542     * @attr ref android.R.styleable#View_foregroundGravity
18543     */
18544    public int getForegroundGravity() {
18545        return mForegroundInfo != null ? mForegroundInfo.mGravity
18546                : Gravity.START | Gravity.TOP;
18547    }
18548
18549    /**
18550     * Describes how the foreground is positioned. Defaults to START and TOP.
18551     *
18552     * @param gravity see {@link android.view.Gravity}
18553     *
18554     * @see #getForegroundGravity()
18555     *
18556     * @attr ref android.R.styleable#View_foregroundGravity
18557     */
18558    public void setForegroundGravity(int gravity) {
18559        if (mForegroundInfo == null) {
18560            mForegroundInfo = new ForegroundInfo();
18561        }
18562
18563        if (mForegroundInfo.mGravity != gravity) {
18564            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
18565                gravity |= Gravity.START;
18566            }
18567
18568            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
18569                gravity |= Gravity.TOP;
18570            }
18571
18572            mForegroundInfo.mGravity = gravity;
18573            requestLayout();
18574        }
18575    }
18576
18577    /**
18578     * Applies a tint to the foreground drawable. Does not modify the current tint
18579     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18580     * <p>
18581     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
18582     * mutate the drawable and apply the specified tint and tint mode using
18583     * {@link Drawable#setTintList(ColorStateList)}.
18584     *
18585     * @param tint the tint to apply, may be {@code null} to clear tint
18586     *
18587     * @attr ref android.R.styleable#View_foregroundTint
18588     * @see #getForegroundTintList()
18589     * @see Drawable#setTintList(ColorStateList)
18590     */
18591    public void setForegroundTintList(@Nullable ColorStateList tint) {
18592        if (mForegroundInfo == null) {
18593            mForegroundInfo = new ForegroundInfo();
18594        }
18595        if (mForegroundInfo.mTintInfo == null) {
18596            mForegroundInfo.mTintInfo = new TintInfo();
18597        }
18598        mForegroundInfo.mTintInfo.mTintList = tint;
18599        mForegroundInfo.mTintInfo.mHasTintList = true;
18600
18601        applyForegroundTint();
18602    }
18603
18604    /**
18605     * Return the tint applied to the foreground drawable, if specified.
18606     *
18607     * @return the tint applied to the foreground drawable
18608     * @attr ref android.R.styleable#View_foregroundTint
18609     * @see #setForegroundTintList(ColorStateList)
18610     */
18611    @Nullable
18612    public ColorStateList getForegroundTintList() {
18613        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18614                ? mForegroundInfo.mTintInfo.mTintList : null;
18615    }
18616
18617    /**
18618     * Specifies the blending mode used to apply the tint specified by
18619     * {@link #setForegroundTintList(ColorStateList)}} to the background
18620     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18621     *
18622     * @param tintMode the blending mode used to apply the tint, may be
18623     *                 {@code null} to clear tint
18624     * @attr ref android.R.styleable#View_foregroundTintMode
18625     * @see #getForegroundTintMode()
18626     * @see Drawable#setTintMode(PorterDuff.Mode)
18627     */
18628    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18629        if (mForegroundInfo == null) {
18630            mForegroundInfo = new ForegroundInfo();
18631        }
18632        if (mForegroundInfo.mTintInfo == null) {
18633            mForegroundInfo.mTintInfo = new TintInfo();
18634        }
18635        mForegroundInfo.mTintInfo.mTintMode = tintMode;
18636        mForegroundInfo.mTintInfo.mHasTintMode = true;
18637
18638        applyForegroundTint();
18639    }
18640
18641    /**
18642     * Return the blending mode used to apply the tint to the foreground
18643     * drawable, if specified.
18644     *
18645     * @return the blending mode used to apply the tint to the foreground
18646     *         drawable
18647     * @attr ref android.R.styleable#View_foregroundTintMode
18648     * @see #setForegroundTintMode(PorterDuff.Mode)
18649     */
18650    @Nullable
18651    public PorterDuff.Mode getForegroundTintMode() {
18652        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
18653                ? mForegroundInfo.mTintInfo.mTintMode : null;
18654    }
18655
18656    private void applyForegroundTint() {
18657        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
18658                && mForegroundInfo.mTintInfo != null) {
18659            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
18660            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18661                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
18662
18663                if (tintInfo.mHasTintList) {
18664                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
18665                }
18666
18667                if (tintInfo.mHasTintMode) {
18668                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
18669                }
18670
18671                // The drawable (or one of its children) may not have been
18672                // stateful before applying the tint, so let's try again.
18673                if (mForegroundInfo.mDrawable.isStateful()) {
18674                    mForegroundInfo.mDrawable.setState(getDrawableState());
18675                }
18676            }
18677        }
18678    }
18679
18680    /**
18681     * Draw any foreground content for this view.
18682     *
18683     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
18684     * drawable or other view-specific decorations. The foreground is drawn on top of the
18685     * primary view content.</p>
18686     *
18687     * @param canvas canvas to draw into
18688     */
18689    public void onDrawForeground(Canvas canvas) {
18690        onDrawScrollIndicators(canvas);
18691        onDrawScrollBars(canvas);
18692
18693        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18694        if (foreground != null) {
18695            if (mForegroundInfo.mBoundsChanged) {
18696                mForegroundInfo.mBoundsChanged = false;
18697                final Rect selfBounds = mForegroundInfo.mSelfBounds;
18698                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
18699
18700                if (mForegroundInfo.mInsidePadding) {
18701                    selfBounds.set(0, 0, getWidth(), getHeight());
18702                } else {
18703                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
18704                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
18705                }
18706
18707                final int ld = getLayoutDirection();
18708                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
18709                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
18710                foreground.setBounds(overlayBounds);
18711            }
18712
18713            foreground.draw(canvas);
18714        }
18715    }
18716
18717    /**
18718     * Sets the padding. The view may add on the space required to display
18719     * the scrollbars, depending on the style and visibility of the scrollbars.
18720     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
18721     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
18722     * from the values set in this call.
18723     *
18724     * @attr ref android.R.styleable#View_padding
18725     * @attr ref android.R.styleable#View_paddingBottom
18726     * @attr ref android.R.styleable#View_paddingLeft
18727     * @attr ref android.R.styleable#View_paddingRight
18728     * @attr ref android.R.styleable#View_paddingTop
18729     * @param left the left padding in pixels
18730     * @param top the top padding in pixels
18731     * @param right the right padding in pixels
18732     * @param bottom the bottom padding in pixels
18733     */
18734    public void setPadding(int left, int top, int right, int bottom) {
18735        resetResolvedPaddingInternal();
18736
18737        mUserPaddingStart = UNDEFINED_PADDING;
18738        mUserPaddingEnd = UNDEFINED_PADDING;
18739
18740        mUserPaddingLeftInitial = left;
18741        mUserPaddingRightInitial = right;
18742
18743        mLeftPaddingDefined = true;
18744        mRightPaddingDefined = true;
18745
18746        internalSetPadding(left, top, right, bottom);
18747    }
18748
18749    /**
18750     * @hide
18751     */
18752    protected void internalSetPadding(int left, int top, int right, int bottom) {
18753        mUserPaddingLeft = left;
18754        mUserPaddingRight = right;
18755        mUserPaddingBottom = bottom;
18756
18757        final int viewFlags = mViewFlags;
18758        boolean changed = false;
18759
18760        // Common case is there are no scroll bars.
18761        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
18762            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
18763                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
18764                        ? 0 : getVerticalScrollbarWidth();
18765                switch (mVerticalScrollbarPosition) {
18766                    case SCROLLBAR_POSITION_DEFAULT:
18767                        if (isLayoutRtl()) {
18768                            left += offset;
18769                        } else {
18770                            right += offset;
18771                        }
18772                        break;
18773                    case SCROLLBAR_POSITION_RIGHT:
18774                        right += offset;
18775                        break;
18776                    case SCROLLBAR_POSITION_LEFT:
18777                        left += offset;
18778                        break;
18779                }
18780            }
18781            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
18782                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
18783                        ? 0 : getHorizontalScrollbarHeight();
18784            }
18785        }
18786
18787        if (mPaddingLeft != left) {
18788            changed = true;
18789            mPaddingLeft = left;
18790        }
18791        if (mPaddingTop != top) {
18792            changed = true;
18793            mPaddingTop = top;
18794        }
18795        if (mPaddingRight != right) {
18796            changed = true;
18797            mPaddingRight = right;
18798        }
18799        if (mPaddingBottom != bottom) {
18800            changed = true;
18801            mPaddingBottom = bottom;
18802        }
18803
18804        if (changed) {
18805            requestLayout();
18806            invalidateOutline();
18807        }
18808    }
18809
18810    /**
18811     * Sets the relative padding. The view may add on the space required to display
18812     * the scrollbars, depending on the style and visibility of the scrollbars.
18813     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
18814     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
18815     * from the values set in this call.
18816     *
18817     * @attr ref android.R.styleable#View_padding
18818     * @attr ref android.R.styleable#View_paddingBottom
18819     * @attr ref android.R.styleable#View_paddingStart
18820     * @attr ref android.R.styleable#View_paddingEnd
18821     * @attr ref android.R.styleable#View_paddingTop
18822     * @param start the start padding in pixels
18823     * @param top the top padding in pixels
18824     * @param end the end padding in pixels
18825     * @param bottom the bottom padding in pixels
18826     */
18827    public void setPaddingRelative(int start, int top, int end, int bottom) {
18828        resetResolvedPaddingInternal();
18829
18830        mUserPaddingStart = start;
18831        mUserPaddingEnd = end;
18832        mLeftPaddingDefined = true;
18833        mRightPaddingDefined = true;
18834
18835        switch(getLayoutDirection()) {
18836            case LAYOUT_DIRECTION_RTL:
18837                mUserPaddingLeftInitial = end;
18838                mUserPaddingRightInitial = start;
18839                internalSetPadding(end, top, start, bottom);
18840                break;
18841            case LAYOUT_DIRECTION_LTR:
18842            default:
18843                mUserPaddingLeftInitial = start;
18844                mUserPaddingRightInitial = end;
18845                internalSetPadding(start, top, end, bottom);
18846        }
18847    }
18848
18849    /**
18850     * Returns the top padding of this view.
18851     *
18852     * @return the top padding in pixels
18853     */
18854    public int getPaddingTop() {
18855        return mPaddingTop;
18856    }
18857
18858    /**
18859     * Returns the bottom padding of this view. If there are inset and enabled
18860     * scrollbars, this value may include the space required to display the
18861     * scrollbars as well.
18862     *
18863     * @return the bottom padding in pixels
18864     */
18865    public int getPaddingBottom() {
18866        return mPaddingBottom;
18867    }
18868
18869    /**
18870     * Returns the left padding of this view. If there are inset and enabled
18871     * scrollbars, this value may include the space required to display the
18872     * scrollbars as well.
18873     *
18874     * @return the left padding in pixels
18875     */
18876    public int getPaddingLeft() {
18877        if (!isPaddingResolved()) {
18878            resolvePadding();
18879        }
18880        return mPaddingLeft;
18881    }
18882
18883    /**
18884     * Returns the start padding of this view depending on its resolved layout direction.
18885     * If there are inset and enabled scrollbars, this value may include the space
18886     * required to display the scrollbars as well.
18887     *
18888     * @return the start padding in pixels
18889     */
18890    public int getPaddingStart() {
18891        if (!isPaddingResolved()) {
18892            resolvePadding();
18893        }
18894        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18895                mPaddingRight : mPaddingLeft;
18896    }
18897
18898    /**
18899     * Returns the right padding of this view. If there are inset and enabled
18900     * scrollbars, this value may include the space required to display the
18901     * scrollbars as well.
18902     *
18903     * @return the right padding in pixels
18904     */
18905    public int getPaddingRight() {
18906        if (!isPaddingResolved()) {
18907            resolvePadding();
18908        }
18909        return mPaddingRight;
18910    }
18911
18912    /**
18913     * Returns the end padding of this view depending on its resolved layout direction.
18914     * If there are inset and enabled scrollbars, this value may include the space
18915     * required to display the scrollbars as well.
18916     *
18917     * @return the end padding in pixels
18918     */
18919    public int getPaddingEnd() {
18920        if (!isPaddingResolved()) {
18921            resolvePadding();
18922        }
18923        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18924                mPaddingLeft : mPaddingRight;
18925    }
18926
18927    /**
18928     * Return if the padding has been set through relative values
18929     * {@link #setPaddingRelative(int, int, int, int)} or through
18930     * @attr ref android.R.styleable#View_paddingStart or
18931     * @attr ref android.R.styleable#View_paddingEnd
18932     *
18933     * @return true if the padding is relative or false if it is not.
18934     */
18935    public boolean isPaddingRelative() {
18936        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18937    }
18938
18939    Insets computeOpticalInsets() {
18940        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18941    }
18942
18943    /**
18944     * @hide
18945     */
18946    public void resetPaddingToInitialValues() {
18947        if (isRtlCompatibilityMode()) {
18948            mPaddingLeft = mUserPaddingLeftInitial;
18949            mPaddingRight = mUserPaddingRightInitial;
18950            return;
18951        }
18952        if (isLayoutRtl()) {
18953            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18954            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18955        } else {
18956            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18957            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18958        }
18959    }
18960
18961    /**
18962     * @hide
18963     */
18964    public Insets getOpticalInsets() {
18965        if (mLayoutInsets == null) {
18966            mLayoutInsets = computeOpticalInsets();
18967        }
18968        return mLayoutInsets;
18969    }
18970
18971    /**
18972     * Set this view's optical insets.
18973     *
18974     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
18975     * property. Views that compute their own optical insets should call it as part of measurement.
18976     * This method does not request layout. If you are setting optical insets outside of
18977     * measure/layout itself you will want to call requestLayout() yourself.
18978     * </p>
18979     * @hide
18980     */
18981    public void setOpticalInsets(Insets insets) {
18982        mLayoutInsets = insets;
18983    }
18984
18985    /**
18986     * Changes the selection state of this view. A view can be selected or not.
18987     * Note that selection is not the same as focus. Views are typically
18988     * selected in the context of an AdapterView like ListView or GridView;
18989     * the selected view is the view that is highlighted.
18990     *
18991     * @param selected true if the view must be selected, false otherwise
18992     */
18993    public void setSelected(boolean selected) {
18994        //noinspection DoubleNegation
18995        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
18996            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
18997            if (!selected) resetPressedState();
18998            invalidate(true);
18999            refreshDrawableState();
19000            dispatchSetSelected(selected);
19001            if (selected) {
19002                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
19003            } else {
19004                notifyViewAccessibilityStateChangedIfNeeded(
19005                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
19006            }
19007        }
19008    }
19009
19010    /**
19011     * Dispatch setSelected to all of this View's children.
19012     *
19013     * @see #setSelected(boolean)
19014     *
19015     * @param selected The new selected state
19016     */
19017    protected void dispatchSetSelected(boolean selected) {
19018    }
19019
19020    /**
19021     * Indicates the selection state of this view.
19022     *
19023     * @return true if the view is selected, false otherwise
19024     */
19025    @ViewDebug.ExportedProperty
19026    public boolean isSelected() {
19027        return (mPrivateFlags & PFLAG_SELECTED) != 0;
19028    }
19029
19030    /**
19031     * Changes the activated state of this view. A view can be activated or not.
19032     * Note that activation is not the same as selection.  Selection is
19033     * a transient property, representing the view (hierarchy) the user is
19034     * currently interacting with.  Activation is a longer-term state that the
19035     * user can move views in and out of.  For example, in a list view with
19036     * single or multiple selection enabled, the views in the current selection
19037     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
19038     * here.)  The activated state is propagated down to children of the view it
19039     * is set on.
19040     *
19041     * @param activated true if the view must be activated, false otherwise
19042     */
19043    public void setActivated(boolean activated) {
19044        //noinspection DoubleNegation
19045        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
19046            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
19047            invalidate(true);
19048            refreshDrawableState();
19049            dispatchSetActivated(activated);
19050        }
19051    }
19052
19053    /**
19054     * Dispatch setActivated to all of this View's children.
19055     *
19056     * @see #setActivated(boolean)
19057     *
19058     * @param activated The new activated state
19059     */
19060    protected void dispatchSetActivated(boolean activated) {
19061    }
19062
19063    /**
19064     * Indicates the activation state of this view.
19065     *
19066     * @return true if the view is activated, false otherwise
19067     */
19068    @ViewDebug.ExportedProperty
19069    public boolean isActivated() {
19070        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
19071    }
19072
19073    /**
19074     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
19075     * observer can be used to get notifications when global events, like
19076     * layout, happen.
19077     *
19078     * The returned ViewTreeObserver observer is not guaranteed to remain
19079     * valid for the lifetime of this View. If the caller of this method keeps
19080     * a long-lived reference to ViewTreeObserver, it should always check for
19081     * the return value of {@link ViewTreeObserver#isAlive()}.
19082     *
19083     * @return The ViewTreeObserver for this view's hierarchy.
19084     */
19085    public ViewTreeObserver getViewTreeObserver() {
19086        if (mAttachInfo != null) {
19087            return mAttachInfo.mTreeObserver;
19088        }
19089        if (mFloatingTreeObserver == null) {
19090            mFloatingTreeObserver = new ViewTreeObserver();
19091        }
19092        return mFloatingTreeObserver;
19093    }
19094
19095    /**
19096     * <p>Finds the topmost view in the current view hierarchy.</p>
19097     *
19098     * @return the topmost view containing this view
19099     */
19100    public View getRootView() {
19101        if (mAttachInfo != null) {
19102            final View v = mAttachInfo.mRootView;
19103            if (v != null) {
19104                return v;
19105            }
19106        }
19107
19108        View parent = this;
19109
19110        while (parent.mParent != null && parent.mParent instanceof View) {
19111            parent = (View) parent.mParent;
19112        }
19113
19114        return parent;
19115    }
19116
19117    /**
19118     * Transforms a motion event from view-local coordinates to on-screen
19119     * coordinates.
19120     *
19121     * @param ev the view-local motion event
19122     * @return false if the transformation could not be applied
19123     * @hide
19124     */
19125    public boolean toGlobalMotionEvent(MotionEvent ev) {
19126        final AttachInfo info = mAttachInfo;
19127        if (info == null) {
19128            return false;
19129        }
19130
19131        final Matrix m = info.mTmpMatrix;
19132        m.set(Matrix.IDENTITY_MATRIX);
19133        transformMatrixToGlobal(m);
19134        ev.transform(m);
19135        return true;
19136    }
19137
19138    /**
19139     * Transforms a motion event from on-screen coordinates to view-local
19140     * coordinates.
19141     *
19142     * @param ev the on-screen motion event
19143     * @return false if the transformation could not be applied
19144     * @hide
19145     */
19146    public boolean toLocalMotionEvent(MotionEvent ev) {
19147        final AttachInfo info = mAttachInfo;
19148        if (info == null) {
19149            return false;
19150        }
19151
19152        final Matrix m = info.mTmpMatrix;
19153        m.set(Matrix.IDENTITY_MATRIX);
19154        transformMatrixToLocal(m);
19155        ev.transform(m);
19156        return true;
19157    }
19158
19159    /**
19160     * Modifies the input matrix such that it maps view-local coordinates to
19161     * on-screen coordinates.
19162     *
19163     * @param m input matrix to modify
19164     * @hide
19165     */
19166    public void transformMatrixToGlobal(Matrix m) {
19167        final ViewParent parent = mParent;
19168        if (parent instanceof View) {
19169            final View vp = (View) parent;
19170            vp.transformMatrixToGlobal(m);
19171            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
19172        } else if (parent instanceof ViewRootImpl) {
19173            final ViewRootImpl vr = (ViewRootImpl) parent;
19174            vr.transformMatrixToGlobal(m);
19175            m.preTranslate(0, -vr.mCurScrollY);
19176        }
19177
19178        m.preTranslate(mLeft, mTop);
19179
19180        if (!hasIdentityMatrix()) {
19181            m.preConcat(getMatrix());
19182        }
19183    }
19184
19185    /**
19186     * Modifies the input matrix such that it maps on-screen coordinates to
19187     * view-local coordinates.
19188     *
19189     * @param m input matrix to modify
19190     * @hide
19191     */
19192    public void transformMatrixToLocal(Matrix m) {
19193        final ViewParent parent = mParent;
19194        if (parent instanceof View) {
19195            final View vp = (View) parent;
19196            vp.transformMatrixToLocal(m);
19197            m.postTranslate(vp.mScrollX, vp.mScrollY);
19198        } else if (parent instanceof ViewRootImpl) {
19199            final ViewRootImpl vr = (ViewRootImpl) parent;
19200            vr.transformMatrixToLocal(m);
19201            m.postTranslate(0, vr.mCurScrollY);
19202        }
19203
19204        m.postTranslate(-mLeft, -mTop);
19205
19206        if (!hasIdentityMatrix()) {
19207            m.postConcat(getInverseMatrix());
19208        }
19209    }
19210
19211    /**
19212     * @hide
19213     */
19214    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
19215            @ViewDebug.IntToString(from = 0, to = "x"),
19216            @ViewDebug.IntToString(from = 1, to = "y")
19217    })
19218    public int[] getLocationOnScreen() {
19219        int[] location = new int[2];
19220        getLocationOnScreen(location);
19221        return location;
19222    }
19223
19224    /**
19225     * <p>Computes the coordinates of this view on the screen. The argument
19226     * must be an array of two integers. After the method returns, the array
19227     * contains the x and y location in that order.</p>
19228     *
19229     * @param outLocation an array of two integers in which to hold the coordinates
19230     */
19231    public void getLocationOnScreen(@Size(2) int[] outLocation) {
19232        getLocationInWindow(outLocation);
19233
19234        final AttachInfo info = mAttachInfo;
19235        if (info != null) {
19236            outLocation[0] += info.mWindowLeft;
19237            outLocation[1] += info.mWindowTop;
19238        }
19239    }
19240
19241    /**
19242     * <p>Computes the coordinates of this view in its window. The argument
19243     * must be an array of two integers. After the method returns, the array
19244     * contains the x and y location in that order.</p>
19245     *
19246     * @param outLocation an array of two integers in which to hold the coordinates
19247     */
19248    public void getLocationInWindow(@Size(2) int[] outLocation) {
19249        if (outLocation == null || outLocation.length < 2) {
19250            throw new IllegalArgumentException("outLocation must be an array of two integers");
19251        }
19252
19253        outLocation[0] = 0;
19254        outLocation[1] = 0;
19255
19256        transformFromViewToWindowSpace(outLocation);
19257    }
19258
19259    /** @hide */
19260    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
19261        if (inOutLocation == null || inOutLocation.length < 2) {
19262            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
19263        }
19264
19265        if (mAttachInfo == null) {
19266            // When the view is not attached to a window, this method does not make sense
19267            inOutLocation[0] = inOutLocation[1] = 0;
19268            return;
19269        }
19270
19271        float position[] = mAttachInfo.mTmpTransformLocation;
19272        position[0] = inOutLocation[0];
19273        position[1] = inOutLocation[1];
19274
19275        if (!hasIdentityMatrix()) {
19276            getMatrix().mapPoints(position);
19277        }
19278
19279        position[0] += mLeft;
19280        position[1] += mTop;
19281
19282        ViewParent viewParent = mParent;
19283        while (viewParent instanceof View) {
19284            final View view = (View) viewParent;
19285
19286            position[0] -= view.mScrollX;
19287            position[1] -= view.mScrollY;
19288
19289            if (!view.hasIdentityMatrix()) {
19290                view.getMatrix().mapPoints(position);
19291            }
19292
19293            position[0] += view.mLeft;
19294            position[1] += view.mTop;
19295
19296            viewParent = view.mParent;
19297         }
19298
19299        if (viewParent instanceof ViewRootImpl) {
19300            // *cough*
19301            final ViewRootImpl vr = (ViewRootImpl) viewParent;
19302            position[1] -= vr.mCurScrollY;
19303        }
19304
19305        inOutLocation[0] = Math.round(position[0]);
19306        inOutLocation[1] = Math.round(position[1]);
19307    }
19308
19309    /**
19310     * {@hide}
19311     * @param id the id of the view to be found
19312     * @return the view of the specified id, null if cannot be found
19313     */
19314    protected View findViewTraversal(@IdRes int id) {
19315        if (id == mID) {
19316            return this;
19317        }
19318        return null;
19319    }
19320
19321    /**
19322     * {@hide}
19323     * @param tag the tag of the view to be found
19324     * @return the view of specified tag, null if cannot be found
19325     */
19326    protected View findViewWithTagTraversal(Object tag) {
19327        if (tag != null && tag.equals(mTag)) {
19328            return this;
19329        }
19330        return null;
19331    }
19332
19333    /**
19334     * {@hide}
19335     * @param predicate The predicate to evaluate.
19336     * @param childToSkip If not null, ignores this child during the recursive traversal.
19337     * @return The first view that matches the predicate or null.
19338     */
19339    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
19340        if (predicate.apply(this)) {
19341            return this;
19342        }
19343        return null;
19344    }
19345
19346    /**
19347     * Look for a child view with the given id.  If this view has the given
19348     * id, return this view.
19349     *
19350     * @param id The id to search for.
19351     * @return The view that has the given id in the hierarchy or null
19352     */
19353    @Nullable
19354    public final View findViewById(@IdRes int id) {
19355        if (id < 0) {
19356            return null;
19357        }
19358        return findViewTraversal(id);
19359    }
19360
19361    /**
19362     * Finds a view by its unuque and stable accessibility id.
19363     *
19364     * @param accessibilityId The searched accessibility id.
19365     * @return The found view.
19366     */
19367    final View findViewByAccessibilityId(int accessibilityId) {
19368        if (accessibilityId < 0) {
19369            return null;
19370        }
19371        View view = findViewByAccessibilityIdTraversal(accessibilityId);
19372        if (view != null) {
19373            return view.includeForAccessibility() ? view : null;
19374        }
19375        return null;
19376    }
19377
19378    /**
19379     * Performs the traversal to find a view by its unuque and stable accessibility id.
19380     *
19381     * <strong>Note:</strong>This method does not stop at the root namespace
19382     * boundary since the user can touch the screen at an arbitrary location
19383     * potentially crossing the root namespace bounday which will send an
19384     * accessibility event to accessibility services and they should be able
19385     * to obtain the event source. Also accessibility ids are guaranteed to be
19386     * unique in the window.
19387     *
19388     * @param accessibilityId The accessibility id.
19389     * @return The found view.
19390     *
19391     * @hide
19392     */
19393    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
19394        if (getAccessibilityViewId() == accessibilityId) {
19395            return this;
19396        }
19397        return null;
19398    }
19399
19400    /**
19401     * Look for a child view with the given tag.  If this view has the given
19402     * tag, return this view.
19403     *
19404     * @param tag The tag to search for, using "tag.equals(getTag())".
19405     * @return The View that has the given tag in the hierarchy or null
19406     */
19407    public final View findViewWithTag(Object tag) {
19408        if (tag == null) {
19409            return null;
19410        }
19411        return findViewWithTagTraversal(tag);
19412    }
19413
19414    /**
19415     * {@hide}
19416     * Look for a child view that matches the specified predicate.
19417     * If this view matches the predicate, return this view.
19418     *
19419     * @param predicate The predicate to evaluate.
19420     * @return The first view that matches the predicate or null.
19421     */
19422    public final View findViewByPredicate(Predicate<View> predicate) {
19423        return findViewByPredicateTraversal(predicate, null);
19424    }
19425
19426    /**
19427     * {@hide}
19428     * Look for a child view that matches the specified predicate,
19429     * starting with the specified view and its descendents and then
19430     * recusively searching the ancestors and siblings of that view
19431     * until this view is reached.
19432     *
19433     * This method is useful in cases where the predicate does not match
19434     * a single unique view (perhaps multiple views use the same id)
19435     * and we are trying to find the view that is "closest" in scope to the
19436     * starting view.
19437     *
19438     * @param start The view to start from.
19439     * @param predicate The predicate to evaluate.
19440     * @return The first view that matches the predicate or null.
19441     */
19442    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
19443        View childToSkip = null;
19444        for (;;) {
19445            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
19446            if (view != null || start == this) {
19447                return view;
19448            }
19449
19450            ViewParent parent = start.getParent();
19451            if (parent == null || !(parent instanceof View)) {
19452                return null;
19453            }
19454
19455            childToSkip = start;
19456            start = (View) parent;
19457        }
19458    }
19459
19460    /**
19461     * Sets the identifier for this view. The identifier does not have to be
19462     * unique in this view's hierarchy. The identifier should be a positive
19463     * number.
19464     *
19465     * @see #NO_ID
19466     * @see #getId()
19467     * @see #findViewById(int)
19468     *
19469     * @param id a number used to identify the view
19470     *
19471     * @attr ref android.R.styleable#View_id
19472     */
19473    public void setId(@IdRes int id) {
19474        mID = id;
19475        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
19476            mID = generateViewId();
19477        }
19478    }
19479
19480    /**
19481     * {@hide}
19482     *
19483     * @param isRoot true if the view belongs to the root namespace, false
19484     *        otherwise
19485     */
19486    public void setIsRootNamespace(boolean isRoot) {
19487        if (isRoot) {
19488            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
19489        } else {
19490            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
19491        }
19492    }
19493
19494    /**
19495     * {@hide}
19496     *
19497     * @return true if the view belongs to the root namespace, false otherwise
19498     */
19499    public boolean isRootNamespace() {
19500        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
19501    }
19502
19503    /**
19504     * Returns this view's identifier.
19505     *
19506     * @return a positive integer used to identify the view or {@link #NO_ID}
19507     *         if the view has no ID
19508     *
19509     * @see #setId(int)
19510     * @see #findViewById(int)
19511     * @attr ref android.R.styleable#View_id
19512     */
19513    @IdRes
19514    @ViewDebug.CapturedViewProperty
19515    public int getId() {
19516        return mID;
19517    }
19518
19519    /**
19520     * Returns this view's tag.
19521     *
19522     * @return the Object stored in this view as a tag, or {@code null} if not
19523     *         set
19524     *
19525     * @see #setTag(Object)
19526     * @see #getTag(int)
19527     */
19528    @ViewDebug.ExportedProperty
19529    public Object getTag() {
19530        return mTag;
19531    }
19532
19533    /**
19534     * Sets the tag associated with this view. A tag can be used to mark
19535     * a view in its hierarchy and does not have to be unique within the
19536     * hierarchy. Tags can also be used to store data within a view without
19537     * resorting to another data structure.
19538     *
19539     * @param tag an Object to tag the view with
19540     *
19541     * @see #getTag()
19542     * @see #setTag(int, Object)
19543     */
19544    public void setTag(final Object tag) {
19545        mTag = tag;
19546    }
19547
19548    /**
19549     * Returns the tag associated with this view and the specified key.
19550     *
19551     * @param key The key identifying the tag
19552     *
19553     * @return the Object stored in this view as a tag, or {@code null} if not
19554     *         set
19555     *
19556     * @see #setTag(int, Object)
19557     * @see #getTag()
19558     */
19559    public Object getTag(int key) {
19560        if (mKeyedTags != null) return mKeyedTags.get(key);
19561        return null;
19562    }
19563
19564    /**
19565     * Sets a tag associated with this view and a key. A tag can be used
19566     * to mark a view in its hierarchy and does not have to be unique within
19567     * the hierarchy. Tags can also be used to store data within a view
19568     * without resorting to another data structure.
19569     *
19570     * The specified key should be an id declared in the resources of the
19571     * application to ensure it is unique (see the <a
19572     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
19573     * Keys identified as belonging to
19574     * the Android framework or not associated with any package will cause
19575     * an {@link IllegalArgumentException} to be thrown.
19576     *
19577     * @param key The key identifying the tag
19578     * @param tag An Object to tag the view with
19579     *
19580     * @throws IllegalArgumentException If they specified key is not valid
19581     *
19582     * @see #setTag(Object)
19583     * @see #getTag(int)
19584     */
19585    public void setTag(int key, final Object tag) {
19586        // If the package id is 0x00 or 0x01, it's either an undefined package
19587        // or a framework id
19588        if ((key >>> 24) < 2) {
19589            throw new IllegalArgumentException("The key must be an application-specific "
19590                    + "resource id.");
19591        }
19592
19593        setKeyedTag(key, tag);
19594    }
19595
19596    /**
19597     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
19598     * framework id.
19599     *
19600     * @hide
19601     */
19602    public void setTagInternal(int key, Object tag) {
19603        if ((key >>> 24) != 0x1) {
19604            throw new IllegalArgumentException("The key must be a framework-specific "
19605                    + "resource id.");
19606        }
19607
19608        setKeyedTag(key, tag);
19609    }
19610
19611    private void setKeyedTag(int key, Object tag) {
19612        if (mKeyedTags == null) {
19613            mKeyedTags = new SparseArray<Object>(2);
19614        }
19615
19616        mKeyedTags.put(key, tag);
19617    }
19618
19619    /**
19620     * Prints information about this view in the log output, with the tag
19621     * {@link #VIEW_LOG_TAG}.
19622     *
19623     * @hide
19624     */
19625    public void debug() {
19626        debug(0);
19627    }
19628
19629    /**
19630     * Prints information about this view in the log output, with the tag
19631     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
19632     * indentation defined by the <code>depth</code>.
19633     *
19634     * @param depth the indentation level
19635     *
19636     * @hide
19637     */
19638    protected void debug(int depth) {
19639        String output = debugIndent(depth - 1);
19640
19641        output += "+ " + this;
19642        int id = getId();
19643        if (id != -1) {
19644            output += " (id=" + id + ")";
19645        }
19646        Object tag = getTag();
19647        if (tag != null) {
19648            output += " (tag=" + tag + ")";
19649        }
19650        Log.d(VIEW_LOG_TAG, output);
19651
19652        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
19653            output = debugIndent(depth) + " FOCUSED";
19654            Log.d(VIEW_LOG_TAG, output);
19655        }
19656
19657        output = debugIndent(depth);
19658        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
19659                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
19660                + "} ";
19661        Log.d(VIEW_LOG_TAG, output);
19662
19663        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
19664                || mPaddingBottom != 0) {
19665            output = debugIndent(depth);
19666            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
19667                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
19668            Log.d(VIEW_LOG_TAG, output);
19669        }
19670
19671        output = debugIndent(depth);
19672        output += "mMeasureWidth=" + mMeasuredWidth +
19673                " mMeasureHeight=" + mMeasuredHeight;
19674        Log.d(VIEW_LOG_TAG, output);
19675
19676        output = debugIndent(depth);
19677        if (mLayoutParams == null) {
19678            output += "BAD! no layout params";
19679        } else {
19680            output = mLayoutParams.debug(output);
19681        }
19682        Log.d(VIEW_LOG_TAG, output);
19683
19684        output = debugIndent(depth);
19685        output += "flags={";
19686        output += View.printFlags(mViewFlags);
19687        output += "}";
19688        Log.d(VIEW_LOG_TAG, output);
19689
19690        output = debugIndent(depth);
19691        output += "privateFlags={";
19692        output += View.printPrivateFlags(mPrivateFlags);
19693        output += "}";
19694        Log.d(VIEW_LOG_TAG, output);
19695    }
19696
19697    /**
19698     * Creates a string of whitespaces used for indentation.
19699     *
19700     * @param depth the indentation level
19701     * @return a String containing (depth * 2 + 3) * 2 white spaces
19702     *
19703     * @hide
19704     */
19705    protected static String debugIndent(int depth) {
19706        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
19707        for (int i = 0; i < (depth * 2) + 3; i++) {
19708            spaces.append(' ').append(' ');
19709        }
19710        return spaces.toString();
19711    }
19712
19713    /**
19714     * <p>Return the offset of the widget's text baseline from the widget's top
19715     * boundary. If this widget does not support baseline alignment, this
19716     * method returns -1. </p>
19717     *
19718     * @return the offset of the baseline within the widget's bounds or -1
19719     *         if baseline alignment is not supported
19720     */
19721    @ViewDebug.ExportedProperty(category = "layout")
19722    public int getBaseline() {
19723        return -1;
19724    }
19725
19726    /**
19727     * Returns whether the view hierarchy is currently undergoing a layout pass. This
19728     * information is useful to avoid situations such as calling {@link #requestLayout()} during
19729     * a layout pass.
19730     *
19731     * @return whether the view hierarchy is currently undergoing a layout pass
19732     */
19733    public boolean isInLayout() {
19734        ViewRootImpl viewRoot = getViewRootImpl();
19735        return (viewRoot != null && viewRoot.isInLayout());
19736    }
19737
19738    /**
19739     * Call this when something has changed which has invalidated the
19740     * layout of this view. This will schedule a layout pass of the view
19741     * tree. This should not be called while the view hierarchy is currently in a layout
19742     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
19743     * end of the current layout pass (and then layout will run again) or after the current
19744     * frame is drawn and the next layout occurs.
19745     *
19746     * <p>Subclasses which override this method should call the superclass method to
19747     * handle possible request-during-layout errors correctly.</p>
19748     */
19749    @CallSuper
19750    public void requestLayout() {
19751        if (mMeasureCache != null) mMeasureCache.clear();
19752
19753        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
19754            // Only trigger request-during-layout logic if this is the view requesting it,
19755            // not the views in its parent hierarchy
19756            ViewRootImpl viewRoot = getViewRootImpl();
19757            if (viewRoot != null && viewRoot.isInLayout()) {
19758                if (!viewRoot.requestLayoutDuringLayout(this)) {
19759                    return;
19760                }
19761            }
19762            mAttachInfo.mViewRequestingLayout = this;
19763        }
19764
19765        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19766        mPrivateFlags |= PFLAG_INVALIDATED;
19767
19768        if (mParent != null && !mParent.isLayoutRequested()) {
19769            mParent.requestLayout();
19770        }
19771        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
19772            mAttachInfo.mViewRequestingLayout = null;
19773        }
19774    }
19775
19776    /**
19777     * Forces this view to be laid out during the next layout pass.
19778     * This method does not call requestLayout() or forceLayout()
19779     * on the parent.
19780     */
19781    public void forceLayout() {
19782        if (mMeasureCache != null) mMeasureCache.clear();
19783
19784        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19785        mPrivateFlags |= PFLAG_INVALIDATED;
19786    }
19787
19788    /**
19789     * <p>
19790     * This is called to find out how big a view should be. The parent
19791     * supplies constraint information in the width and height parameters.
19792     * </p>
19793     *
19794     * <p>
19795     * The actual measurement work of a view is performed in
19796     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
19797     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
19798     * </p>
19799     *
19800     *
19801     * @param widthMeasureSpec Horizontal space requirements as imposed by the
19802     *        parent
19803     * @param heightMeasureSpec Vertical space requirements as imposed by the
19804     *        parent
19805     *
19806     * @see #onMeasure(int, int)
19807     */
19808    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
19809        boolean optical = isLayoutModeOptical(this);
19810        if (optical != isLayoutModeOptical(mParent)) {
19811            Insets insets = getOpticalInsets();
19812            int oWidth  = insets.left + insets.right;
19813            int oHeight = insets.top  + insets.bottom;
19814            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
19815            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
19816        }
19817
19818        // Suppress sign extension for the low bytes
19819        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
19820        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
19821
19822        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19823
19824        // Optimize layout by avoiding an extra EXACTLY pass when the view is
19825        // already measured as the correct size. In API 23 and below, this
19826        // extra pass is required to make LinearLayout re-distribute weight.
19827        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
19828                || heightMeasureSpec != mOldHeightMeasureSpec;
19829        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
19830                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
19831        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
19832                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
19833        final boolean needsLayout = specChanged
19834                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
19835
19836        if (forceLayout || needsLayout) {
19837            // first clears the measured dimension flag
19838            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
19839
19840            resolveRtlPropertiesIfNeeded();
19841
19842            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
19843            if (cacheIndex < 0 || sIgnoreMeasureCache) {
19844                // measure ourselves, this should set the measured dimension flag back
19845                onMeasure(widthMeasureSpec, heightMeasureSpec);
19846                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19847            } else {
19848                long value = mMeasureCache.valueAt(cacheIndex);
19849                // Casting a long to int drops the high 32 bits, no mask needed
19850                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
19851                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19852            }
19853
19854            // flag not set, setMeasuredDimension() was not invoked, we raise
19855            // an exception to warn the developer
19856            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
19857                throw new IllegalStateException("View with id " + getId() + ": "
19858                        + getClass().getName() + "#onMeasure() did not set the"
19859                        + " measured dimension by calling"
19860                        + " setMeasuredDimension()");
19861            }
19862
19863            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
19864        }
19865
19866        mOldWidthMeasureSpec = widthMeasureSpec;
19867        mOldHeightMeasureSpec = heightMeasureSpec;
19868
19869        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
19870                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
19871    }
19872
19873    /**
19874     * <p>
19875     * Measure the view and its content to determine the measured width and the
19876     * measured height. This method is invoked by {@link #measure(int, int)} and
19877     * should be overridden by subclasses to provide accurate and efficient
19878     * measurement of their contents.
19879     * </p>
19880     *
19881     * <p>
19882     * <strong>CONTRACT:</strong> When overriding this method, you
19883     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
19884     * measured width and height of this view. Failure to do so will trigger an
19885     * <code>IllegalStateException</code>, thrown by
19886     * {@link #measure(int, int)}. Calling the superclass'
19887     * {@link #onMeasure(int, int)} is a valid use.
19888     * </p>
19889     *
19890     * <p>
19891     * The base class implementation of measure defaults to the background size,
19892     * unless a larger size is allowed by the MeasureSpec. Subclasses should
19893     * override {@link #onMeasure(int, int)} to provide better measurements of
19894     * their content.
19895     * </p>
19896     *
19897     * <p>
19898     * If this method is overridden, it is the subclass's responsibility to make
19899     * sure the measured height and width are at least the view's minimum height
19900     * and width ({@link #getSuggestedMinimumHeight()} and
19901     * {@link #getSuggestedMinimumWidth()}).
19902     * </p>
19903     *
19904     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
19905     *                         The requirements are encoded with
19906     *                         {@link android.view.View.MeasureSpec}.
19907     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19908     *                         The requirements are encoded with
19909     *                         {@link android.view.View.MeasureSpec}.
19910     *
19911     * @see #getMeasuredWidth()
19912     * @see #getMeasuredHeight()
19913     * @see #setMeasuredDimension(int, int)
19914     * @see #getSuggestedMinimumHeight()
19915     * @see #getSuggestedMinimumWidth()
19916     * @see android.view.View.MeasureSpec#getMode(int)
19917     * @see android.view.View.MeasureSpec#getSize(int)
19918     */
19919    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19920        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19921                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19922    }
19923
19924    /**
19925     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19926     * measured width and measured height. Failing to do so will trigger an
19927     * exception at measurement time.</p>
19928     *
19929     * @param measuredWidth The measured width of this view.  May be a complex
19930     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19931     * {@link #MEASURED_STATE_TOO_SMALL}.
19932     * @param measuredHeight The measured height of this view.  May be a complex
19933     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19934     * {@link #MEASURED_STATE_TOO_SMALL}.
19935     */
19936    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19937        boolean optical = isLayoutModeOptical(this);
19938        if (optical != isLayoutModeOptical(mParent)) {
19939            Insets insets = getOpticalInsets();
19940            int opticalWidth  = insets.left + insets.right;
19941            int opticalHeight = insets.top  + insets.bottom;
19942
19943            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
19944            measuredHeight += optical ? opticalHeight : -opticalHeight;
19945        }
19946        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19947    }
19948
19949    /**
19950     * Sets the measured dimension without extra processing for things like optical bounds.
19951     * Useful for reapplying consistent values that have already been cooked with adjustments
19952     * for optical bounds, etc. such as those from the measurement cache.
19953     *
19954     * @param measuredWidth The measured width of this view.  May be a complex
19955     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19956     * {@link #MEASURED_STATE_TOO_SMALL}.
19957     * @param measuredHeight The measured height of this view.  May be a complex
19958     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19959     * {@link #MEASURED_STATE_TOO_SMALL}.
19960     */
19961    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19962        mMeasuredWidth = measuredWidth;
19963        mMeasuredHeight = measuredHeight;
19964
19965        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19966    }
19967
19968    /**
19969     * Merge two states as returned by {@link #getMeasuredState()}.
19970     * @param curState The current state as returned from a view or the result
19971     * of combining multiple views.
19972     * @param newState The new view state to combine.
19973     * @return Returns a new integer reflecting the combination of the two
19974     * states.
19975     */
19976    public static int combineMeasuredStates(int curState, int newState) {
19977        return curState | newState;
19978    }
19979
19980    /**
19981     * Version of {@link #resolveSizeAndState(int, int, int)}
19982     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
19983     */
19984    public static int resolveSize(int size, int measureSpec) {
19985        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
19986    }
19987
19988    /**
19989     * Utility to reconcile a desired size and state, with constraints imposed
19990     * by a MeasureSpec. Will take the desired size, unless a different size
19991     * is imposed by the constraints. The returned value is a compound integer,
19992     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
19993     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
19994     * resulting size is smaller than the size the view wants to be.
19995     *
19996     * @param size How big the view wants to be.
19997     * @param measureSpec Constraints imposed by the parent.
19998     * @param childMeasuredState Size information bit mask for the view's
19999     *                           children.
20000     * @return Size information bit mask as defined by
20001     *         {@link #MEASURED_SIZE_MASK} and
20002     *         {@link #MEASURED_STATE_TOO_SMALL}.
20003     */
20004    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
20005        final int specMode = MeasureSpec.getMode(measureSpec);
20006        final int specSize = MeasureSpec.getSize(measureSpec);
20007        final int result;
20008        switch (specMode) {
20009            case MeasureSpec.AT_MOST:
20010                if (specSize < size) {
20011                    result = specSize | MEASURED_STATE_TOO_SMALL;
20012                } else {
20013                    result = size;
20014                }
20015                break;
20016            case MeasureSpec.EXACTLY:
20017                result = specSize;
20018                break;
20019            case MeasureSpec.UNSPECIFIED:
20020            default:
20021                result = size;
20022        }
20023        return result | (childMeasuredState & MEASURED_STATE_MASK);
20024    }
20025
20026    /**
20027     * Utility to return a default size. Uses the supplied size if the
20028     * MeasureSpec imposed no constraints. Will get larger if allowed
20029     * by the MeasureSpec.
20030     *
20031     * @param size Default size for this view
20032     * @param measureSpec Constraints imposed by the parent
20033     * @return The size this view should be.
20034     */
20035    public static int getDefaultSize(int size, int measureSpec) {
20036        int result = size;
20037        int specMode = MeasureSpec.getMode(measureSpec);
20038        int specSize = MeasureSpec.getSize(measureSpec);
20039
20040        switch (specMode) {
20041        case MeasureSpec.UNSPECIFIED:
20042            result = size;
20043            break;
20044        case MeasureSpec.AT_MOST:
20045        case MeasureSpec.EXACTLY:
20046            result = specSize;
20047            break;
20048        }
20049        return result;
20050    }
20051
20052    /**
20053     * Returns the suggested minimum height that the view should use. This
20054     * returns the maximum of the view's minimum height
20055     * and the background's minimum height
20056     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
20057     * <p>
20058     * When being used in {@link #onMeasure(int, int)}, the caller should still
20059     * ensure the returned height is within the requirements of the parent.
20060     *
20061     * @return The suggested minimum height of the view.
20062     */
20063    protected int getSuggestedMinimumHeight() {
20064        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
20065
20066    }
20067
20068    /**
20069     * Returns the suggested minimum width that the view should use. This
20070     * returns the maximum of the view's minimum width
20071     * and the background's minimum width
20072     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
20073     * <p>
20074     * When being used in {@link #onMeasure(int, int)}, the caller should still
20075     * ensure the returned width is within the requirements of the parent.
20076     *
20077     * @return The suggested minimum width of the view.
20078     */
20079    protected int getSuggestedMinimumWidth() {
20080        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
20081    }
20082
20083    /**
20084     * Returns the minimum height of the view.
20085     *
20086     * @return the minimum height the view will try to be.
20087     *
20088     * @see #setMinimumHeight(int)
20089     *
20090     * @attr ref android.R.styleable#View_minHeight
20091     */
20092    public int getMinimumHeight() {
20093        return mMinHeight;
20094    }
20095
20096    /**
20097     * Sets the minimum height of the view. It is not guaranteed the view will
20098     * be able to achieve this minimum height (for example, if its parent layout
20099     * constrains it with less available height).
20100     *
20101     * @param minHeight The minimum height the view will try to be.
20102     *
20103     * @see #getMinimumHeight()
20104     *
20105     * @attr ref android.R.styleable#View_minHeight
20106     */
20107    @RemotableViewMethod
20108    public void setMinimumHeight(int minHeight) {
20109        mMinHeight = minHeight;
20110        requestLayout();
20111    }
20112
20113    /**
20114     * Returns the minimum width of the view.
20115     *
20116     * @return the minimum width the view will try to be.
20117     *
20118     * @see #setMinimumWidth(int)
20119     *
20120     * @attr ref android.R.styleable#View_minWidth
20121     */
20122    public int getMinimumWidth() {
20123        return mMinWidth;
20124    }
20125
20126    /**
20127     * Sets the minimum width of the view. It is not guaranteed the view will
20128     * be able to achieve this minimum width (for example, if its parent layout
20129     * constrains it with less available width).
20130     *
20131     * @param minWidth The minimum width the view will try to be.
20132     *
20133     * @see #getMinimumWidth()
20134     *
20135     * @attr ref android.R.styleable#View_minWidth
20136     */
20137    public void setMinimumWidth(int minWidth) {
20138        mMinWidth = minWidth;
20139        requestLayout();
20140
20141    }
20142
20143    /**
20144     * Get the animation currently associated with this view.
20145     *
20146     * @return The animation that is currently playing or
20147     *         scheduled to play for this view.
20148     */
20149    public Animation getAnimation() {
20150        return mCurrentAnimation;
20151    }
20152
20153    /**
20154     * Start the specified animation now.
20155     *
20156     * @param animation the animation to start now
20157     */
20158    public void startAnimation(Animation animation) {
20159        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
20160        setAnimation(animation);
20161        invalidateParentCaches();
20162        invalidate(true);
20163    }
20164
20165    /**
20166     * Cancels any animations for this view.
20167     */
20168    public void clearAnimation() {
20169        if (mCurrentAnimation != null) {
20170            mCurrentAnimation.detach();
20171        }
20172        mCurrentAnimation = null;
20173        invalidateParentIfNeeded();
20174    }
20175
20176    /**
20177     * Sets the next animation to play for this view.
20178     * If you want the animation to play immediately, use
20179     * {@link #startAnimation(android.view.animation.Animation)} instead.
20180     * This method provides allows fine-grained
20181     * control over the start time and invalidation, but you
20182     * must make sure that 1) the animation has a start time set, and
20183     * 2) the view's parent (which controls animations on its children)
20184     * will be invalidated when the animation is supposed to
20185     * start.
20186     *
20187     * @param animation The next animation, or null.
20188     */
20189    public void setAnimation(Animation animation) {
20190        mCurrentAnimation = animation;
20191
20192        if (animation != null) {
20193            // If the screen is off assume the animation start time is now instead of
20194            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
20195            // would cause the animation to start when the screen turns back on
20196            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
20197                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
20198                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
20199            }
20200            animation.reset();
20201        }
20202    }
20203
20204    /**
20205     * Invoked by a parent ViewGroup to notify the start of the animation
20206     * currently associated with this view. If you override this method,
20207     * always call super.onAnimationStart();
20208     *
20209     * @see #setAnimation(android.view.animation.Animation)
20210     * @see #getAnimation()
20211     */
20212    @CallSuper
20213    protected void onAnimationStart() {
20214        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
20215    }
20216
20217    /**
20218     * Invoked by a parent ViewGroup to notify the end of the animation
20219     * currently associated with this view. If you override this method,
20220     * always call super.onAnimationEnd();
20221     *
20222     * @see #setAnimation(android.view.animation.Animation)
20223     * @see #getAnimation()
20224     */
20225    @CallSuper
20226    protected void onAnimationEnd() {
20227        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
20228    }
20229
20230    /**
20231     * Invoked if there is a Transform that involves alpha. Subclass that can
20232     * draw themselves with the specified alpha should return true, and then
20233     * respect that alpha when their onDraw() is called. If this returns false
20234     * then the view may be redirected to draw into an offscreen buffer to
20235     * fulfill the request, which will look fine, but may be slower than if the
20236     * subclass handles it internally. The default implementation returns false.
20237     *
20238     * @param alpha The alpha (0..255) to apply to the view's drawing
20239     * @return true if the view can draw with the specified alpha.
20240     */
20241    protected boolean onSetAlpha(int alpha) {
20242        return false;
20243    }
20244
20245    /**
20246     * This is used by the RootView to perform an optimization when
20247     * the view hierarchy contains one or several SurfaceView.
20248     * SurfaceView is always considered transparent, but its children are not,
20249     * therefore all View objects remove themselves from the global transparent
20250     * region (passed as a parameter to this function).
20251     *
20252     * @param region The transparent region for this ViewAncestor (window).
20253     *
20254     * @return Returns true if the effective visibility of the view at this
20255     * point is opaque, regardless of the transparent region; returns false
20256     * if it is possible for underlying windows to be seen behind the view.
20257     *
20258     * {@hide}
20259     */
20260    public boolean gatherTransparentRegion(Region region) {
20261        final AttachInfo attachInfo = mAttachInfo;
20262        if (region != null && attachInfo != null) {
20263            final int pflags = mPrivateFlags;
20264            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
20265                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
20266                // remove it from the transparent region.
20267                final int[] location = attachInfo.mTransparentLocation;
20268                getLocationInWindow(location);
20269                region.op(location[0], location[1], location[0] + mRight - mLeft,
20270                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
20271            } else {
20272                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
20273                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
20274                    // the background drawable's non-transparent parts from this transparent region.
20275                    applyDrawableToTransparentRegion(mBackground, region);
20276                }
20277                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20278                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
20279                    // Similarly, we remove the foreground drawable's non-transparent parts.
20280                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
20281                }
20282            }
20283        }
20284        return true;
20285    }
20286
20287    /**
20288     * Play a sound effect for this view.
20289     *
20290     * <p>The framework will play sound effects for some built in actions, such as
20291     * clicking, but you may wish to play these effects in your widget,
20292     * for instance, for internal navigation.
20293     *
20294     * <p>The sound effect will only be played if sound effects are enabled by the user, and
20295     * {@link #isSoundEffectsEnabled()} is true.
20296     *
20297     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
20298     */
20299    public void playSoundEffect(int soundConstant) {
20300        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
20301            return;
20302        }
20303        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
20304    }
20305
20306    /**
20307     * BZZZTT!!1!
20308     *
20309     * <p>Provide haptic feedback to the user for this view.
20310     *
20311     * <p>The framework will provide haptic feedback for some built in actions,
20312     * such as long presses, but you may wish to provide feedback for your
20313     * own widget.
20314     *
20315     * <p>The feedback will only be performed if
20316     * {@link #isHapticFeedbackEnabled()} is true.
20317     *
20318     * @param feedbackConstant One of the constants defined in
20319     * {@link HapticFeedbackConstants}
20320     */
20321    public boolean performHapticFeedback(int feedbackConstant) {
20322        return performHapticFeedback(feedbackConstant, 0);
20323    }
20324
20325    /**
20326     * BZZZTT!!1!
20327     *
20328     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
20329     *
20330     * @param feedbackConstant One of the constants defined in
20331     * {@link HapticFeedbackConstants}
20332     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
20333     */
20334    public boolean performHapticFeedback(int feedbackConstant, int flags) {
20335        if (mAttachInfo == null) {
20336            return false;
20337        }
20338        //noinspection SimplifiableIfStatement
20339        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
20340                && !isHapticFeedbackEnabled()) {
20341            return false;
20342        }
20343        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
20344                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
20345    }
20346
20347    /**
20348     * Request that the visibility of the status bar or other screen/window
20349     * decorations be changed.
20350     *
20351     * <p>This method is used to put the over device UI into temporary modes
20352     * where the user's attention is focused more on the application content,
20353     * by dimming or hiding surrounding system affordances.  This is typically
20354     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
20355     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
20356     * to be placed behind the action bar (and with these flags other system
20357     * affordances) so that smooth transitions between hiding and showing them
20358     * can be done.
20359     *
20360     * <p>Two representative examples of the use of system UI visibility is
20361     * implementing a content browsing application (like a magazine reader)
20362     * and a video playing application.
20363     *
20364     * <p>The first code shows a typical implementation of a View in a content
20365     * browsing application.  In this implementation, the application goes
20366     * into a content-oriented mode by hiding the status bar and action bar,
20367     * and putting the navigation elements into lights out mode.  The user can
20368     * then interact with content while in this mode.  Such an application should
20369     * provide an easy way for the user to toggle out of the mode (such as to
20370     * check information in the status bar or access notifications).  In the
20371     * implementation here, this is done simply by tapping on the content.
20372     *
20373     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
20374     *      content}
20375     *
20376     * <p>This second code sample shows a typical implementation of a View
20377     * in a video playing application.  In this situation, while the video is
20378     * playing the application would like to go into a complete full-screen mode,
20379     * to use as much of the display as possible for the video.  When in this state
20380     * the user can not interact with the application; the system intercepts
20381     * touching on the screen to pop the UI out of full screen mode.  See
20382     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
20383     *
20384     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
20385     *      content}
20386     *
20387     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20388     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20389     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20390     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20391     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20392     */
20393    public void setSystemUiVisibility(int visibility) {
20394        if (visibility != mSystemUiVisibility) {
20395            mSystemUiVisibility = visibility;
20396            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20397                mParent.recomputeViewAttributes(this);
20398            }
20399        }
20400    }
20401
20402    /**
20403     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
20404     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20405     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20406     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20407     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20408     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20409     */
20410    public int getSystemUiVisibility() {
20411        return mSystemUiVisibility;
20412    }
20413
20414    /**
20415     * Returns the current system UI visibility that is currently set for
20416     * the entire window.  This is the combination of the
20417     * {@link #setSystemUiVisibility(int)} values supplied by all of the
20418     * views in the window.
20419     */
20420    public int getWindowSystemUiVisibility() {
20421        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
20422    }
20423
20424    /**
20425     * Override to find out when the window's requested system UI visibility
20426     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
20427     * This is different from the callbacks received through
20428     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
20429     * in that this is only telling you about the local request of the window,
20430     * not the actual values applied by the system.
20431     */
20432    public void onWindowSystemUiVisibilityChanged(int visible) {
20433    }
20434
20435    /**
20436     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
20437     * the view hierarchy.
20438     */
20439    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
20440        onWindowSystemUiVisibilityChanged(visible);
20441    }
20442
20443    /**
20444     * Set a listener to receive callbacks when the visibility of the system bar changes.
20445     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
20446     */
20447    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
20448        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
20449        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20450            mParent.recomputeViewAttributes(this);
20451        }
20452    }
20453
20454    /**
20455     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
20456     * the view hierarchy.
20457     */
20458    public void dispatchSystemUiVisibilityChanged(int visibility) {
20459        ListenerInfo li = mListenerInfo;
20460        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
20461            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
20462                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
20463        }
20464    }
20465
20466    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
20467        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
20468        if (val != mSystemUiVisibility) {
20469            setSystemUiVisibility(val);
20470            return true;
20471        }
20472        return false;
20473    }
20474
20475    /** @hide */
20476    public void setDisabledSystemUiVisibility(int flags) {
20477        if (mAttachInfo != null) {
20478            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
20479                mAttachInfo.mDisabledSystemUiVisibility = flags;
20480                if (mParent != null) {
20481                    mParent.recomputeViewAttributes(this);
20482                }
20483            }
20484        }
20485    }
20486
20487    /**
20488     * Creates an image that the system displays during the drag and drop
20489     * operation. This is called a &quot;drag shadow&quot;. The default implementation
20490     * for a DragShadowBuilder based on a View returns an image that has exactly the same
20491     * appearance as the given View. The default also positions the center of the drag shadow
20492     * directly under the touch point. If no View is provided (the constructor with no parameters
20493     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
20494     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
20495     * default is an invisible drag shadow.
20496     * <p>
20497     * You are not required to use the View you provide to the constructor as the basis of the
20498     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
20499     * anything you want as the drag shadow.
20500     * </p>
20501     * <p>
20502     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
20503     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
20504     *  size and position of the drag shadow. It uses this data to construct a
20505     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
20506     *  so that your application can draw the shadow image in the Canvas.
20507     * </p>
20508     *
20509     * <div class="special reference">
20510     * <h3>Developer Guides</h3>
20511     * <p>For a guide to implementing drag and drop features, read the
20512     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20513     * </div>
20514     */
20515    public static class DragShadowBuilder {
20516        private final WeakReference<View> mView;
20517
20518        /**
20519         * Constructs a shadow image builder based on a View. By default, the resulting drag
20520         * shadow will have the same appearance and dimensions as the View, with the touch point
20521         * over the center of the View.
20522         * @param view A View. Any View in scope can be used.
20523         */
20524        public DragShadowBuilder(View view) {
20525            mView = new WeakReference<View>(view);
20526        }
20527
20528        /**
20529         * Construct a shadow builder object with no associated View.  This
20530         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
20531         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
20532         * to supply the drag shadow's dimensions and appearance without
20533         * reference to any View object. If they are not overridden, then the result is an
20534         * invisible drag shadow.
20535         */
20536        public DragShadowBuilder() {
20537            mView = new WeakReference<View>(null);
20538        }
20539
20540        /**
20541         * Returns the View object that had been passed to the
20542         * {@link #View.DragShadowBuilder(View)}
20543         * constructor.  If that View parameter was {@code null} or if the
20544         * {@link #View.DragShadowBuilder()}
20545         * constructor was used to instantiate the builder object, this method will return
20546         * null.
20547         *
20548         * @return The View object associate with this builder object.
20549         */
20550        @SuppressWarnings({"JavadocReference"})
20551        final public View getView() {
20552            return mView.get();
20553        }
20554
20555        /**
20556         * Provides the metrics for the shadow image. These include the dimensions of
20557         * the shadow image, and the point within that shadow that should
20558         * be centered under the touch location while dragging.
20559         * <p>
20560         * The default implementation sets the dimensions of the shadow to be the
20561         * same as the dimensions of the View itself and centers the shadow under
20562         * the touch point.
20563         * </p>
20564         *
20565         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
20566         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
20567         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
20568         * image.
20569         *
20570         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
20571         * shadow image that should be underneath the touch point during the drag and drop
20572         * operation. Your application must set {@link android.graphics.Point#x} to the
20573         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
20574         */
20575        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
20576            final View view = mView.get();
20577            if (view != null) {
20578                outShadowSize.set(view.getWidth(), view.getHeight());
20579                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
20580            } else {
20581                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
20582            }
20583        }
20584
20585        /**
20586         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
20587         * based on the dimensions it received from the
20588         * {@link #onProvideShadowMetrics(Point, Point)} callback.
20589         *
20590         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
20591         */
20592        public void onDrawShadow(Canvas canvas) {
20593            final View view = mView.get();
20594            if (view != null) {
20595                view.draw(canvas);
20596            } else {
20597                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
20598            }
20599        }
20600    }
20601
20602    /**
20603     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
20604     * startDragAndDrop()} for newer platform versions.
20605     */
20606    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
20607                                   Object myLocalState, int flags) {
20608        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
20609    }
20610
20611    /**
20612     * Starts a drag and drop operation. When your application calls this method, it passes a
20613     * {@link android.view.View.DragShadowBuilder} object to the system. The
20614     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
20615     * to get metrics for the drag shadow, and then calls the object's
20616     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
20617     * <p>
20618     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
20619     *  drag events to all the View objects in your application that are currently visible. It does
20620     *  this either by calling the View object's drag listener (an implementation of
20621     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
20622     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
20623     *  Both are passed a {@link android.view.DragEvent} object that has a
20624     *  {@link android.view.DragEvent#getAction()} value of
20625     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
20626     * </p>
20627     * <p>
20628     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
20629     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
20630     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
20631     * to the View the user selected for dragging.
20632     * </p>
20633     * @param data A {@link android.content.ClipData} object pointing to the data to be
20634     * transferred by the drag and drop operation.
20635     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20636     * drag shadow.
20637     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
20638     * drop operation. This Object is put into every DragEvent object sent by the system during the
20639     * current drag.
20640     * <p>
20641     * myLocalState is a lightweight mechanism for the sending information from the dragged View
20642     * to the target Views. For example, it can contain flags that differentiate between a
20643     * a copy operation and a move operation.
20644     * </p>
20645     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
20646     * flags, or any combination of the following:
20647     *     <ul>
20648     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
20649     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
20650     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
20651     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
20652     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
20653     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
20654     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
20655     *     </ul>
20656     * @return {@code true} if the method completes successfully, or
20657     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
20658     * do a drag, and so no drag operation is in progress.
20659     */
20660    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
20661            Object myLocalState, int flags) {
20662        if (ViewDebug.DEBUG_DRAG) {
20663            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
20664        }
20665        if (mAttachInfo == null) {
20666            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
20667            return false;
20668        }
20669        boolean okay = false;
20670
20671        Point shadowSize = new Point();
20672        Point shadowTouchPoint = new Point();
20673        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
20674
20675        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
20676                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
20677            throw new IllegalStateException("Drag shadow dimensions must not be negative");
20678        }
20679
20680        if (ViewDebug.DEBUG_DRAG) {
20681            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
20682                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
20683        }
20684        if (mAttachInfo.mDragSurface != null) {
20685            mAttachInfo.mDragSurface.release();
20686        }
20687        mAttachInfo.mDragSurface = new Surface();
20688        try {
20689            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
20690                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
20691            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
20692                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
20693            if (mAttachInfo.mDragToken != null) {
20694                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20695                try {
20696                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20697                    shadowBuilder.onDrawShadow(canvas);
20698                } finally {
20699                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20700                }
20701
20702                final ViewRootImpl root = getViewRootImpl();
20703
20704                // Cache the local state object for delivery with DragEvents
20705                root.setLocalDragState(myLocalState);
20706
20707                // repurpose 'shadowSize' for the last touch point
20708                root.getLastTouchPoint(shadowSize);
20709
20710                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
20711                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
20712                        shadowTouchPoint.x, shadowTouchPoint.y, data);
20713                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
20714            }
20715        } catch (Exception e) {
20716            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
20717            mAttachInfo.mDragSurface.destroy();
20718            mAttachInfo.mDragSurface = null;
20719        }
20720
20721        return okay;
20722    }
20723
20724    /**
20725     * Cancels an ongoing drag and drop operation.
20726     * <p>
20727     * A {@link android.view.DragEvent} object with
20728     * {@link android.view.DragEvent#getAction()} value of
20729     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
20730     * {@link android.view.DragEvent#getResult()} value of {@code false}
20731     * will be sent to every
20732     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
20733     * even if they are not currently visible.
20734     * </p>
20735     * <p>
20736     * This method can be called on any View in the same window as the View on which
20737     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
20738     * was called.
20739     * </p>
20740     */
20741    public final void cancelDragAndDrop() {
20742        if (ViewDebug.DEBUG_DRAG) {
20743            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
20744        }
20745        if (mAttachInfo == null) {
20746            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
20747            return;
20748        }
20749        if (mAttachInfo.mDragToken != null) {
20750            try {
20751                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
20752            } catch (Exception e) {
20753                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
20754            }
20755            mAttachInfo.mDragToken = null;
20756        } else {
20757            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
20758        }
20759    }
20760
20761    /**
20762     * Updates the drag shadow for the ongoing drag and drop operation.
20763     *
20764     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
20765     * new drag shadow.
20766     */
20767    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
20768        if (ViewDebug.DEBUG_DRAG) {
20769            Log.d(VIEW_LOG_TAG, "updateDragShadow");
20770        }
20771        if (mAttachInfo == null) {
20772            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
20773            return;
20774        }
20775        if (mAttachInfo.mDragToken != null) {
20776            try {
20777                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
20778                try {
20779                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
20780                    shadowBuilder.onDrawShadow(canvas);
20781                } finally {
20782                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
20783                }
20784            } catch (Exception e) {
20785                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
20786            }
20787        } else {
20788            Log.e(VIEW_LOG_TAG, "No active drag");
20789        }
20790    }
20791
20792    /**
20793     * Starts a move from {startX, startY}, the amount of the movement will be the offset
20794     * between {startX, startY} and the new cursor positon.
20795     * @param startX horizontal coordinate where the move started.
20796     * @param startY vertical coordinate where the move started.
20797     * @return whether moving was started successfully.
20798     * @hide
20799     */
20800    public final boolean startMovingTask(float startX, float startY) {
20801        if (ViewDebug.DEBUG_POSITIONING) {
20802            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
20803        }
20804        try {
20805            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
20806        } catch (RemoteException e) {
20807            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
20808        }
20809        return false;
20810    }
20811
20812    /**
20813     * Handles drag events sent by the system following a call to
20814     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
20815     * startDragAndDrop()}.
20816     *<p>
20817     * When the system calls this method, it passes a
20818     * {@link android.view.DragEvent} object. A call to
20819     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
20820     * in DragEvent. The method uses these to determine what is happening in the drag and drop
20821     * operation.
20822     * @param event The {@link android.view.DragEvent} sent by the system.
20823     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
20824     * in DragEvent, indicating the type of drag event represented by this object.
20825     * @return {@code true} if the method was successful, otherwise {@code false}.
20826     * <p>
20827     *  The method should return {@code true} in response to an action type of
20828     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
20829     *  operation.
20830     * </p>
20831     * <p>
20832     *  The method should also return {@code true} in response to an action type of
20833     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
20834     *  {@code false} if it didn't.
20835     * </p>
20836     */
20837    public boolean onDragEvent(DragEvent event) {
20838        return false;
20839    }
20840
20841    /**
20842     * Detects if this View is enabled and has a drag event listener.
20843     * If both are true, then it calls the drag event listener with the
20844     * {@link android.view.DragEvent} it received. If the drag event listener returns
20845     * {@code true}, then dispatchDragEvent() returns {@code true}.
20846     * <p>
20847     * For all other cases, the method calls the
20848     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
20849     * method and returns its result.
20850     * </p>
20851     * <p>
20852     * This ensures that a drag event is always consumed, even if the View does not have a drag
20853     * event listener. However, if the View has a listener and the listener returns true, then
20854     * onDragEvent() is not called.
20855     * </p>
20856     */
20857    public boolean dispatchDragEvent(DragEvent event) {
20858        ListenerInfo li = mListenerInfo;
20859        //noinspection SimplifiableIfStatement
20860        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
20861                && li.mOnDragListener.onDrag(this, event)) {
20862            return true;
20863        }
20864        return onDragEvent(event);
20865    }
20866
20867    boolean canAcceptDrag() {
20868        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
20869    }
20870
20871    /**
20872     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
20873     * it is ever exposed at all.
20874     * @hide
20875     */
20876    public void onCloseSystemDialogs(String reason) {
20877    }
20878
20879    /**
20880     * Given a Drawable whose bounds have been set to draw into this view,
20881     * update a Region being computed for
20882     * {@link #gatherTransparentRegion(android.graphics.Region)} so
20883     * that any non-transparent parts of the Drawable are removed from the
20884     * given transparent region.
20885     *
20886     * @param dr The Drawable whose transparency is to be applied to the region.
20887     * @param region A Region holding the current transparency information,
20888     * where any parts of the region that are set are considered to be
20889     * transparent.  On return, this region will be modified to have the
20890     * transparency information reduced by the corresponding parts of the
20891     * Drawable that are not transparent.
20892     * {@hide}
20893     */
20894    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
20895        if (DBG) {
20896            Log.i("View", "Getting transparent region for: " + this);
20897        }
20898        final Region r = dr.getTransparentRegion();
20899        final Rect db = dr.getBounds();
20900        final AttachInfo attachInfo = mAttachInfo;
20901        if (r != null && attachInfo != null) {
20902            final int w = getRight()-getLeft();
20903            final int h = getBottom()-getTop();
20904            if (db.left > 0) {
20905                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
20906                r.op(0, 0, db.left, h, Region.Op.UNION);
20907            }
20908            if (db.right < w) {
20909                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
20910                r.op(db.right, 0, w, h, Region.Op.UNION);
20911            }
20912            if (db.top > 0) {
20913                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
20914                r.op(0, 0, w, db.top, Region.Op.UNION);
20915            }
20916            if (db.bottom < h) {
20917                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
20918                r.op(0, db.bottom, w, h, Region.Op.UNION);
20919            }
20920            final int[] location = attachInfo.mTransparentLocation;
20921            getLocationInWindow(location);
20922            r.translate(location[0], location[1]);
20923            region.op(r, Region.Op.INTERSECT);
20924        } else {
20925            region.op(db, Region.Op.DIFFERENCE);
20926        }
20927    }
20928
20929    private void checkForLongClick(int delayOffset, float x, float y) {
20930        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
20931            mHasPerformedLongPress = false;
20932
20933            if (mPendingCheckForLongPress == null) {
20934                mPendingCheckForLongPress = new CheckForLongPress();
20935            }
20936            mPendingCheckForLongPress.setAnchor(x, y);
20937            mPendingCheckForLongPress.rememberWindowAttachCount();
20938            postDelayed(mPendingCheckForLongPress,
20939                    ViewConfiguration.getLongPressTimeout() - delayOffset);
20940        }
20941    }
20942
20943    /**
20944     * Inflate a view from an XML resource.  This convenience method wraps the {@link
20945     * LayoutInflater} class, which provides a full range of options for view inflation.
20946     *
20947     * @param context The Context object for your activity or application.
20948     * @param resource The resource ID to inflate
20949     * @param root A view group that will be the parent.  Used to properly inflate the
20950     * layout_* parameters.
20951     * @see LayoutInflater
20952     */
20953    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
20954        LayoutInflater factory = LayoutInflater.from(context);
20955        return factory.inflate(resource, root);
20956    }
20957
20958    /**
20959     * Scroll the view with standard behavior for scrolling beyond the normal
20960     * content boundaries. Views that call this method should override
20961     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
20962     * results of an over-scroll operation.
20963     *
20964     * Views can use this method to handle any touch or fling-based scrolling.
20965     *
20966     * @param deltaX Change in X in pixels
20967     * @param deltaY Change in Y in pixels
20968     * @param scrollX Current X scroll value in pixels before applying deltaX
20969     * @param scrollY Current Y scroll value in pixels before applying deltaY
20970     * @param scrollRangeX Maximum content scroll range along the X axis
20971     * @param scrollRangeY Maximum content scroll range along the Y axis
20972     * @param maxOverScrollX Number of pixels to overscroll by in either direction
20973     *          along the X axis.
20974     * @param maxOverScrollY Number of pixels to overscroll by in either direction
20975     *          along the Y axis.
20976     * @param isTouchEvent true if this scroll operation is the result of a touch event.
20977     * @return true if scrolling was clamped to an over-scroll boundary along either
20978     *          axis, false otherwise.
20979     */
20980    @SuppressWarnings({"UnusedParameters"})
20981    protected boolean overScrollBy(int deltaX, int deltaY,
20982            int scrollX, int scrollY,
20983            int scrollRangeX, int scrollRangeY,
20984            int maxOverScrollX, int maxOverScrollY,
20985            boolean isTouchEvent) {
20986        final int overScrollMode = mOverScrollMode;
20987        final boolean canScrollHorizontal =
20988                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
20989        final boolean canScrollVertical =
20990                computeVerticalScrollRange() > computeVerticalScrollExtent();
20991        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
20992                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
20993        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
20994                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
20995
20996        int newScrollX = scrollX + deltaX;
20997        if (!overScrollHorizontal) {
20998            maxOverScrollX = 0;
20999        }
21000
21001        int newScrollY = scrollY + deltaY;
21002        if (!overScrollVertical) {
21003            maxOverScrollY = 0;
21004        }
21005
21006        // Clamp values if at the limits and record
21007        final int left = -maxOverScrollX;
21008        final int right = maxOverScrollX + scrollRangeX;
21009        final int top = -maxOverScrollY;
21010        final int bottom = maxOverScrollY + scrollRangeY;
21011
21012        boolean clampedX = false;
21013        if (newScrollX > right) {
21014            newScrollX = right;
21015            clampedX = true;
21016        } else if (newScrollX < left) {
21017            newScrollX = left;
21018            clampedX = true;
21019        }
21020
21021        boolean clampedY = false;
21022        if (newScrollY > bottom) {
21023            newScrollY = bottom;
21024            clampedY = true;
21025        } else if (newScrollY < top) {
21026            newScrollY = top;
21027            clampedY = true;
21028        }
21029
21030        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
21031
21032        return clampedX || clampedY;
21033    }
21034
21035    /**
21036     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
21037     * respond to the results of an over-scroll operation.
21038     *
21039     * @param scrollX New X scroll value in pixels
21040     * @param scrollY New Y scroll value in pixels
21041     * @param clampedX True if scrollX was clamped to an over-scroll boundary
21042     * @param clampedY True if scrollY was clamped to an over-scroll boundary
21043     */
21044    protected void onOverScrolled(int scrollX, int scrollY,
21045            boolean clampedX, boolean clampedY) {
21046        // Intentionally empty.
21047    }
21048
21049    /**
21050     * Returns the over-scroll mode for this view. The result will be
21051     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21052     * (allow over-scrolling only if the view content is larger than the container),
21053     * or {@link #OVER_SCROLL_NEVER}.
21054     *
21055     * @return This view's over-scroll mode.
21056     */
21057    public int getOverScrollMode() {
21058        return mOverScrollMode;
21059    }
21060
21061    /**
21062     * Set the over-scroll mode for this view. Valid over-scroll modes are
21063     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21064     * (allow over-scrolling only if the view content is larger than the container),
21065     * or {@link #OVER_SCROLL_NEVER}.
21066     *
21067     * Setting the over-scroll mode of a view will have an effect only if the
21068     * view is capable of scrolling.
21069     *
21070     * @param overScrollMode The new over-scroll mode for this view.
21071     */
21072    public void setOverScrollMode(int overScrollMode) {
21073        if (overScrollMode != OVER_SCROLL_ALWAYS &&
21074                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
21075                overScrollMode != OVER_SCROLL_NEVER) {
21076            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
21077        }
21078        mOverScrollMode = overScrollMode;
21079    }
21080
21081    /**
21082     * Enable or disable nested scrolling for this view.
21083     *
21084     * <p>If this property is set to true the view will be permitted to initiate nested
21085     * scrolling operations with a compatible parent view in the current hierarchy. If this
21086     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
21087     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
21088     * the nested scroll.</p>
21089     *
21090     * @param enabled true to enable nested scrolling, false to disable
21091     *
21092     * @see #isNestedScrollingEnabled()
21093     */
21094    public void setNestedScrollingEnabled(boolean enabled) {
21095        if (enabled) {
21096            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
21097        } else {
21098            stopNestedScroll();
21099            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
21100        }
21101    }
21102
21103    /**
21104     * Returns true if nested scrolling is enabled for this view.
21105     *
21106     * <p>If nested scrolling is enabled and this View class implementation supports it,
21107     * this view will act as a nested scrolling child view when applicable, forwarding data
21108     * about the scroll operation in progress to a compatible and cooperating nested scrolling
21109     * parent.</p>
21110     *
21111     * @return true if nested scrolling is enabled
21112     *
21113     * @see #setNestedScrollingEnabled(boolean)
21114     */
21115    public boolean isNestedScrollingEnabled() {
21116        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
21117                PFLAG3_NESTED_SCROLLING_ENABLED;
21118    }
21119
21120    /**
21121     * Begin a nestable scroll operation along the given axes.
21122     *
21123     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
21124     *
21125     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
21126     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
21127     * In the case of touch scrolling the nested scroll will be terminated automatically in
21128     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
21129     * In the event of programmatic scrolling the caller must explicitly call
21130     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
21131     *
21132     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
21133     * If it returns false the caller may ignore the rest of this contract until the next scroll.
21134     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
21135     *
21136     * <p>At each incremental step of the scroll the caller should invoke
21137     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
21138     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
21139     * parent at least partially consumed the scroll and the caller should adjust the amount it
21140     * scrolls by.</p>
21141     *
21142     * <p>After applying the remainder of the scroll delta the caller should invoke
21143     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
21144     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
21145     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
21146     * </p>
21147     *
21148     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
21149     *             {@link #SCROLL_AXIS_VERTICAL}.
21150     * @return true if a cooperative parent was found and nested scrolling has been enabled for
21151     *         the current gesture.
21152     *
21153     * @see #stopNestedScroll()
21154     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21155     * @see #dispatchNestedScroll(int, int, int, int, int[])
21156     */
21157    public boolean startNestedScroll(int axes) {
21158        if (hasNestedScrollingParent()) {
21159            // Already in progress
21160            return true;
21161        }
21162        if (isNestedScrollingEnabled()) {
21163            ViewParent p = getParent();
21164            View child = this;
21165            while (p != null) {
21166                try {
21167                    if (p.onStartNestedScroll(child, this, axes)) {
21168                        mNestedScrollingParent = p;
21169                        p.onNestedScrollAccepted(child, this, axes);
21170                        return true;
21171                    }
21172                } catch (AbstractMethodError e) {
21173                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
21174                            "method onStartNestedScroll", e);
21175                    // Allow the search upward to continue
21176                }
21177                if (p instanceof View) {
21178                    child = (View) p;
21179                }
21180                p = p.getParent();
21181            }
21182        }
21183        return false;
21184    }
21185
21186    /**
21187     * Stop a nested scroll in progress.
21188     *
21189     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
21190     *
21191     * @see #startNestedScroll(int)
21192     */
21193    public void stopNestedScroll() {
21194        if (mNestedScrollingParent != null) {
21195            mNestedScrollingParent.onStopNestedScroll(this);
21196            mNestedScrollingParent = null;
21197        }
21198    }
21199
21200    /**
21201     * Returns true if this view has a nested scrolling parent.
21202     *
21203     * <p>The presence of a nested scrolling parent indicates that this view has initiated
21204     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
21205     *
21206     * @return whether this view has a nested scrolling parent
21207     */
21208    public boolean hasNestedScrollingParent() {
21209        return mNestedScrollingParent != null;
21210    }
21211
21212    /**
21213     * Dispatch one step of a nested scroll in progress.
21214     *
21215     * <p>Implementations of views that support nested scrolling should call this to report
21216     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
21217     * is not currently in progress or nested scrolling is not
21218     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
21219     *
21220     * <p>Compatible View implementations should also call
21221     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
21222     * consuming a component of the scroll event themselves.</p>
21223     *
21224     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
21225     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
21226     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
21227     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
21228     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21229     *                       in local view coordinates of this view from before this operation
21230     *                       to after it completes. View implementations may use this to adjust
21231     *                       expected input coordinate tracking.
21232     * @return true if the event was dispatched, false if it could not be dispatched.
21233     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21234     */
21235    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
21236            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
21237        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21238            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
21239                int startX = 0;
21240                int startY = 0;
21241                if (offsetInWindow != null) {
21242                    getLocationInWindow(offsetInWindow);
21243                    startX = offsetInWindow[0];
21244                    startY = offsetInWindow[1];
21245                }
21246
21247                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
21248                        dxUnconsumed, dyUnconsumed);
21249
21250                if (offsetInWindow != null) {
21251                    getLocationInWindow(offsetInWindow);
21252                    offsetInWindow[0] -= startX;
21253                    offsetInWindow[1] -= startY;
21254                }
21255                return true;
21256            } else if (offsetInWindow != null) {
21257                // No motion, no dispatch. Keep offsetInWindow up to date.
21258                offsetInWindow[0] = 0;
21259                offsetInWindow[1] = 0;
21260            }
21261        }
21262        return false;
21263    }
21264
21265    /**
21266     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
21267     *
21268     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
21269     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
21270     * scrolling operation to consume some or all of the scroll operation before the child view
21271     * consumes it.</p>
21272     *
21273     * @param dx Horizontal scroll distance in pixels
21274     * @param dy Vertical scroll distance in pixels
21275     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
21276     *                 and consumed[1] the consumed dy.
21277     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21278     *                       in local view coordinates of this view from before this operation
21279     *                       to after it completes. View implementations may use this to adjust
21280     *                       expected input coordinate tracking.
21281     * @return true if the parent consumed some or all of the scroll delta
21282     * @see #dispatchNestedScroll(int, int, int, int, int[])
21283     */
21284    public boolean dispatchNestedPreScroll(int dx, int dy,
21285            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
21286        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21287            if (dx != 0 || dy != 0) {
21288                int startX = 0;
21289                int startY = 0;
21290                if (offsetInWindow != null) {
21291                    getLocationInWindow(offsetInWindow);
21292                    startX = offsetInWindow[0];
21293                    startY = offsetInWindow[1];
21294                }
21295
21296                if (consumed == null) {
21297                    if (mTempNestedScrollConsumed == null) {
21298                        mTempNestedScrollConsumed = new int[2];
21299                    }
21300                    consumed = mTempNestedScrollConsumed;
21301                }
21302                consumed[0] = 0;
21303                consumed[1] = 0;
21304                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
21305
21306                if (offsetInWindow != null) {
21307                    getLocationInWindow(offsetInWindow);
21308                    offsetInWindow[0] -= startX;
21309                    offsetInWindow[1] -= startY;
21310                }
21311                return consumed[0] != 0 || consumed[1] != 0;
21312            } else if (offsetInWindow != null) {
21313                offsetInWindow[0] = 0;
21314                offsetInWindow[1] = 0;
21315            }
21316        }
21317        return false;
21318    }
21319
21320    /**
21321     * Dispatch a fling to a nested scrolling parent.
21322     *
21323     * <p>This method should be used to indicate that a nested scrolling child has detected
21324     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
21325     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
21326     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
21327     * along a scrollable axis.</p>
21328     *
21329     * <p>If a nested scrolling child view would normally fling but it is at the edge of
21330     * its own content, it can use this method to delegate the fling to its nested scrolling
21331     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
21332     *
21333     * @param velocityX Horizontal fling velocity in pixels per second
21334     * @param velocityY Vertical fling velocity in pixels per second
21335     * @param consumed true if the child consumed the fling, false otherwise
21336     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
21337     */
21338    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
21339        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21340            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
21341        }
21342        return false;
21343    }
21344
21345    /**
21346     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
21347     *
21348     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
21349     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
21350     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
21351     * before the child view consumes it. If this method returns <code>true</code>, a nested
21352     * parent view consumed the fling and this view should not scroll as a result.</p>
21353     *
21354     * <p>For a better user experience, only one view in a nested scrolling chain should consume
21355     * the fling at a time. If a parent view consumed the fling this method will return false.
21356     * Custom view implementations should account for this in two ways:</p>
21357     *
21358     * <ul>
21359     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
21360     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
21361     *     position regardless.</li>
21362     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
21363     *     even to settle back to a valid idle position.</li>
21364     * </ul>
21365     *
21366     * <p>Views should also not offer fling velocities to nested parent views along an axis
21367     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
21368     * should not offer a horizontal fling velocity to its parents since scrolling along that
21369     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
21370     *
21371     * @param velocityX Horizontal fling velocity in pixels per second
21372     * @param velocityY Vertical fling velocity in pixels per second
21373     * @return true if a nested scrolling parent consumed the fling
21374     */
21375    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
21376        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21377            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
21378        }
21379        return false;
21380    }
21381
21382    /**
21383     * Gets a scale factor that determines the distance the view should scroll
21384     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
21385     * @return The vertical scroll scale factor.
21386     * @hide
21387     */
21388    protected float getVerticalScrollFactor() {
21389        if (mVerticalScrollFactor == 0) {
21390            TypedValue outValue = new TypedValue();
21391            if (!mContext.getTheme().resolveAttribute(
21392                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
21393                throw new IllegalStateException(
21394                        "Expected theme to define listPreferredItemHeight.");
21395            }
21396            mVerticalScrollFactor = outValue.getDimension(
21397                    mContext.getResources().getDisplayMetrics());
21398        }
21399        return mVerticalScrollFactor;
21400    }
21401
21402    /**
21403     * Gets a scale factor that determines the distance the view should scroll
21404     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
21405     * @return The horizontal scroll scale factor.
21406     * @hide
21407     */
21408    protected float getHorizontalScrollFactor() {
21409        // TODO: Should use something else.
21410        return getVerticalScrollFactor();
21411    }
21412
21413    /**
21414     * Return the value specifying the text direction or policy that was set with
21415     * {@link #setTextDirection(int)}.
21416     *
21417     * @return the defined text direction. It can be one of:
21418     *
21419     * {@link #TEXT_DIRECTION_INHERIT},
21420     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21421     * {@link #TEXT_DIRECTION_ANY_RTL},
21422     * {@link #TEXT_DIRECTION_LTR},
21423     * {@link #TEXT_DIRECTION_RTL},
21424     * {@link #TEXT_DIRECTION_LOCALE},
21425     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21426     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21427     *
21428     * @attr ref android.R.styleable#View_textDirection
21429     *
21430     * @hide
21431     */
21432    @ViewDebug.ExportedProperty(category = "text", mapping = {
21433            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21434            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21435            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21436            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21437            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21438            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21439            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21440            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21441    })
21442    public int getRawTextDirection() {
21443        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
21444    }
21445
21446    /**
21447     * Set the text direction.
21448     *
21449     * @param textDirection the direction to set. Should be one of:
21450     *
21451     * {@link #TEXT_DIRECTION_INHERIT},
21452     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21453     * {@link #TEXT_DIRECTION_ANY_RTL},
21454     * {@link #TEXT_DIRECTION_LTR},
21455     * {@link #TEXT_DIRECTION_RTL},
21456     * {@link #TEXT_DIRECTION_LOCALE}
21457     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21458     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
21459     *
21460     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
21461     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
21462     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
21463     *
21464     * @attr ref android.R.styleable#View_textDirection
21465     */
21466    public void setTextDirection(int textDirection) {
21467        if (getRawTextDirection() != textDirection) {
21468            // Reset the current text direction and the resolved one
21469            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
21470            resetResolvedTextDirection();
21471            // Set the new text direction
21472            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
21473            // Do resolution
21474            resolveTextDirection();
21475            // Notify change
21476            onRtlPropertiesChanged(getLayoutDirection());
21477            // Refresh
21478            requestLayout();
21479            invalidate(true);
21480        }
21481    }
21482
21483    /**
21484     * Return the resolved text direction.
21485     *
21486     * @return the resolved text direction. Returns one of:
21487     *
21488     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21489     * {@link #TEXT_DIRECTION_ANY_RTL},
21490     * {@link #TEXT_DIRECTION_LTR},
21491     * {@link #TEXT_DIRECTION_RTL},
21492     * {@link #TEXT_DIRECTION_LOCALE},
21493     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21494     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21495     *
21496     * @attr ref android.R.styleable#View_textDirection
21497     */
21498    @ViewDebug.ExportedProperty(category = "text", mapping = {
21499            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21500            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21501            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21502            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21503            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21504            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21505            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21506            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21507    })
21508    public int getTextDirection() {
21509        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
21510    }
21511
21512    /**
21513     * Resolve the text direction.
21514     *
21515     * @return true if resolution has been done, false otherwise.
21516     *
21517     * @hide
21518     */
21519    public boolean resolveTextDirection() {
21520        // Reset any previous text direction resolution
21521        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21522
21523        if (hasRtlSupport()) {
21524            // Set resolved text direction flag depending on text direction flag
21525            final int textDirection = getRawTextDirection();
21526            switch(textDirection) {
21527                case TEXT_DIRECTION_INHERIT:
21528                    if (!canResolveTextDirection()) {
21529                        // We cannot do the resolution if there is no parent, so use the default one
21530                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21531                        // Resolution will need to happen again later
21532                        return false;
21533                    }
21534
21535                    // Parent has not yet resolved, so we still return the default
21536                    try {
21537                        if (!mParent.isTextDirectionResolved()) {
21538                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21539                            // Resolution will need to happen again later
21540                            return false;
21541                        }
21542                    } catch (AbstractMethodError e) {
21543                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21544                                " does not fully implement ViewParent", e);
21545                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
21546                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21547                        return true;
21548                    }
21549
21550                    // Set current resolved direction to the same value as the parent's one
21551                    int parentResolvedDirection;
21552                    try {
21553                        parentResolvedDirection = mParent.getTextDirection();
21554                    } catch (AbstractMethodError e) {
21555                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21556                                " does not fully implement ViewParent", e);
21557                        parentResolvedDirection = TEXT_DIRECTION_LTR;
21558                    }
21559                    switch (parentResolvedDirection) {
21560                        case TEXT_DIRECTION_FIRST_STRONG:
21561                        case TEXT_DIRECTION_ANY_RTL:
21562                        case TEXT_DIRECTION_LTR:
21563                        case TEXT_DIRECTION_RTL:
21564                        case TEXT_DIRECTION_LOCALE:
21565                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
21566                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
21567                            mPrivateFlags2 |=
21568                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21569                            break;
21570                        default:
21571                            // Default resolved direction is "first strong" heuristic
21572                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21573                    }
21574                    break;
21575                case TEXT_DIRECTION_FIRST_STRONG:
21576                case TEXT_DIRECTION_ANY_RTL:
21577                case TEXT_DIRECTION_LTR:
21578                case TEXT_DIRECTION_RTL:
21579                case TEXT_DIRECTION_LOCALE:
21580                case TEXT_DIRECTION_FIRST_STRONG_LTR:
21581                case TEXT_DIRECTION_FIRST_STRONG_RTL:
21582                    // Resolved direction is the same as text direction
21583                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
21584                    break;
21585                default:
21586                    // Default resolved direction is "first strong" heuristic
21587                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21588            }
21589        } else {
21590            // Default resolved direction is "first strong" heuristic
21591            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21592        }
21593
21594        // Set to resolved
21595        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
21596        return true;
21597    }
21598
21599    /**
21600     * Check if text direction resolution can be done.
21601     *
21602     * @return true if text direction resolution can be done otherwise return false.
21603     */
21604    public boolean canResolveTextDirection() {
21605        switch (getRawTextDirection()) {
21606            case TEXT_DIRECTION_INHERIT:
21607                if (mParent != null) {
21608                    try {
21609                        return mParent.canResolveTextDirection();
21610                    } catch (AbstractMethodError e) {
21611                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21612                                " does not fully implement ViewParent", e);
21613                    }
21614                }
21615                return false;
21616
21617            default:
21618                return true;
21619        }
21620    }
21621
21622    /**
21623     * Reset resolved text direction. Text direction will be resolved during a call to
21624     * {@link #onMeasure(int, int)}.
21625     *
21626     * @hide
21627     */
21628    public void resetResolvedTextDirection() {
21629        // Reset any previous text direction resolution
21630        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
21631        // Set to default value
21632        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
21633    }
21634
21635    /**
21636     * @return true if text direction is inherited.
21637     *
21638     * @hide
21639     */
21640    public boolean isTextDirectionInherited() {
21641        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
21642    }
21643
21644    /**
21645     * @return true if text direction is resolved.
21646     */
21647    public boolean isTextDirectionResolved() {
21648        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
21649    }
21650
21651    /**
21652     * Return the value specifying the text alignment or policy that was set with
21653     * {@link #setTextAlignment(int)}.
21654     *
21655     * @return the defined text alignment. It can be one of:
21656     *
21657     * {@link #TEXT_ALIGNMENT_INHERIT},
21658     * {@link #TEXT_ALIGNMENT_GRAVITY},
21659     * {@link #TEXT_ALIGNMENT_CENTER},
21660     * {@link #TEXT_ALIGNMENT_TEXT_START},
21661     * {@link #TEXT_ALIGNMENT_TEXT_END},
21662     * {@link #TEXT_ALIGNMENT_VIEW_START},
21663     * {@link #TEXT_ALIGNMENT_VIEW_END}
21664     *
21665     * @attr ref android.R.styleable#View_textAlignment
21666     *
21667     * @hide
21668     */
21669    @ViewDebug.ExportedProperty(category = "text", mapping = {
21670            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21671            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21672            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21673            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21674            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21675            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21676            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21677    })
21678    @TextAlignment
21679    public int getRawTextAlignment() {
21680        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
21681    }
21682
21683    /**
21684     * Set the text alignment.
21685     *
21686     * @param textAlignment The text alignment to set. Should be one of
21687     *
21688     * {@link #TEXT_ALIGNMENT_INHERIT},
21689     * {@link #TEXT_ALIGNMENT_GRAVITY},
21690     * {@link #TEXT_ALIGNMENT_CENTER},
21691     * {@link #TEXT_ALIGNMENT_TEXT_START},
21692     * {@link #TEXT_ALIGNMENT_TEXT_END},
21693     * {@link #TEXT_ALIGNMENT_VIEW_START},
21694     * {@link #TEXT_ALIGNMENT_VIEW_END}
21695     *
21696     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
21697     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
21698     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
21699     *
21700     * @attr ref android.R.styleable#View_textAlignment
21701     */
21702    public void setTextAlignment(@TextAlignment int textAlignment) {
21703        if (textAlignment != getRawTextAlignment()) {
21704            // Reset the current and resolved text alignment
21705            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
21706            resetResolvedTextAlignment();
21707            // Set the new text alignment
21708            mPrivateFlags2 |=
21709                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
21710            // Do resolution
21711            resolveTextAlignment();
21712            // Notify change
21713            onRtlPropertiesChanged(getLayoutDirection());
21714            // Refresh
21715            requestLayout();
21716            invalidate(true);
21717        }
21718    }
21719
21720    /**
21721     * Return the resolved text alignment.
21722     *
21723     * @return the resolved text alignment. Returns one of:
21724     *
21725     * {@link #TEXT_ALIGNMENT_GRAVITY},
21726     * {@link #TEXT_ALIGNMENT_CENTER},
21727     * {@link #TEXT_ALIGNMENT_TEXT_START},
21728     * {@link #TEXT_ALIGNMENT_TEXT_END},
21729     * {@link #TEXT_ALIGNMENT_VIEW_START},
21730     * {@link #TEXT_ALIGNMENT_VIEW_END}
21731     *
21732     * @attr ref android.R.styleable#View_textAlignment
21733     */
21734    @ViewDebug.ExportedProperty(category = "text", mapping = {
21735            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
21736            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
21737            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
21738            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
21739            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
21740            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
21741            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
21742    })
21743    @TextAlignment
21744    public int getTextAlignment() {
21745        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
21746                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
21747    }
21748
21749    /**
21750     * Resolve the text alignment.
21751     *
21752     * @return true if resolution has been done, false otherwise.
21753     *
21754     * @hide
21755     */
21756    public boolean resolveTextAlignment() {
21757        // Reset any previous text alignment resolution
21758        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21759
21760        if (hasRtlSupport()) {
21761            // Set resolved text alignment flag depending on text alignment flag
21762            final int textAlignment = getRawTextAlignment();
21763            switch (textAlignment) {
21764                case TEXT_ALIGNMENT_INHERIT:
21765                    // Check if we can resolve the text alignment
21766                    if (!canResolveTextAlignment()) {
21767                        // We cannot do the resolution if there is no parent so use the default
21768                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21769                        // Resolution will need to happen again later
21770                        return false;
21771                    }
21772
21773                    // Parent has not yet resolved, so we still return the default
21774                    try {
21775                        if (!mParent.isTextAlignmentResolved()) {
21776                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21777                            // Resolution will need to happen again later
21778                            return false;
21779                        }
21780                    } catch (AbstractMethodError e) {
21781                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21782                                " does not fully implement ViewParent", e);
21783                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
21784                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21785                        return true;
21786                    }
21787
21788                    int parentResolvedTextAlignment;
21789                    try {
21790                        parentResolvedTextAlignment = mParent.getTextAlignment();
21791                    } catch (AbstractMethodError e) {
21792                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21793                                " does not fully implement ViewParent", e);
21794                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
21795                    }
21796                    switch (parentResolvedTextAlignment) {
21797                        case TEXT_ALIGNMENT_GRAVITY:
21798                        case TEXT_ALIGNMENT_TEXT_START:
21799                        case TEXT_ALIGNMENT_TEXT_END:
21800                        case TEXT_ALIGNMENT_CENTER:
21801                        case TEXT_ALIGNMENT_VIEW_START:
21802                        case TEXT_ALIGNMENT_VIEW_END:
21803                            // Resolved text alignment is the same as the parent resolved
21804                            // text alignment
21805                            mPrivateFlags2 |=
21806                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21807                            break;
21808                        default:
21809                            // Use default resolved text alignment
21810                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21811                    }
21812                    break;
21813                case TEXT_ALIGNMENT_GRAVITY:
21814                case TEXT_ALIGNMENT_TEXT_START:
21815                case TEXT_ALIGNMENT_TEXT_END:
21816                case TEXT_ALIGNMENT_CENTER:
21817                case TEXT_ALIGNMENT_VIEW_START:
21818                case TEXT_ALIGNMENT_VIEW_END:
21819                    // Resolved text alignment is the same as text alignment
21820                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
21821                    break;
21822                default:
21823                    // Use default resolved text alignment
21824                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21825            }
21826        } else {
21827            // Use default resolved text alignment
21828            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21829        }
21830
21831        // Set the resolved
21832        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21833        return true;
21834    }
21835
21836    /**
21837     * Check if text alignment resolution can be done.
21838     *
21839     * @return true if text alignment resolution can be done otherwise return false.
21840     */
21841    public boolean canResolveTextAlignment() {
21842        switch (getRawTextAlignment()) {
21843            case TEXT_DIRECTION_INHERIT:
21844                if (mParent != null) {
21845                    try {
21846                        return mParent.canResolveTextAlignment();
21847                    } catch (AbstractMethodError e) {
21848                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21849                                " does not fully implement ViewParent", e);
21850                    }
21851                }
21852                return false;
21853
21854            default:
21855                return true;
21856        }
21857    }
21858
21859    /**
21860     * Reset resolved text alignment. Text alignment will be resolved during a call to
21861     * {@link #onMeasure(int, int)}.
21862     *
21863     * @hide
21864     */
21865    public void resetResolvedTextAlignment() {
21866        // Reset any previous text alignment resolution
21867        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21868        // Set to default
21869        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21870    }
21871
21872    /**
21873     * @return true if text alignment is inherited.
21874     *
21875     * @hide
21876     */
21877    public boolean isTextAlignmentInherited() {
21878        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
21879    }
21880
21881    /**
21882     * @return true if text alignment is resolved.
21883     */
21884    public boolean isTextAlignmentResolved() {
21885        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21886    }
21887
21888    /**
21889     * Generate a value suitable for use in {@link #setId(int)}.
21890     * This value will not collide with ID values generated at build time by aapt for R.id.
21891     *
21892     * @return a generated ID value
21893     */
21894    public static int generateViewId() {
21895        for (;;) {
21896            final int result = sNextGeneratedId.get();
21897            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
21898            int newValue = result + 1;
21899            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
21900            if (sNextGeneratedId.compareAndSet(result, newValue)) {
21901                return result;
21902            }
21903        }
21904    }
21905
21906    /**
21907     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
21908     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
21909     *                           a normal View or a ViewGroup with
21910     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
21911     * @hide
21912     */
21913    public void captureTransitioningViews(List<View> transitioningViews) {
21914        if (getVisibility() == View.VISIBLE) {
21915            transitioningViews.add(this);
21916        }
21917    }
21918
21919    /**
21920     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
21921     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
21922     * @hide
21923     */
21924    public void findNamedViews(Map<String, View> namedElements) {
21925        if (getVisibility() == VISIBLE || mGhostView != null) {
21926            String transitionName = getTransitionName();
21927            if (transitionName != null) {
21928                namedElements.put(transitionName, this);
21929            }
21930        }
21931    }
21932
21933    /**
21934     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
21935     * The default implementation does not care the location or event types, but some subclasses
21936     * may use it (such as WebViews).
21937     * @param event The MotionEvent from a mouse
21938     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
21939     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
21940     * @see PointerIcon
21941     */
21942    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
21943        final float x = event.getX(pointerIndex);
21944        final float y = event.getY(pointerIndex);
21945        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
21946            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
21947        }
21948        return mPointerIcon;
21949    }
21950
21951    /**
21952     * Set the pointer icon for the current view.
21953     * Passing {@code null} will restore the pointer icon to its default value.
21954     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
21955     */
21956    public void setPointerIcon(PointerIcon pointerIcon) {
21957        mPointerIcon = pointerIcon;
21958        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
21959            return;
21960        }
21961        try {
21962            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
21963        } catch (RemoteException e) {
21964        }
21965    }
21966
21967    /**
21968     * Gets the pointer icon for the current view.
21969     */
21970    public PointerIcon getPointerIcon() {
21971        return mPointerIcon;
21972    }
21973
21974    //
21975    // Properties
21976    //
21977    /**
21978     * A Property wrapper around the <code>alpha</code> functionality handled by the
21979     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
21980     */
21981    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
21982        @Override
21983        public void setValue(View object, float value) {
21984            object.setAlpha(value);
21985        }
21986
21987        @Override
21988        public Float get(View object) {
21989            return object.getAlpha();
21990        }
21991    };
21992
21993    /**
21994     * A Property wrapper around the <code>translationX</code> functionality handled by the
21995     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
21996     */
21997    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
21998        @Override
21999        public void setValue(View object, float value) {
22000            object.setTranslationX(value);
22001        }
22002
22003                @Override
22004        public Float get(View object) {
22005            return object.getTranslationX();
22006        }
22007    };
22008
22009    /**
22010     * A Property wrapper around the <code>translationY</code> functionality handled by the
22011     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
22012     */
22013    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
22014        @Override
22015        public void setValue(View object, float value) {
22016            object.setTranslationY(value);
22017        }
22018
22019        @Override
22020        public Float get(View object) {
22021            return object.getTranslationY();
22022        }
22023    };
22024
22025    /**
22026     * A Property wrapper around the <code>translationZ</code> functionality handled by the
22027     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
22028     */
22029    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
22030        @Override
22031        public void setValue(View object, float value) {
22032            object.setTranslationZ(value);
22033        }
22034
22035        @Override
22036        public Float get(View object) {
22037            return object.getTranslationZ();
22038        }
22039    };
22040
22041    /**
22042     * A Property wrapper around the <code>x</code> functionality handled by the
22043     * {@link View#setX(float)} and {@link View#getX()} methods.
22044     */
22045    public static final Property<View, Float> X = new FloatProperty<View>("x") {
22046        @Override
22047        public void setValue(View object, float value) {
22048            object.setX(value);
22049        }
22050
22051        @Override
22052        public Float get(View object) {
22053            return object.getX();
22054        }
22055    };
22056
22057    /**
22058     * A Property wrapper around the <code>y</code> functionality handled by the
22059     * {@link View#setY(float)} and {@link View#getY()} methods.
22060     */
22061    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
22062        @Override
22063        public void setValue(View object, float value) {
22064            object.setY(value);
22065        }
22066
22067        @Override
22068        public Float get(View object) {
22069            return object.getY();
22070        }
22071    };
22072
22073    /**
22074     * A Property wrapper around the <code>z</code> functionality handled by the
22075     * {@link View#setZ(float)} and {@link View#getZ()} methods.
22076     */
22077    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
22078        @Override
22079        public void setValue(View object, float value) {
22080            object.setZ(value);
22081        }
22082
22083        @Override
22084        public Float get(View object) {
22085            return object.getZ();
22086        }
22087    };
22088
22089    /**
22090     * A Property wrapper around the <code>rotation</code> functionality handled by the
22091     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
22092     */
22093    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
22094        @Override
22095        public void setValue(View object, float value) {
22096            object.setRotation(value);
22097        }
22098
22099        @Override
22100        public Float get(View object) {
22101            return object.getRotation();
22102        }
22103    };
22104
22105    /**
22106     * A Property wrapper around the <code>rotationX</code> functionality handled by the
22107     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
22108     */
22109    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
22110        @Override
22111        public void setValue(View object, float value) {
22112            object.setRotationX(value);
22113        }
22114
22115        @Override
22116        public Float get(View object) {
22117            return object.getRotationX();
22118        }
22119    };
22120
22121    /**
22122     * A Property wrapper around the <code>rotationY</code> functionality handled by the
22123     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
22124     */
22125    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
22126        @Override
22127        public void setValue(View object, float value) {
22128            object.setRotationY(value);
22129        }
22130
22131        @Override
22132        public Float get(View object) {
22133            return object.getRotationY();
22134        }
22135    };
22136
22137    /**
22138     * A Property wrapper around the <code>scaleX</code> functionality handled by the
22139     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
22140     */
22141    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
22142        @Override
22143        public void setValue(View object, float value) {
22144            object.setScaleX(value);
22145        }
22146
22147        @Override
22148        public Float get(View object) {
22149            return object.getScaleX();
22150        }
22151    };
22152
22153    /**
22154     * A Property wrapper around the <code>scaleY</code> functionality handled by the
22155     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
22156     */
22157    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
22158        @Override
22159        public void setValue(View object, float value) {
22160            object.setScaleY(value);
22161        }
22162
22163        @Override
22164        public Float get(View object) {
22165            return object.getScaleY();
22166        }
22167    };
22168
22169    /**
22170     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
22171     * Each MeasureSpec represents a requirement for either the width or the height.
22172     * A MeasureSpec is comprised of a size and a mode. There are three possible
22173     * modes:
22174     * <dl>
22175     * <dt>UNSPECIFIED</dt>
22176     * <dd>
22177     * The parent has not imposed any constraint on the child. It can be whatever size
22178     * it wants.
22179     * </dd>
22180     *
22181     * <dt>EXACTLY</dt>
22182     * <dd>
22183     * The parent has determined an exact size for the child. The child is going to be
22184     * given those bounds regardless of how big it wants to be.
22185     * </dd>
22186     *
22187     * <dt>AT_MOST</dt>
22188     * <dd>
22189     * The child can be as large as it wants up to the specified size.
22190     * </dd>
22191     * </dl>
22192     *
22193     * MeasureSpecs are implemented as ints to reduce object allocation. This class
22194     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
22195     */
22196    public static class MeasureSpec {
22197        private static final int MODE_SHIFT = 30;
22198        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
22199
22200        /** @hide */
22201        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
22202        @Retention(RetentionPolicy.SOURCE)
22203        public @interface MeasureSpecMode {}
22204
22205        /**
22206         * Measure specification mode: The parent has not imposed any constraint
22207         * on the child. It can be whatever size it wants.
22208         */
22209        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
22210
22211        /**
22212         * Measure specification mode: The parent has determined an exact size
22213         * for the child. The child is going to be given those bounds regardless
22214         * of how big it wants to be.
22215         */
22216        public static final int EXACTLY     = 1 << MODE_SHIFT;
22217
22218        /**
22219         * Measure specification mode: The child can be as large as it wants up
22220         * to the specified size.
22221         */
22222        public static final int AT_MOST     = 2 << MODE_SHIFT;
22223
22224        /**
22225         * Creates a measure specification based on the supplied size and mode.
22226         *
22227         * The mode must always be one of the following:
22228         * <ul>
22229         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
22230         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
22231         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
22232         * </ul>
22233         *
22234         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
22235         * implementation was such that the order of arguments did not matter
22236         * and overflow in either value could impact the resulting MeasureSpec.
22237         * {@link android.widget.RelativeLayout} was affected by this bug.
22238         * Apps targeting API levels greater than 17 will get the fixed, more strict
22239         * behavior.</p>
22240         *
22241         * @param size the size of the measure specification
22242         * @param mode the mode of the measure specification
22243         * @return the measure specification based on size and mode
22244         */
22245        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
22246                                          @MeasureSpecMode int mode) {
22247            if (sUseBrokenMakeMeasureSpec) {
22248                return size + mode;
22249            } else {
22250                return (size & ~MODE_MASK) | (mode & MODE_MASK);
22251            }
22252        }
22253
22254        /**
22255         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
22256         * will automatically get a size of 0. Older apps expect this.
22257         *
22258         * @hide internal use only for compatibility with system widgets and older apps
22259         */
22260        public static int makeSafeMeasureSpec(int size, int mode) {
22261            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
22262                return 0;
22263            }
22264            return makeMeasureSpec(size, mode);
22265        }
22266
22267        /**
22268         * Extracts the mode from the supplied measure specification.
22269         *
22270         * @param measureSpec the measure specification to extract the mode from
22271         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
22272         *         {@link android.view.View.MeasureSpec#AT_MOST} or
22273         *         {@link android.view.View.MeasureSpec#EXACTLY}
22274         */
22275        @MeasureSpecMode
22276        public static int getMode(int measureSpec) {
22277            //noinspection ResourceType
22278            return (measureSpec & MODE_MASK);
22279        }
22280
22281        /**
22282         * Extracts the size from the supplied measure specification.
22283         *
22284         * @param measureSpec the measure specification to extract the size from
22285         * @return the size in pixels defined in the supplied measure specification
22286         */
22287        public static int getSize(int measureSpec) {
22288            return (measureSpec & ~MODE_MASK);
22289        }
22290
22291        static int adjust(int measureSpec, int delta) {
22292            final int mode = getMode(measureSpec);
22293            int size = getSize(measureSpec);
22294            if (mode == UNSPECIFIED) {
22295                // No need to adjust size for UNSPECIFIED mode.
22296                return makeMeasureSpec(size, UNSPECIFIED);
22297            }
22298            size += delta;
22299            if (size < 0) {
22300                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
22301                        ") spec: " + toString(measureSpec) + " delta: " + delta);
22302                size = 0;
22303            }
22304            return makeMeasureSpec(size, mode);
22305        }
22306
22307        /**
22308         * Returns a String representation of the specified measure
22309         * specification.
22310         *
22311         * @param measureSpec the measure specification to convert to a String
22312         * @return a String with the following format: "MeasureSpec: MODE SIZE"
22313         */
22314        public static String toString(int measureSpec) {
22315            int mode = getMode(measureSpec);
22316            int size = getSize(measureSpec);
22317
22318            StringBuilder sb = new StringBuilder("MeasureSpec: ");
22319
22320            if (mode == UNSPECIFIED)
22321                sb.append("UNSPECIFIED ");
22322            else if (mode == EXACTLY)
22323                sb.append("EXACTLY ");
22324            else if (mode == AT_MOST)
22325                sb.append("AT_MOST ");
22326            else
22327                sb.append(mode).append(" ");
22328
22329            sb.append(size);
22330            return sb.toString();
22331        }
22332    }
22333
22334    private final class CheckForLongPress implements Runnable {
22335        private int mOriginalWindowAttachCount;
22336        private float mX;
22337        private float mY;
22338
22339        @Override
22340        public void run() {
22341            if (isPressed() && (mParent != null)
22342                    && mOriginalWindowAttachCount == mWindowAttachCount) {
22343                if (performLongClick(mX, mY)) {
22344                    mHasPerformedLongPress = true;
22345                }
22346            }
22347        }
22348
22349        public void setAnchor(float x, float y) {
22350            mX = x;
22351            mY = y;
22352        }
22353
22354        public void rememberWindowAttachCount() {
22355            mOriginalWindowAttachCount = mWindowAttachCount;
22356        }
22357    }
22358
22359    private final class CheckForTap implements Runnable {
22360        public float x;
22361        public float y;
22362
22363        @Override
22364        public void run() {
22365            mPrivateFlags &= ~PFLAG_PREPRESSED;
22366            setPressed(true, x, y);
22367            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
22368        }
22369    }
22370
22371    private final class PerformClick implements Runnable {
22372        @Override
22373        public void run() {
22374            performClick();
22375        }
22376    }
22377
22378    /**
22379     * This method returns a ViewPropertyAnimator object, which can be used to animate
22380     * specific properties on this View.
22381     *
22382     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
22383     */
22384    public ViewPropertyAnimator animate() {
22385        if (mAnimator == null) {
22386            mAnimator = new ViewPropertyAnimator(this);
22387        }
22388        return mAnimator;
22389    }
22390
22391    /**
22392     * Sets the name of the View to be used to identify Views in Transitions.
22393     * Names should be unique in the View hierarchy.
22394     *
22395     * @param transitionName The name of the View to uniquely identify it for Transitions.
22396     */
22397    public final void setTransitionName(String transitionName) {
22398        mTransitionName = transitionName;
22399    }
22400
22401    /**
22402     * Returns the name of the View to be used to identify Views in Transitions.
22403     * Names should be unique in the View hierarchy.
22404     *
22405     * <p>This returns null if the View has not been given a name.</p>
22406     *
22407     * @return The name used of the View to be used to identify Views in Transitions or null
22408     * if no name has been given.
22409     */
22410    @ViewDebug.ExportedProperty
22411    public String getTransitionName() {
22412        return mTransitionName;
22413    }
22414
22415    /**
22416     * @hide
22417     */
22418    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
22419        // Do nothing.
22420    }
22421
22422    /**
22423     * Interface definition for a callback to be invoked when a hardware key event is
22424     * dispatched to this view. The callback will be invoked before the key event is
22425     * given to the view. This is only useful for hardware keyboards; a software input
22426     * method has no obligation to trigger this listener.
22427     */
22428    public interface OnKeyListener {
22429        /**
22430         * Called when a hardware key is dispatched to a view. This allows listeners to
22431         * get a chance to respond before the target view.
22432         * <p>Key presses in software keyboards will generally NOT trigger this method,
22433         * although some may elect to do so in some situations. Do not assume a
22434         * software input method has to be key-based; even if it is, it may use key presses
22435         * in a different way than you expect, so there is no way to reliably catch soft
22436         * input key presses.
22437         *
22438         * @param v The view the key has been dispatched to.
22439         * @param keyCode The code for the physical key that was pressed
22440         * @param event The KeyEvent object containing full information about
22441         *        the event.
22442         * @return True if the listener has consumed the event, false otherwise.
22443         */
22444        boolean onKey(View v, int keyCode, KeyEvent event);
22445    }
22446
22447    /**
22448     * Interface definition for a callback to be invoked when a touch event is
22449     * dispatched to this view. The callback will be invoked before the touch
22450     * event is given to the view.
22451     */
22452    public interface OnTouchListener {
22453        /**
22454         * Called when a touch event is dispatched to a view. This allows listeners to
22455         * get a chance to respond before the target view.
22456         *
22457         * @param v The view the touch event has been dispatched to.
22458         * @param event The MotionEvent object containing full information about
22459         *        the event.
22460         * @return True if the listener has consumed the event, false otherwise.
22461         */
22462        boolean onTouch(View v, MotionEvent event);
22463    }
22464
22465    /**
22466     * Interface definition for a callback to be invoked when a hover event is
22467     * dispatched to this view. The callback will be invoked before the hover
22468     * event is given to the view.
22469     */
22470    public interface OnHoverListener {
22471        /**
22472         * Called when a hover event is dispatched to a view. This allows listeners to
22473         * get a chance to respond before the target view.
22474         *
22475         * @param v The view the hover event has been dispatched to.
22476         * @param event The MotionEvent object containing full information about
22477         *        the event.
22478         * @return True if the listener has consumed the event, false otherwise.
22479         */
22480        boolean onHover(View v, MotionEvent event);
22481    }
22482
22483    /**
22484     * Interface definition for a callback to be invoked when a generic motion event is
22485     * dispatched to this view. The callback will be invoked before the generic motion
22486     * event is given to the view.
22487     */
22488    public interface OnGenericMotionListener {
22489        /**
22490         * Called when a generic motion event is dispatched to a view. This allows listeners to
22491         * get a chance to respond before the target view.
22492         *
22493         * @param v The view the generic motion event has been dispatched to.
22494         * @param event The MotionEvent object containing full information about
22495         *        the event.
22496         * @return True if the listener has consumed the event, false otherwise.
22497         */
22498        boolean onGenericMotion(View v, MotionEvent event);
22499    }
22500
22501    /**
22502     * Interface definition for a callback to be invoked when a view has been clicked and held.
22503     */
22504    public interface OnLongClickListener {
22505        /**
22506         * Called when a view has been clicked and held.
22507         *
22508         * @param v The view that was clicked and held.
22509         *
22510         * @return true if the callback consumed the long click, false otherwise.
22511         */
22512        boolean onLongClick(View v);
22513    }
22514
22515    /**
22516     * Interface definition for a callback to be invoked when a drag is being dispatched
22517     * to this view.  The callback will be invoked before the hosting view's own
22518     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
22519     * onDrag(event) behavior, it should return 'false' from this callback.
22520     *
22521     * <div class="special reference">
22522     * <h3>Developer Guides</h3>
22523     * <p>For a guide to implementing drag and drop features, read the
22524     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22525     * </div>
22526     */
22527    public interface OnDragListener {
22528        /**
22529         * Called when a drag event is dispatched to a view. This allows listeners
22530         * to get a chance to override base View behavior.
22531         *
22532         * @param v The View that received the drag event.
22533         * @param event The {@link android.view.DragEvent} object for the drag event.
22534         * @return {@code true} if the drag event was handled successfully, or {@code false}
22535         * if the drag event was not handled. Note that {@code false} will trigger the View
22536         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
22537         */
22538        boolean onDrag(View v, DragEvent event);
22539    }
22540
22541    /**
22542     * Interface definition for a callback to be invoked when the focus state of
22543     * a view changed.
22544     */
22545    public interface OnFocusChangeListener {
22546        /**
22547         * Called when the focus state of a view has changed.
22548         *
22549         * @param v The view whose state has changed.
22550         * @param hasFocus The new focus state of v.
22551         */
22552        void onFocusChange(View v, boolean hasFocus);
22553    }
22554
22555    /**
22556     * Interface definition for a callback to be invoked when a view is clicked.
22557     */
22558    public interface OnClickListener {
22559        /**
22560         * Called when a view has been clicked.
22561         *
22562         * @param v The view that was clicked.
22563         */
22564        void onClick(View v);
22565    }
22566
22567    /**
22568     * Interface definition for a callback to be invoked when a view is context clicked.
22569     */
22570    public interface OnContextClickListener {
22571        /**
22572         * Called when a view is context clicked.
22573         *
22574         * @param v The view that has been context clicked.
22575         * @return true if the callback consumed the context click, false otherwise.
22576         */
22577        boolean onContextClick(View v);
22578    }
22579
22580    /**
22581     * Interface definition for a callback to be invoked when the context menu
22582     * for this view is being built.
22583     */
22584    public interface OnCreateContextMenuListener {
22585        /**
22586         * Called when the context menu for this view is being built. It is not
22587         * safe to hold onto the menu after this method returns.
22588         *
22589         * @param menu The context menu that is being built
22590         * @param v The view for which the context menu is being built
22591         * @param menuInfo Extra information about the item for which the
22592         *            context menu should be shown. This information will vary
22593         *            depending on the class of v.
22594         */
22595        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
22596    }
22597
22598    /**
22599     * Interface definition for a callback to be invoked when the status bar changes
22600     * visibility.  This reports <strong>global</strong> changes to the system UI
22601     * state, not what the application is requesting.
22602     *
22603     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
22604     */
22605    public interface OnSystemUiVisibilityChangeListener {
22606        /**
22607         * Called when the status bar changes visibility because of a call to
22608         * {@link View#setSystemUiVisibility(int)}.
22609         *
22610         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22611         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
22612         * This tells you the <strong>global</strong> state of these UI visibility
22613         * flags, not what your app is currently applying.
22614         */
22615        public void onSystemUiVisibilityChange(int visibility);
22616    }
22617
22618    /**
22619     * Interface definition for a callback to be invoked when this view is attached
22620     * or detached from its window.
22621     */
22622    public interface OnAttachStateChangeListener {
22623        /**
22624         * Called when the view is attached to a window.
22625         * @param v The view that was attached
22626         */
22627        public void onViewAttachedToWindow(View v);
22628        /**
22629         * Called when the view is detached from a window.
22630         * @param v The view that was detached
22631         */
22632        public void onViewDetachedFromWindow(View v);
22633    }
22634
22635    /**
22636     * Listener for applying window insets on a view in a custom way.
22637     *
22638     * <p>Apps may choose to implement this interface if they want to apply custom policy
22639     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
22640     * is set, its
22641     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
22642     * method will be called instead of the View's own
22643     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
22644     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
22645     * the View's normal behavior as part of its own.</p>
22646     */
22647    public interface OnApplyWindowInsetsListener {
22648        /**
22649         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
22650         * on a View, this listener method will be called instead of the view's own
22651         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
22652         *
22653         * @param v The view applying window insets
22654         * @param insets The insets to apply
22655         * @return The insets supplied, minus any insets that were consumed
22656         */
22657        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
22658    }
22659
22660    private final class UnsetPressedState implements Runnable {
22661        @Override
22662        public void run() {
22663            setPressed(false);
22664        }
22665    }
22666
22667    /**
22668     * Base class for derived classes that want to save and restore their own
22669     * state in {@link android.view.View#onSaveInstanceState()}.
22670     */
22671    public static class BaseSavedState extends AbsSavedState {
22672        String mStartActivityRequestWhoSaved;
22673
22674        /**
22675         * Constructor used when reading from a parcel. Reads the state of the superclass.
22676         *
22677         * @param source parcel to read from
22678         */
22679        public BaseSavedState(Parcel source) {
22680            this(source, null);
22681        }
22682
22683        /**
22684         * Constructor used when reading from a parcel using a given class loader.
22685         * Reads the state of the superclass.
22686         *
22687         * @param source parcel to read from
22688         * @param loader ClassLoader to use for reading
22689         */
22690        public BaseSavedState(Parcel source, ClassLoader loader) {
22691            super(source, loader);
22692            mStartActivityRequestWhoSaved = source.readString();
22693        }
22694
22695        /**
22696         * Constructor called by derived classes when creating their SavedState objects
22697         *
22698         * @param superState The state of the superclass of this view
22699         */
22700        public BaseSavedState(Parcelable superState) {
22701            super(superState);
22702        }
22703
22704        @Override
22705        public void writeToParcel(Parcel out, int flags) {
22706            super.writeToParcel(out, flags);
22707            out.writeString(mStartActivityRequestWhoSaved);
22708        }
22709
22710        public static final Parcelable.Creator<BaseSavedState> CREATOR
22711                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
22712            @Override
22713            public BaseSavedState createFromParcel(Parcel in) {
22714                return new BaseSavedState(in);
22715            }
22716
22717            @Override
22718            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
22719                return new BaseSavedState(in, loader);
22720            }
22721
22722            @Override
22723            public BaseSavedState[] newArray(int size) {
22724                return new BaseSavedState[size];
22725            }
22726        };
22727    }
22728
22729    /**
22730     * A set of information given to a view when it is attached to its parent
22731     * window.
22732     */
22733    final static class AttachInfo {
22734        interface Callbacks {
22735            void playSoundEffect(int effectId);
22736            boolean performHapticFeedback(int effectId, boolean always);
22737        }
22738
22739        /**
22740         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
22741         * to a Handler. This class contains the target (View) to invalidate and
22742         * the coordinates of the dirty rectangle.
22743         *
22744         * For performance purposes, this class also implements a pool of up to
22745         * POOL_LIMIT objects that get reused. This reduces memory allocations
22746         * whenever possible.
22747         */
22748        static class InvalidateInfo {
22749            private static final int POOL_LIMIT = 10;
22750
22751            private static final SynchronizedPool<InvalidateInfo> sPool =
22752                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
22753
22754            View target;
22755
22756            int left;
22757            int top;
22758            int right;
22759            int bottom;
22760
22761            public static InvalidateInfo obtain() {
22762                InvalidateInfo instance = sPool.acquire();
22763                return (instance != null) ? instance : new InvalidateInfo();
22764            }
22765
22766            public void recycle() {
22767                target = null;
22768                sPool.release(this);
22769            }
22770        }
22771
22772        final IWindowSession mSession;
22773
22774        final IWindow mWindow;
22775
22776        final IBinder mWindowToken;
22777
22778        final Display mDisplay;
22779
22780        final Callbacks mRootCallbacks;
22781
22782        IWindowId mIWindowId;
22783        WindowId mWindowId;
22784
22785        /**
22786         * The top view of the hierarchy.
22787         */
22788        View mRootView;
22789
22790        IBinder mPanelParentWindowToken;
22791
22792        boolean mHardwareAccelerated;
22793        boolean mHardwareAccelerationRequested;
22794        ThreadedRenderer mHardwareRenderer;
22795        List<RenderNode> mPendingAnimatingRenderNodes;
22796
22797        /**
22798         * The state of the display to which the window is attached, as reported
22799         * by {@link Display#getState()}.  Note that the display state constants
22800         * declared by {@link Display} do not exactly line up with the screen state
22801         * constants declared by {@link View} (there are more display states than
22802         * screen states).
22803         */
22804        int mDisplayState = Display.STATE_UNKNOWN;
22805
22806        /**
22807         * Scale factor used by the compatibility mode
22808         */
22809        float mApplicationScale;
22810
22811        /**
22812         * Indicates whether the application is in compatibility mode
22813         */
22814        boolean mScalingRequired;
22815
22816        /**
22817         * Left position of this view's window
22818         */
22819        int mWindowLeft;
22820
22821        /**
22822         * Top position of this view's window
22823         */
22824        int mWindowTop;
22825
22826        /**
22827         * Indicates whether views need to use 32-bit drawing caches
22828         */
22829        boolean mUse32BitDrawingCache;
22830
22831        /**
22832         * For windows that are full-screen but using insets to layout inside
22833         * of the screen areas, these are the current insets to appear inside
22834         * the overscan area of the display.
22835         */
22836        final Rect mOverscanInsets = new Rect();
22837
22838        /**
22839         * For windows that are full-screen but using insets to layout inside
22840         * of the screen decorations, these are the current insets for the
22841         * content of the window.
22842         */
22843        final Rect mContentInsets = new Rect();
22844
22845        /**
22846         * For windows that are full-screen but using insets to layout inside
22847         * of the screen decorations, these are the current insets for the
22848         * actual visible parts of the window.
22849         */
22850        final Rect mVisibleInsets = new Rect();
22851
22852        /**
22853         * For windows that are full-screen but using insets to layout inside
22854         * of the screen decorations, these are the current insets for the
22855         * stable system windows.
22856         */
22857        final Rect mStableInsets = new Rect();
22858
22859        /**
22860         * For windows that include areas that are not covered by real surface these are the outsets
22861         * for real surface.
22862         */
22863        final Rect mOutsets = new Rect();
22864
22865        /**
22866         * In multi-window we force show the navigation bar. Because we don't want that the surface
22867         * size changes in this mode, we instead have a flag whether the navigation bar size should
22868         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
22869         */
22870        boolean mAlwaysConsumeNavBar;
22871
22872        /**
22873         * The internal insets given by this window.  This value is
22874         * supplied by the client (through
22875         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
22876         * be given to the window manager when changed to be used in laying
22877         * out windows behind it.
22878         */
22879        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
22880                = new ViewTreeObserver.InternalInsetsInfo();
22881
22882        /**
22883         * Set to true when mGivenInternalInsets is non-empty.
22884         */
22885        boolean mHasNonEmptyGivenInternalInsets;
22886
22887        /**
22888         * All views in the window's hierarchy that serve as scroll containers,
22889         * used to determine if the window can be resized or must be panned
22890         * to adjust for a soft input area.
22891         */
22892        final ArrayList<View> mScrollContainers = new ArrayList<View>();
22893
22894        final KeyEvent.DispatcherState mKeyDispatchState
22895                = new KeyEvent.DispatcherState();
22896
22897        /**
22898         * Indicates whether the view's window currently has the focus.
22899         */
22900        boolean mHasWindowFocus;
22901
22902        /**
22903         * The current visibility of the window.
22904         */
22905        int mWindowVisibility;
22906
22907        /**
22908         * Indicates the time at which drawing started to occur.
22909         */
22910        long mDrawingTime;
22911
22912        /**
22913         * Indicates whether or not ignoring the DIRTY_MASK flags.
22914         */
22915        boolean mIgnoreDirtyState;
22916
22917        /**
22918         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
22919         * to avoid clearing that flag prematurely.
22920         */
22921        boolean mSetIgnoreDirtyState = false;
22922
22923        /**
22924         * Indicates whether the view's window is currently in touch mode.
22925         */
22926        boolean mInTouchMode;
22927
22928        /**
22929         * Indicates whether the view has requested unbuffered input dispatching for the current
22930         * event stream.
22931         */
22932        boolean mUnbufferedDispatchRequested;
22933
22934        /**
22935         * Indicates that ViewAncestor should trigger a global layout change
22936         * the next time it performs a traversal
22937         */
22938        boolean mRecomputeGlobalAttributes;
22939
22940        /**
22941         * Always report new attributes at next traversal.
22942         */
22943        boolean mForceReportNewAttributes;
22944
22945        /**
22946         * Set during a traveral if any views want to keep the screen on.
22947         */
22948        boolean mKeepScreenOn;
22949
22950        /**
22951         * Set during a traveral if the light center needs to be updated.
22952         */
22953        boolean mNeedsUpdateLightCenter;
22954
22955        /**
22956         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
22957         */
22958        int mSystemUiVisibility;
22959
22960        /**
22961         * Hack to force certain system UI visibility flags to be cleared.
22962         */
22963        int mDisabledSystemUiVisibility;
22964
22965        /**
22966         * Last global system UI visibility reported by the window manager.
22967         */
22968        int mGlobalSystemUiVisibility = -1;
22969
22970        /**
22971         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
22972         * attached.
22973         */
22974        boolean mHasSystemUiListeners;
22975
22976        /**
22977         * Set if the window has requested to extend into the overscan region
22978         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
22979         */
22980        boolean mOverscanRequested;
22981
22982        /**
22983         * Set if the visibility of any views has changed.
22984         */
22985        boolean mViewVisibilityChanged;
22986
22987        /**
22988         * Set to true if a view has been scrolled.
22989         */
22990        boolean mViewScrollChanged;
22991
22992        /**
22993         * Set to true if high contrast mode enabled
22994         */
22995        boolean mHighContrastText;
22996
22997        /**
22998         * Set to true if a pointer event is currently being handled.
22999         */
23000        boolean mHandlingPointerEvent;
23001
23002        /**
23003         * Global to the view hierarchy used as a temporary for dealing with
23004         * x/y points in the transparent region computations.
23005         */
23006        final int[] mTransparentLocation = new int[2];
23007
23008        /**
23009         * Global to the view hierarchy used as a temporary for dealing with
23010         * x/y points in the ViewGroup.invalidateChild implementation.
23011         */
23012        final int[] mInvalidateChildLocation = new int[2];
23013
23014        /**
23015         * Global to the view hierarchy used as a temporary for dealing with
23016         * computing absolute on-screen location.
23017         */
23018        final int[] mTmpLocation = new int[2];
23019
23020        /**
23021         * Global to the view hierarchy used as a temporary for dealing with
23022         * x/y location when view is transformed.
23023         */
23024        final float[] mTmpTransformLocation = new float[2];
23025
23026        /**
23027         * The view tree observer used to dispatch global events like
23028         * layout, pre-draw, touch mode change, etc.
23029         */
23030        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
23031
23032        /**
23033         * A Canvas used by the view hierarchy to perform bitmap caching.
23034         */
23035        Canvas mCanvas;
23036
23037        /**
23038         * The view root impl.
23039         */
23040        final ViewRootImpl mViewRootImpl;
23041
23042        /**
23043         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
23044         * handler can be used to pump events in the UI events queue.
23045         */
23046        final Handler mHandler;
23047
23048        /**
23049         * Temporary for use in computing invalidate rectangles while
23050         * calling up the hierarchy.
23051         */
23052        final Rect mTmpInvalRect = new Rect();
23053
23054        /**
23055         * Temporary for use in computing hit areas with transformed views
23056         */
23057        final RectF mTmpTransformRect = new RectF();
23058
23059        /**
23060         * Temporary for use in computing hit areas with transformed views
23061         */
23062        final RectF mTmpTransformRect1 = new RectF();
23063
23064        /**
23065         * Temporary list of rectanges.
23066         */
23067        final List<RectF> mTmpRectList = new ArrayList<>();
23068
23069        /**
23070         * Temporary for use in transforming invalidation rect
23071         */
23072        final Matrix mTmpMatrix = new Matrix();
23073
23074        /**
23075         * Temporary for use in transforming invalidation rect
23076         */
23077        final Transformation mTmpTransformation = new Transformation();
23078
23079        /**
23080         * Temporary for use in querying outlines from OutlineProviders
23081         */
23082        final Outline mTmpOutline = new Outline();
23083
23084        /**
23085         * Temporary list for use in collecting focusable descendents of a view.
23086         */
23087        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
23088
23089        /**
23090         * The id of the window for accessibility purposes.
23091         */
23092        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
23093
23094        /**
23095         * Flags related to accessibility processing.
23096         *
23097         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
23098         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
23099         */
23100        int mAccessibilityFetchFlags;
23101
23102        /**
23103         * The drawable for highlighting accessibility focus.
23104         */
23105        Drawable mAccessibilityFocusDrawable;
23106
23107        /**
23108         * Show where the margins, bounds and layout bounds are for each view.
23109         */
23110        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
23111
23112        /**
23113         * Point used to compute visible regions.
23114         */
23115        final Point mPoint = new Point();
23116
23117        /**
23118         * Used to track which View originated a requestLayout() call, used when
23119         * requestLayout() is called during layout.
23120         */
23121        View mViewRequestingLayout;
23122
23123        /**
23124         * Used to track views that need (at least) a partial relayout at their current size
23125         * during the next traversal.
23126         */
23127        List<View> mPartialLayoutViews = new ArrayList<>();
23128
23129        /**
23130         * Swapped with mPartialLayoutViews during layout to avoid concurrent
23131         * modification. Lazily assigned during ViewRootImpl layout.
23132         */
23133        List<View> mEmptyPartialLayoutViews;
23134
23135        /**
23136         * Used to track the identity of the current drag operation.
23137         */
23138        IBinder mDragToken;
23139
23140        /**
23141         * The drag shadow surface for the current drag operation.
23142         */
23143        public Surface mDragSurface;
23144
23145        /**
23146         * Creates a new set of attachment information with the specified
23147         * events handler and thread.
23148         *
23149         * @param handler the events handler the view must use
23150         */
23151        AttachInfo(IWindowSession session, IWindow window, Display display,
23152                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
23153            mSession = session;
23154            mWindow = window;
23155            mWindowToken = window.asBinder();
23156            mDisplay = display;
23157            mViewRootImpl = viewRootImpl;
23158            mHandler = handler;
23159            mRootCallbacks = effectPlayer;
23160        }
23161    }
23162
23163    /**
23164     * <p>ScrollabilityCache holds various fields used by a View when scrolling
23165     * is supported. This avoids keeping too many unused fields in most
23166     * instances of View.</p>
23167     */
23168    private static class ScrollabilityCache implements Runnable {
23169
23170        /**
23171         * Scrollbars are not visible
23172         */
23173        public static final int OFF = 0;
23174
23175        /**
23176         * Scrollbars are visible
23177         */
23178        public static final int ON = 1;
23179
23180        /**
23181         * Scrollbars are fading away
23182         */
23183        public static final int FADING = 2;
23184
23185        public boolean fadeScrollBars;
23186
23187        public int fadingEdgeLength;
23188        public int scrollBarDefaultDelayBeforeFade;
23189        public int scrollBarFadeDuration;
23190
23191        public int scrollBarSize;
23192        public ScrollBarDrawable scrollBar;
23193        public float[] interpolatorValues;
23194        public View host;
23195
23196        public final Paint paint;
23197        public final Matrix matrix;
23198        public Shader shader;
23199
23200        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
23201
23202        private static final float[] OPAQUE = { 255 };
23203        private static final float[] TRANSPARENT = { 0.0f };
23204
23205        /**
23206         * When fading should start. This time moves into the future every time
23207         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
23208         */
23209        public long fadeStartTime;
23210
23211
23212        /**
23213         * The current state of the scrollbars: ON, OFF, or FADING
23214         */
23215        public int state = OFF;
23216
23217        private int mLastColor;
23218
23219        public final Rect mScrollBarBounds = new Rect();
23220
23221        public static final int NOT_DRAGGING = 0;
23222        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
23223        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
23224        public int mScrollBarDraggingState = NOT_DRAGGING;
23225
23226        public float mScrollBarDraggingPos = 0;
23227
23228        public ScrollabilityCache(ViewConfiguration configuration, View host) {
23229            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
23230            scrollBarSize = configuration.getScaledScrollBarSize();
23231            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
23232            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
23233
23234            paint = new Paint();
23235            matrix = new Matrix();
23236            // use use a height of 1, and then wack the matrix each time we
23237            // actually use it.
23238            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23239            paint.setShader(shader);
23240            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23241
23242            this.host = host;
23243        }
23244
23245        public void setFadeColor(int color) {
23246            if (color != mLastColor) {
23247                mLastColor = color;
23248
23249                if (color != 0) {
23250                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
23251                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
23252                    paint.setShader(shader);
23253                    // Restore the default transfer mode (src_over)
23254                    paint.setXfermode(null);
23255                } else {
23256                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23257                    paint.setShader(shader);
23258                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23259                }
23260            }
23261        }
23262
23263        public void run() {
23264            long now = AnimationUtils.currentAnimationTimeMillis();
23265            if (now >= fadeStartTime) {
23266
23267                // the animation fades the scrollbars out by changing
23268                // the opacity (alpha) from fully opaque to fully
23269                // transparent
23270                int nextFrame = (int) now;
23271                int framesCount = 0;
23272
23273                Interpolator interpolator = scrollBarInterpolator;
23274
23275                // Start opaque
23276                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
23277
23278                // End transparent
23279                nextFrame += scrollBarFadeDuration;
23280                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
23281
23282                state = FADING;
23283
23284                // Kick off the fade animation
23285                host.invalidate(true);
23286            }
23287        }
23288    }
23289
23290    /**
23291     * Resuable callback for sending
23292     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
23293     */
23294    private class SendViewScrolledAccessibilityEvent implements Runnable {
23295        public volatile boolean mIsPending;
23296
23297        public void run() {
23298            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
23299            mIsPending = false;
23300        }
23301    }
23302
23303    /**
23304     * <p>
23305     * This class represents a delegate that can be registered in a {@link View}
23306     * to enhance accessibility support via composition rather via inheritance.
23307     * It is specifically targeted to widget developers that extend basic View
23308     * classes i.e. classes in package android.view, that would like their
23309     * applications to be backwards compatible.
23310     * </p>
23311     * <div class="special reference">
23312     * <h3>Developer Guides</h3>
23313     * <p>For more information about making applications accessible, read the
23314     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
23315     * developer guide.</p>
23316     * </div>
23317     * <p>
23318     * A scenario in which a developer would like to use an accessibility delegate
23319     * is overriding a method introduced in a later API version then the minimal API
23320     * version supported by the application. For example, the method
23321     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
23322     * in API version 4 when the accessibility APIs were first introduced. If a
23323     * developer would like his application to run on API version 4 devices (assuming
23324     * all other APIs used by the application are version 4 or lower) and take advantage
23325     * of this method, instead of overriding the method which would break the application's
23326     * backwards compatibility, he can override the corresponding method in this
23327     * delegate and register the delegate in the target View if the API version of
23328     * the system is high enough i.e. the API version is same or higher to the API
23329     * version that introduced
23330     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
23331     * </p>
23332     * <p>
23333     * Here is an example implementation:
23334     * </p>
23335     * <code><pre><p>
23336     * if (Build.VERSION.SDK_INT >= 14) {
23337     *     // If the API version is equal of higher than the version in
23338     *     // which onInitializeAccessibilityNodeInfo was introduced we
23339     *     // register a delegate with a customized implementation.
23340     *     View view = findViewById(R.id.view_id);
23341     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
23342     *         public void onInitializeAccessibilityNodeInfo(View host,
23343     *                 AccessibilityNodeInfo info) {
23344     *             // Let the default implementation populate the info.
23345     *             super.onInitializeAccessibilityNodeInfo(host, info);
23346     *             // Set some other information.
23347     *             info.setEnabled(host.isEnabled());
23348     *         }
23349     *     });
23350     * }
23351     * </code></pre></p>
23352     * <p>
23353     * This delegate contains methods that correspond to the accessibility methods
23354     * in View. If a delegate has been specified the implementation in View hands
23355     * off handling to the corresponding method in this delegate. The default
23356     * implementation the delegate methods behaves exactly as the corresponding
23357     * method in View for the case of no accessibility delegate been set. Hence,
23358     * to customize the behavior of a View method, clients can override only the
23359     * corresponding delegate method without altering the behavior of the rest
23360     * accessibility related methods of the host view.
23361     * </p>
23362     * <p>
23363     * <strong>Note:</strong> On platform versions prior to
23364     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
23365     * views in the {@code android.widget.*} package are called <i>before</i>
23366     * host methods. This prevents certain properties such as class name from
23367     * being modified by overriding
23368     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
23369     * as any changes will be overwritten by the host class.
23370     * <p>
23371     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
23372     * methods are called <i>after</i> host methods, which all properties to be
23373     * modified without being overwritten by the host class.
23374     */
23375    public static class AccessibilityDelegate {
23376
23377        /**
23378         * Sends an accessibility event of the given type. If accessibility is not
23379         * enabled this method has no effect.
23380         * <p>
23381         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
23382         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
23383         * been set.
23384         * </p>
23385         *
23386         * @param host The View hosting the delegate.
23387         * @param eventType The type of the event to send.
23388         *
23389         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
23390         */
23391        public void sendAccessibilityEvent(View host, int eventType) {
23392            host.sendAccessibilityEventInternal(eventType);
23393        }
23394
23395        /**
23396         * Performs the specified accessibility action on the view. For
23397         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
23398         * <p>
23399         * The default implementation behaves as
23400         * {@link View#performAccessibilityAction(int, Bundle)
23401         *  View#performAccessibilityAction(int, Bundle)} for the case of
23402         *  no accessibility delegate been set.
23403         * </p>
23404         *
23405         * @param action The action to perform.
23406         * @return Whether the action was performed.
23407         *
23408         * @see View#performAccessibilityAction(int, Bundle)
23409         *      View#performAccessibilityAction(int, Bundle)
23410         */
23411        public boolean performAccessibilityAction(View host, int action, Bundle args) {
23412            return host.performAccessibilityActionInternal(action, args);
23413        }
23414
23415        /**
23416         * Sends an accessibility event. This method behaves exactly as
23417         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
23418         * empty {@link AccessibilityEvent} and does not perform a check whether
23419         * accessibility is enabled.
23420         * <p>
23421         * The default implementation behaves as
23422         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23423         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
23424         * the case of no accessibility delegate been set.
23425         * </p>
23426         *
23427         * @param host The View hosting the delegate.
23428         * @param event The event to send.
23429         *
23430         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23431         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23432         */
23433        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
23434            host.sendAccessibilityEventUncheckedInternal(event);
23435        }
23436
23437        /**
23438         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
23439         * to its children for adding their text content to the event.
23440         * <p>
23441         * The default implementation behaves as
23442         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23443         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
23444         * the case of no accessibility delegate been set.
23445         * </p>
23446         *
23447         * @param host The View hosting the delegate.
23448         * @param event The event.
23449         * @return True if the event population was completed.
23450         *
23451         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23452         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23453         */
23454        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23455            return host.dispatchPopulateAccessibilityEventInternal(event);
23456        }
23457
23458        /**
23459         * Gives a chance to the host View to populate the accessibility event with its
23460         * text content.
23461         * <p>
23462         * The default implementation behaves as
23463         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
23464         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
23465         * the case of no accessibility delegate been set.
23466         * </p>
23467         *
23468         * @param host The View hosting the delegate.
23469         * @param event The accessibility event which to populate.
23470         *
23471         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
23472         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
23473         */
23474        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23475            host.onPopulateAccessibilityEventInternal(event);
23476        }
23477
23478        /**
23479         * Initializes an {@link AccessibilityEvent} with information about the
23480         * the host View which is the event source.
23481         * <p>
23482         * The default implementation behaves as
23483         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
23484         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
23485         * the case of no accessibility delegate been set.
23486         * </p>
23487         *
23488         * @param host The View hosting the delegate.
23489         * @param event The event to initialize.
23490         *
23491         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
23492         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
23493         */
23494        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
23495            host.onInitializeAccessibilityEventInternal(event);
23496        }
23497
23498        /**
23499         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
23500         * <p>
23501         * The default implementation behaves as
23502         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23503         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
23504         * the case of no accessibility delegate been set.
23505         * </p>
23506         *
23507         * @param host The View hosting the delegate.
23508         * @param info The instance to initialize.
23509         *
23510         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23511         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
23512         */
23513        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
23514            host.onInitializeAccessibilityNodeInfoInternal(info);
23515        }
23516
23517        /**
23518         * Called when a child of the host View has requested sending an
23519         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
23520         * to augment the event.
23521         * <p>
23522         * The default implementation behaves as
23523         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23524         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
23525         * the case of no accessibility delegate been set.
23526         * </p>
23527         *
23528         * @param host The View hosting the delegate.
23529         * @param child The child which requests sending the event.
23530         * @param event The event to be sent.
23531         * @return True if the event should be sent
23532         *
23533         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23534         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
23535         */
23536        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
23537                AccessibilityEvent event) {
23538            return host.onRequestSendAccessibilityEventInternal(child, event);
23539        }
23540
23541        /**
23542         * Gets the provider for managing a virtual view hierarchy rooted at this View
23543         * and reported to {@link android.accessibilityservice.AccessibilityService}s
23544         * that explore the window content.
23545         * <p>
23546         * The default implementation behaves as
23547         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
23548         * the case of no accessibility delegate been set.
23549         * </p>
23550         *
23551         * @return The provider.
23552         *
23553         * @see AccessibilityNodeProvider
23554         */
23555        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
23556            return null;
23557        }
23558
23559        /**
23560         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
23561         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
23562         * This method is responsible for obtaining an accessibility node info from a
23563         * pool of reusable instances and calling
23564         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
23565         * view to initialize the former.
23566         * <p>
23567         * <strong>Note:</strong> The client is responsible for recycling the obtained
23568         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
23569         * creation.
23570         * </p>
23571         * <p>
23572         * The default implementation behaves as
23573         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
23574         * the case of no accessibility delegate been set.
23575         * </p>
23576         * @return A populated {@link AccessibilityNodeInfo}.
23577         *
23578         * @see AccessibilityNodeInfo
23579         *
23580         * @hide
23581         */
23582        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
23583            return host.createAccessibilityNodeInfoInternal();
23584        }
23585    }
23586
23587    private class MatchIdPredicate implements Predicate<View> {
23588        public int mId;
23589
23590        @Override
23591        public boolean apply(View view) {
23592            return (view.mID == mId);
23593        }
23594    }
23595
23596    private class MatchLabelForPredicate implements Predicate<View> {
23597        private int mLabeledId;
23598
23599        @Override
23600        public boolean apply(View view) {
23601            return (view.mLabelForId == mLabeledId);
23602        }
23603    }
23604
23605    private class SendViewStateChangedAccessibilityEvent implements Runnable {
23606        private int mChangeTypes = 0;
23607        private boolean mPosted;
23608        private boolean mPostedWithDelay;
23609        private long mLastEventTimeMillis;
23610
23611        @Override
23612        public void run() {
23613            mPosted = false;
23614            mPostedWithDelay = false;
23615            mLastEventTimeMillis = SystemClock.uptimeMillis();
23616            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
23617                final AccessibilityEvent event = AccessibilityEvent.obtain();
23618                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
23619                event.setContentChangeTypes(mChangeTypes);
23620                sendAccessibilityEventUnchecked(event);
23621            }
23622            mChangeTypes = 0;
23623        }
23624
23625        public void runOrPost(int changeType) {
23626            mChangeTypes |= changeType;
23627
23628            // If this is a live region or the child of a live region, collect
23629            // all events from this frame and send them on the next frame.
23630            if (inLiveRegion()) {
23631                // If we're already posted with a delay, remove that.
23632                if (mPostedWithDelay) {
23633                    removeCallbacks(this);
23634                    mPostedWithDelay = false;
23635                }
23636                // Only post if we're not already posted.
23637                if (!mPosted) {
23638                    post(this);
23639                    mPosted = true;
23640                }
23641                return;
23642            }
23643
23644            if (mPosted) {
23645                return;
23646            }
23647
23648            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
23649            final long minEventIntevalMillis =
23650                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
23651            if (timeSinceLastMillis >= minEventIntevalMillis) {
23652                removeCallbacks(this);
23653                run();
23654            } else {
23655                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
23656                mPostedWithDelay = true;
23657            }
23658        }
23659    }
23660
23661    private boolean inLiveRegion() {
23662        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23663            return true;
23664        }
23665
23666        ViewParent parent = getParent();
23667        while (parent instanceof View) {
23668            if (((View) parent).getAccessibilityLiveRegion()
23669                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
23670                return true;
23671            }
23672            parent = parent.getParent();
23673        }
23674
23675        return false;
23676    }
23677
23678    /**
23679     * Dump all private flags in readable format, useful for documentation and
23680     * sanity checking.
23681     */
23682    private static void dumpFlags() {
23683        final HashMap<String, String> found = Maps.newHashMap();
23684        try {
23685            for (Field field : View.class.getDeclaredFields()) {
23686                final int modifiers = field.getModifiers();
23687                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
23688                    if (field.getType().equals(int.class)) {
23689                        final int value = field.getInt(null);
23690                        dumpFlag(found, field.getName(), value);
23691                    } else if (field.getType().equals(int[].class)) {
23692                        final int[] values = (int[]) field.get(null);
23693                        for (int i = 0; i < values.length; i++) {
23694                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
23695                        }
23696                    }
23697                }
23698            }
23699        } catch (IllegalAccessException e) {
23700            throw new RuntimeException(e);
23701        }
23702
23703        final ArrayList<String> keys = Lists.newArrayList();
23704        keys.addAll(found.keySet());
23705        Collections.sort(keys);
23706        for (String key : keys) {
23707            Log.d(VIEW_LOG_TAG, found.get(key));
23708        }
23709    }
23710
23711    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
23712        // Sort flags by prefix, then by bits, always keeping unique keys
23713        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
23714        final int prefix = name.indexOf('_');
23715        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
23716        final String output = bits + " " + name;
23717        found.put(key, output);
23718    }
23719
23720    /** {@hide} */
23721    public void encode(@NonNull ViewHierarchyEncoder stream) {
23722        stream.beginObject(this);
23723        encodeProperties(stream);
23724        stream.endObject();
23725    }
23726
23727    /** {@hide} */
23728    @CallSuper
23729    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
23730        Object resolveId = ViewDebug.resolveId(getContext(), mID);
23731        if (resolveId instanceof String) {
23732            stream.addProperty("id", (String) resolveId);
23733        } else {
23734            stream.addProperty("id", mID);
23735        }
23736
23737        stream.addProperty("misc:transformation.alpha",
23738                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
23739        stream.addProperty("misc:transitionName", getTransitionName());
23740
23741        // layout
23742        stream.addProperty("layout:left", mLeft);
23743        stream.addProperty("layout:right", mRight);
23744        stream.addProperty("layout:top", mTop);
23745        stream.addProperty("layout:bottom", mBottom);
23746        stream.addProperty("layout:width", getWidth());
23747        stream.addProperty("layout:height", getHeight());
23748        stream.addProperty("layout:layoutDirection", getLayoutDirection());
23749        stream.addProperty("layout:layoutRtl", isLayoutRtl());
23750        stream.addProperty("layout:hasTransientState", hasTransientState());
23751        stream.addProperty("layout:baseline", getBaseline());
23752
23753        // layout params
23754        ViewGroup.LayoutParams layoutParams = getLayoutParams();
23755        if (layoutParams != null) {
23756            stream.addPropertyKey("layoutParams");
23757            layoutParams.encode(stream);
23758        }
23759
23760        // scrolling
23761        stream.addProperty("scrolling:scrollX", mScrollX);
23762        stream.addProperty("scrolling:scrollY", mScrollY);
23763
23764        // padding
23765        stream.addProperty("padding:paddingLeft", mPaddingLeft);
23766        stream.addProperty("padding:paddingRight", mPaddingRight);
23767        stream.addProperty("padding:paddingTop", mPaddingTop);
23768        stream.addProperty("padding:paddingBottom", mPaddingBottom);
23769        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
23770        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
23771        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
23772        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
23773        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
23774
23775        // measurement
23776        stream.addProperty("measurement:minHeight", mMinHeight);
23777        stream.addProperty("measurement:minWidth", mMinWidth);
23778        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
23779        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
23780
23781        // drawing
23782        stream.addProperty("drawing:elevation", getElevation());
23783        stream.addProperty("drawing:translationX", getTranslationX());
23784        stream.addProperty("drawing:translationY", getTranslationY());
23785        stream.addProperty("drawing:translationZ", getTranslationZ());
23786        stream.addProperty("drawing:rotation", getRotation());
23787        stream.addProperty("drawing:rotationX", getRotationX());
23788        stream.addProperty("drawing:rotationY", getRotationY());
23789        stream.addProperty("drawing:scaleX", getScaleX());
23790        stream.addProperty("drawing:scaleY", getScaleY());
23791        stream.addProperty("drawing:pivotX", getPivotX());
23792        stream.addProperty("drawing:pivotY", getPivotY());
23793        stream.addProperty("drawing:opaque", isOpaque());
23794        stream.addProperty("drawing:alpha", getAlpha());
23795        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
23796        stream.addProperty("drawing:shadow", hasShadow());
23797        stream.addProperty("drawing:solidColor", getSolidColor());
23798        stream.addProperty("drawing:layerType", mLayerType);
23799        stream.addProperty("drawing:willNotDraw", willNotDraw());
23800        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
23801        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
23802        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
23803        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
23804
23805        // focus
23806        stream.addProperty("focus:hasFocus", hasFocus());
23807        stream.addProperty("focus:isFocused", isFocused());
23808        stream.addProperty("focus:isFocusable", isFocusable());
23809        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
23810
23811        stream.addProperty("misc:clickable", isClickable());
23812        stream.addProperty("misc:pressed", isPressed());
23813        stream.addProperty("misc:selected", isSelected());
23814        stream.addProperty("misc:touchMode", isInTouchMode());
23815        stream.addProperty("misc:hovered", isHovered());
23816        stream.addProperty("misc:activated", isActivated());
23817
23818        stream.addProperty("misc:visibility", getVisibility());
23819        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
23820        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
23821
23822        stream.addProperty("misc:enabled", isEnabled());
23823        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
23824        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
23825
23826        // theme attributes
23827        Resources.Theme theme = getContext().getTheme();
23828        if (theme != null) {
23829            stream.addPropertyKey("theme");
23830            theme.encode(stream);
23831        }
23832
23833        // view attribute information
23834        int n = mAttributes != null ? mAttributes.length : 0;
23835        stream.addProperty("meta:__attrCount__", n/2);
23836        for (int i = 0; i < n; i += 2) {
23837            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
23838        }
23839
23840        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
23841
23842        // text
23843        stream.addProperty("text:textDirection", getTextDirection());
23844        stream.addProperty("text:textAlignment", getTextAlignment());
23845
23846        // accessibility
23847        CharSequence contentDescription = getContentDescription();
23848        stream.addProperty("accessibility:contentDescription",
23849                contentDescription == null ? "" : contentDescription.toString());
23850        stream.addProperty("accessibility:labelFor", getLabelFor());
23851        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
23852    }
23853
23854    /**
23855     * Determine if this view is rendered on a round wearable device and is the main view
23856     * on the screen.
23857     */
23858    private boolean shouldDrawRoundScrollbar() {
23859        if (!mResources.getConfiguration().isScreenRound()) {
23860            return false;
23861        }
23862
23863        final View rootView = getRootView();
23864        final WindowInsets insets = getRootWindowInsets();
23865
23866        int height = getHeight();
23867        int width = getWidth();
23868        int displayHeight = rootView.getHeight();
23869        int displayWidth = rootView.getWidth();
23870
23871        if (height != displayHeight || width != displayWidth) {
23872            return false;
23873        }
23874
23875        getLocationOnScreen(mAttachInfo.mTmpLocation);
23876        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
23877                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
23878    }
23879}
23880