View.java revision 311a5b54979afee7e07bf31600182584fde15b4f
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
20import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
21import static android.os.Build.VERSION_CODES.KITKAT;
22import static android.os.Build.VERSION_CODES.M;
23import static android.os.Build.VERSION_CODES.N;
24
25import static java.lang.Math.max;
26
27import android.animation.AnimatorInflater;
28import android.animation.StateListAnimator;
29import android.annotation.CallSuper;
30import android.annotation.ColorInt;
31import android.annotation.DrawableRes;
32import android.annotation.FloatRange;
33import android.annotation.IdRes;
34import android.annotation.IntDef;
35import android.annotation.IntRange;
36import android.annotation.LayoutRes;
37import android.annotation.NonNull;
38import android.annotation.Nullable;
39import android.annotation.Size;
40import android.annotation.TestApi;
41import android.annotation.UiThread;
42import android.content.ClipData;
43import android.content.Context;
44import android.content.ContextWrapper;
45import android.content.Intent;
46import android.content.res.ColorStateList;
47import android.content.res.Configuration;
48import android.content.res.Resources;
49import android.content.res.TypedArray;
50import android.graphics.Bitmap;
51import android.graphics.Canvas;
52import android.graphics.Color;
53import android.graphics.Insets;
54import android.graphics.Interpolator;
55import android.graphics.LinearGradient;
56import android.graphics.Matrix;
57import android.graphics.Outline;
58import android.graphics.Paint;
59import android.graphics.PixelFormat;
60import android.graphics.Point;
61import android.graphics.PorterDuff;
62import android.graphics.PorterDuffXfermode;
63import android.graphics.Rect;
64import android.graphics.RectF;
65import android.graphics.Region;
66import android.graphics.Shader;
67import android.graphics.drawable.ColorDrawable;
68import android.graphics.drawable.Drawable;
69import android.hardware.display.DisplayManagerGlobal;
70import android.os.Build.VERSION_CODES;
71import android.os.Bundle;
72import android.os.Handler;
73import android.os.IBinder;
74import android.os.Parcel;
75import android.os.Parcelable;
76import android.os.RemoteException;
77import android.os.SystemClock;
78import android.os.SystemProperties;
79import android.os.Trace;
80import android.text.TextUtils;
81import android.util.AttributeSet;
82import android.util.FloatProperty;
83import android.util.LayoutDirection;
84import android.util.Log;
85import android.util.LongSparseLongArray;
86import android.util.Pools.SynchronizedPool;
87import android.util.Property;
88import android.util.SparseArray;
89import android.util.StateSet;
90import android.util.SuperNotCalledException;
91import android.util.TypedValue;
92import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
93import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
94import android.view.AccessibilityIterators.TextSegmentIterator;
95import android.view.AccessibilityIterators.WordTextSegmentIterator;
96import android.view.ContextMenu.ContextMenuInfo;
97import android.view.accessibility.AccessibilityEvent;
98import android.view.accessibility.AccessibilityEventSource;
99import android.view.accessibility.AccessibilityManager;
100import android.view.accessibility.AccessibilityNodeInfo;
101import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
102import android.view.accessibility.AccessibilityNodeProvider;
103import android.view.animation.Animation;
104import android.view.animation.AnimationUtils;
105import android.view.animation.Transformation;
106import android.view.inputmethod.EditorInfo;
107import android.view.inputmethod.InputConnection;
108import android.view.inputmethod.InputMethodManager;
109import android.widget.Checkable;
110import android.widget.FrameLayout;
111import android.widget.ScrollBarDrawable;
112
113import com.android.internal.R;
114import com.android.internal.util.Predicate;
115import com.android.internal.view.TooltipPopup;
116import com.android.internal.view.menu.MenuBuilder;
117import com.android.internal.widget.ScrollBarUtils;
118
119import com.google.android.collect.Lists;
120import com.google.android.collect.Maps;
121
122import java.lang.annotation.Retention;
123import java.lang.annotation.RetentionPolicy;
124import java.lang.ref.WeakReference;
125import java.lang.reflect.Field;
126import java.lang.reflect.InvocationTargetException;
127import java.lang.reflect.Method;
128import java.lang.reflect.Modifier;
129import java.util.ArrayList;
130import java.util.Arrays;
131import java.util.Collection;
132import java.util.Collections;
133import java.util.HashMap;
134import java.util.List;
135import java.util.Locale;
136import java.util.Map;
137import java.util.concurrent.CopyOnWriteArrayList;
138import java.util.concurrent.atomic.AtomicInteger;
139
140/**
141 * <p>
142 * This class represents the basic building block for user interface components. A View
143 * occupies a rectangular area on the screen and is responsible for drawing and
144 * event handling. View is the base class for <em>widgets</em>, which are
145 * used to create interactive UI components (buttons, text fields, etc.). The
146 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
147 * are invisible containers that hold other Views (or other ViewGroups) and define
148 * their layout properties.
149 * </p>
150 *
151 * <div class="special reference">
152 * <h3>Developer Guides</h3>
153 * <p>For information about using this class to develop your application's user interface,
154 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
155 * </div>
156 *
157 * <a name="Using"></a>
158 * <h3>Using Views</h3>
159 * <p>
160 * All of the views in a window are arranged in a single tree. You can add views
161 * either from code or by specifying a tree of views in one or more XML layout
162 * files. There are many specialized subclasses of views that act as controls or
163 * are capable of displaying text, images, or other content.
164 * </p>
165 * <p>
166 * Once you have created a tree of views, there are typically a few types of
167 * common operations you may wish to perform:
168 * <ul>
169 * <li><strong>Set properties:</strong> for example setting the text of a
170 * {@link android.widget.TextView}. The available properties and the methods
171 * that set them will vary among the different subclasses of views. Note that
172 * properties that are known at build time can be set in the XML layout
173 * files.</li>
174 * <li><strong>Set focus:</strong> The framework will handle moving focus in
175 * response to user input. To force focus to a specific view, call
176 * {@link #requestFocus}.</li>
177 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
178 * that will be notified when something interesting happens to the view. For
179 * example, all views will let you set a listener to be notified when the view
180 * gains or loses focus. You can register such a listener using
181 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
182 * Other view subclasses offer more specialized listeners. For example, a Button
183 * exposes a listener to notify clients when the button is clicked.</li>
184 * <li><strong>Set visibility:</strong> You can hide or show views using
185 * {@link #setVisibility(int)}.</li>
186 * </ul>
187 * </p>
188 * <p><em>
189 * Note: The Android framework is responsible for measuring, laying out and
190 * drawing views. You should not call methods that perform these actions on
191 * views yourself unless you are actually implementing a
192 * {@link android.view.ViewGroup}.
193 * </em></p>
194 *
195 * <a name="Lifecycle"></a>
196 * <h3>Implementing a Custom View</h3>
197 *
198 * <p>
199 * To implement a custom view, you will usually begin by providing overrides for
200 * some of the standard methods that the framework calls on all views. You do
201 * not need to override all of these methods. In fact, you can start by just
202 * overriding {@link #onDraw(android.graphics.Canvas)}.
203 * <table border="2" width="85%" align="center" cellpadding="5">
204 *     <thead>
205 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
206 *     </thead>
207 *
208 *     <tbody>
209 *     <tr>
210 *         <td rowspan="2">Creation</td>
211 *         <td>Constructors</td>
212 *         <td>There is a form of the constructor that are called when the view
213 *         is created from code and a form that is called when the view is
214 *         inflated from a layout file. The second form should parse and apply
215 *         any attributes defined in the layout file.
216 *         </td>
217 *     </tr>
218 *     <tr>
219 *         <td><code>{@link #onFinishInflate()}</code></td>
220 *         <td>Called after a view and all of its children has been inflated
221 *         from XML.</td>
222 *     </tr>
223 *
224 *     <tr>
225 *         <td rowspan="3">Layout</td>
226 *         <td><code>{@link #onMeasure(int, int)}</code></td>
227 *         <td>Called to determine the size requirements for this view and all
228 *         of its children.
229 *         </td>
230 *     </tr>
231 *     <tr>
232 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
233 *         <td>Called when this view should assign a size and position to all
234 *         of its children.
235 *         </td>
236 *     </tr>
237 *     <tr>
238 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
239 *         <td>Called when the size of this view has changed.
240 *         </td>
241 *     </tr>
242 *
243 *     <tr>
244 *         <td>Drawing</td>
245 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
246 *         <td>Called when the view should render its content.
247 *         </td>
248 *     </tr>
249 *
250 *     <tr>
251 *         <td rowspan="4">Event processing</td>
252 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
253 *         <td>Called when a new hardware key event occurs.
254 *         </td>
255 *     </tr>
256 *     <tr>
257 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
258 *         <td>Called when a hardware key up event occurs.
259 *         </td>
260 *     </tr>
261 *     <tr>
262 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
263 *         <td>Called when a trackball motion event occurs.
264 *         </td>
265 *     </tr>
266 *     <tr>
267 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
268 *         <td>Called when a touch screen motion event occurs.
269 *         </td>
270 *     </tr>
271 *
272 *     <tr>
273 *         <td rowspan="2">Focus</td>
274 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
275 *         <td>Called when the view gains or loses focus.
276 *         </td>
277 *     </tr>
278 *
279 *     <tr>
280 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
281 *         <td>Called when the window containing the view gains or loses focus.
282 *         </td>
283 *     </tr>
284 *
285 *     <tr>
286 *         <td rowspan="3">Attaching</td>
287 *         <td><code>{@link #onAttachedToWindow()}</code></td>
288 *         <td>Called when the view is attached to a window.
289 *         </td>
290 *     </tr>
291 *
292 *     <tr>
293 *         <td><code>{@link #onDetachedFromWindow}</code></td>
294 *         <td>Called when the view is detached from its window.
295 *         </td>
296 *     </tr>
297 *
298 *     <tr>
299 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
300 *         <td>Called when the visibility of the window containing the view
301 *         has changed.
302 *         </td>
303 *     </tr>
304 *     </tbody>
305 *
306 * </table>
307 * </p>
308 *
309 * <a name="IDs"></a>
310 * <h3>IDs</h3>
311 * Views may have an integer id associated with them. These ids are typically
312 * assigned in the layout XML files, and are used to find specific views within
313 * the view tree. A common pattern is to:
314 * <ul>
315 * <li>Define a Button in the layout file and assign it a unique ID.
316 * <pre>
317 * &lt;Button
318 *     android:id="@+id/my_button"
319 *     android:layout_width="wrap_content"
320 *     android:layout_height="wrap_content"
321 *     android:text="@string/my_button_text"/&gt;
322 * </pre></li>
323 * <li>From the onCreate method of an Activity, find the Button
324 * <pre class="prettyprint">
325 *      Button myButton = (Button) findViewById(R.id.my_button);
326 * </pre></li>
327 * </ul>
328 * <p>
329 * View IDs need not be unique throughout the tree, but it is good practice to
330 * ensure that they are at least unique within the part of the tree you are
331 * searching.
332 * </p>
333 *
334 * <a name="Position"></a>
335 * <h3>Position</h3>
336 * <p>
337 * The geometry of a view is that of a rectangle. A view has a location,
338 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
339 * two dimensions, expressed as a width and a height. The unit for location
340 * and dimensions is the pixel.
341 * </p>
342 *
343 * <p>
344 * It is possible to retrieve the location of a view by invoking the methods
345 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
346 * coordinate of the rectangle representing the view. The latter returns the
347 * top, or Y, coordinate of the rectangle representing the view. These methods
348 * both return the location of the view relative to its parent. For instance,
349 * when getLeft() returns 20, that means the view is located 20 pixels to the
350 * right of the left edge of its direct parent.
351 * </p>
352 *
353 * <p>
354 * In addition, several convenience methods are offered to avoid unnecessary
355 * computations, namely {@link #getRight()} and {@link #getBottom()}.
356 * These methods return the coordinates of the right and bottom edges of the
357 * rectangle representing the view. For instance, calling {@link #getRight()}
358 * is similar to the following computation: <code>getLeft() + getWidth()</code>
359 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
360 * </p>
361 *
362 * <a name="SizePaddingMargins"></a>
363 * <h3>Size, padding and margins</h3>
364 * <p>
365 * The size of a view is expressed with a width and a height. A view actually
366 * possess two pairs of width and height values.
367 * </p>
368 *
369 * <p>
370 * The first pair is known as <em>measured width</em> and
371 * <em>measured height</em>. These dimensions define how big a view wants to be
372 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
373 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
374 * and {@link #getMeasuredHeight()}.
375 * </p>
376 *
377 * <p>
378 * The second pair is simply known as <em>width</em> and <em>height</em>, or
379 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
380 * dimensions define the actual size of the view on screen, at drawing time and
381 * after layout. These values may, but do not have to, be different from the
382 * measured width and height. The width and height can be obtained by calling
383 * {@link #getWidth()} and {@link #getHeight()}.
384 * </p>
385 *
386 * <p>
387 * To measure its dimensions, a view takes into account its padding. The padding
388 * is expressed in pixels for the left, top, right and bottom parts of the view.
389 * Padding can be used to offset the content of the view by a specific amount of
390 * pixels. For instance, a left padding of 2 will push the view's content by
391 * 2 pixels to the right of the left edge. Padding can be set using the
392 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
393 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
394 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
395 * {@link #getPaddingEnd()}.
396 * </p>
397 *
398 * <p>
399 * Even though a view can define a padding, it does not provide any support for
400 * margins. However, view groups provide such a support. Refer to
401 * {@link android.view.ViewGroup} and
402 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
403 * </p>
404 *
405 * <a name="Layout"></a>
406 * <h3>Layout</h3>
407 * <p>
408 * Layout is a two pass process: a measure pass and a layout pass. The measuring
409 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
410 * of the view tree. Each view pushes dimension specifications down the tree
411 * during the recursion. At the end of the measure pass, every view has stored
412 * its measurements. The second pass happens in
413 * {@link #layout(int,int,int,int)} and is also top-down. During
414 * this pass each parent is responsible for positioning all of its children
415 * using the sizes computed in the measure pass.
416 * </p>
417 *
418 * <p>
419 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
420 * {@link #getMeasuredHeight()} values must be set, along with those for all of
421 * that view's descendants. A view's measured width and measured height values
422 * must respect the constraints imposed by the view's parents. This guarantees
423 * that at the end of the measure pass, all parents accept all of their
424 * children's measurements. A parent view may call measure() more than once on
425 * its children. For example, the parent may measure each child once with
426 * unspecified dimensions to find out how big they want to be, then call
427 * measure() on them again with actual numbers if the sum of all the children's
428 * unconstrained sizes is too big or too small.
429 * </p>
430 *
431 * <p>
432 * The measure pass uses two classes to communicate dimensions. The
433 * {@link MeasureSpec} class is used by views to tell their parents how they
434 * want to be measured and positioned. The base LayoutParams class just
435 * describes how big the view wants to be for both width and height. For each
436 * dimension, it can specify one of:
437 * <ul>
438 * <li> an exact number
439 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
440 * (minus padding)
441 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
442 * enclose its content (plus padding).
443 * </ul>
444 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
445 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
446 * an X and Y value.
447 * </p>
448 *
449 * <p>
450 * MeasureSpecs are used to push requirements down the tree from parent to
451 * child. A MeasureSpec can be in one of three modes:
452 * <ul>
453 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
454 * of a child view. For example, a LinearLayout may call measure() on its child
455 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
456 * tall the child view wants to be given a width of 240 pixels.
457 * <li>EXACTLY: This is used by the parent to impose an exact size on the
458 * child. The child must use this size, and guarantee that all of its
459 * descendants will fit within this size.
460 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
461 * child. The child must guarantee that it and all of its descendants will fit
462 * within this size.
463 * </ul>
464 * </p>
465 *
466 * <p>
467 * To initiate a layout, call {@link #requestLayout}. This method is typically
468 * called by a view on itself when it believes that is can no longer fit within
469 * its current bounds.
470 * </p>
471 *
472 * <a name="Drawing"></a>
473 * <h3>Drawing</h3>
474 * <p>
475 * Drawing is handled by walking the tree and recording the drawing commands of
476 * any View that needs to update. After this, the drawing commands of the
477 * entire tree are issued to screen, clipped to the newly damaged area.
478 * </p>
479 *
480 * <p>
481 * The tree is largely recorded and drawn in order, with parents drawn before
482 * (i.e., behind) their children, with siblings drawn in the order they appear
483 * in the tree. If you set a background drawable for a View, then the View will
484 * draw it before calling back to its <code>onDraw()</code> method. The child
485 * drawing order can be overridden with
486 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
487 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
488 * </p>
489 *
490 * <p>
491 * To force a view to draw, call {@link #invalidate()}.
492 * </p>
493 *
494 * <a name="EventHandlingThreading"></a>
495 * <h3>Event Handling and Threading</h3>
496 * <p>
497 * The basic cycle of a view is as follows:
498 * <ol>
499 * <li>An event comes in and is dispatched to the appropriate view. The view
500 * handles the event and notifies any listeners.</li>
501 * <li>If in the course of processing the event, the view's bounds may need
502 * to be changed, the view will call {@link #requestLayout()}.</li>
503 * <li>Similarly, if in the course of processing the event the view's appearance
504 * may need to be changed, the view will call {@link #invalidate()}.</li>
505 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
506 * the framework will take care of measuring, laying out, and drawing the tree
507 * as appropriate.</li>
508 * </ol>
509 * </p>
510 *
511 * <p><em>Note: The entire view tree is single threaded. You must always be on
512 * the UI thread when calling any method on any view.</em>
513 * If you are doing work on other threads and want to update the state of a view
514 * from that thread, you should use a {@link Handler}.
515 * </p>
516 *
517 * <a name="FocusHandling"></a>
518 * <h3>Focus Handling</h3>
519 * <p>
520 * The framework will handle routine focus movement in response to user input.
521 * This includes changing the focus as views are removed or hidden, or as new
522 * views become available. Views indicate their willingness to take focus
523 * through the {@link #isFocusable} method. To change whether a view can take
524 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
525 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
526 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
527 * </p>
528 * <p>
529 * Focus movement is based on an algorithm which finds the nearest neighbor in a
530 * given direction. In rare cases, the default algorithm may not match the
531 * intended behavior of the developer. In these situations, you can provide
532 * explicit overrides by using these XML attributes in the layout file:
533 * <pre>
534 * nextFocusDown
535 * nextFocusLeft
536 * nextFocusRight
537 * nextFocusUp
538 * </pre>
539 * </p>
540 *
541 *
542 * <p>
543 * To get a particular view to take focus, call {@link #requestFocus()}.
544 * </p>
545 *
546 * <a name="TouchMode"></a>
547 * <h3>Touch Mode</h3>
548 * <p>
549 * When a user is navigating a user interface via directional keys such as a D-pad, it is
550 * necessary to give focus to actionable items such as buttons so the user can see
551 * what will take input.  If the device has touch capabilities, however, and the user
552 * begins interacting with the interface by touching it, it is no longer necessary to
553 * always highlight, or give focus to, a particular view.  This motivates a mode
554 * for interaction named 'touch mode'.
555 * </p>
556 * <p>
557 * For a touch capable device, once the user touches the screen, the device
558 * will enter touch mode.  From this point onward, only views for which
559 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
560 * Other views that are touchable, like buttons, will not take focus when touched; they will
561 * only fire the on click listeners.
562 * </p>
563 * <p>
564 * Any time a user hits a directional key, such as a D-pad direction, the view device will
565 * exit touch mode, and find a view to take focus, so that the user may resume interacting
566 * with the user interface without touching the screen again.
567 * </p>
568 * <p>
569 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
570 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
571 * </p>
572 *
573 * <a name="Scrolling"></a>
574 * <h3>Scrolling</h3>
575 * <p>
576 * The framework provides basic support for views that wish to internally
577 * scroll their content. This includes keeping track of the X and Y scroll
578 * offset as well as mechanisms for drawing scrollbars. See
579 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
580 * {@link #awakenScrollBars()} for more details.
581 * </p>
582 *
583 * <a name="Tags"></a>
584 * <h3>Tags</h3>
585 * <p>
586 * Unlike IDs, tags are not used to identify views. Tags are essentially an
587 * extra piece of information that can be associated with a view. They are most
588 * often used as a convenience to store data related to views in the views
589 * themselves rather than by putting them in a separate structure.
590 * </p>
591 * <p>
592 * Tags may be specified with character sequence values in layout XML as either
593 * a single tag using the {@link android.R.styleable#View_tag android:tag}
594 * attribute or multiple tags using the {@code <tag>} child element:
595 * <pre>
596 *     &ltView ...
597 *           android:tag="@string/mytag_value" /&gt;
598 *     &ltView ...&gt;
599 *         &lttag android:id="@+id/mytag"
600 *              android:value="@string/mytag_value" /&gt;
601 *     &lt/View>
602 * </pre>
603 * </p>
604 * <p>
605 * Tags may also be specified with arbitrary objects from code using
606 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
607 * </p>
608 *
609 * <a name="Themes"></a>
610 * <h3>Themes</h3>
611 * <p>
612 * By default, Views are created using the theme of the Context object supplied
613 * to their constructor; however, a different theme may be specified by using
614 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
615 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
616 * code.
617 * </p>
618 * <p>
619 * When the {@link android.R.styleable#View_theme android:theme} attribute is
620 * used in XML, the specified theme is applied on top of the inflation
621 * context's theme (see {@link LayoutInflater}) and used for the view itself as
622 * well as any child elements.
623 * </p>
624 * <p>
625 * In the following example, both views will be created using the Material dark
626 * color scheme; however, because an overlay theme is used which only defines a
627 * subset of attributes, the value of
628 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
629 * the inflation context's theme (e.g. the Activity theme) will be preserved.
630 * <pre>
631 *     &ltLinearLayout
632 *             ...
633 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
634 *         &ltView ...&gt;
635 *     &lt/LinearLayout&gt;
636 * </pre>
637 * </p>
638 *
639 * <a name="Properties"></a>
640 * <h3>Properties</h3>
641 * <p>
642 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
643 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
644 * available both in the {@link Property} form as well as in similarly-named setter/getter
645 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
646 * be used to set persistent state associated with these rendering-related properties on the view.
647 * The properties and methods can also be used in conjunction with
648 * {@link android.animation.Animator Animator}-based animations, described more in the
649 * <a href="#Animation">Animation</a> section.
650 * </p>
651 *
652 * <a name="Animation"></a>
653 * <h3>Animation</h3>
654 * <p>
655 * Starting with Android 3.0, the preferred way of animating views is to use the
656 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
657 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
658 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
659 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
660 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
661 * makes animating these View properties particularly easy and efficient.
662 * </p>
663 * <p>
664 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
665 * You can attach an {@link Animation} object to a view using
666 * {@link #setAnimation(Animation)} or
667 * {@link #startAnimation(Animation)}. The animation can alter the scale,
668 * rotation, translation and alpha of a view over time. If the animation is
669 * attached to a view that has children, the animation will affect the entire
670 * subtree rooted by that node. When an animation is started, the framework will
671 * take care of redrawing the appropriate views until the animation completes.
672 * </p>
673 *
674 * <a name="Security"></a>
675 * <h3>Security</h3>
676 * <p>
677 * Sometimes it is essential that an application be able to verify that an action
678 * is being performed with the full knowledge and consent of the user, such as
679 * granting a permission request, making a purchase or clicking on an advertisement.
680 * Unfortunately, a malicious application could try to spoof the user into
681 * performing these actions, unaware, by concealing the intended purpose of the view.
682 * As a remedy, the framework offers a touch filtering mechanism that can be used to
683 * improve the security of views that provide access to sensitive functionality.
684 * </p><p>
685 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
686 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
687 * will discard touches that are received whenever the view's window is obscured by
688 * another visible window.  As a result, the view will not receive touches whenever a
689 * toast, dialog or other window appears above the view's window.
690 * </p><p>
691 * For more fine-grained control over security, consider overriding the
692 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
693 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
694 * </p>
695 *
696 * @attr ref android.R.styleable#View_alpha
697 * @attr ref android.R.styleable#View_background
698 * @attr ref android.R.styleable#View_clickable
699 * @attr ref android.R.styleable#View_contentDescription
700 * @attr ref android.R.styleable#View_drawingCacheQuality
701 * @attr ref android.R.styleable#View_duplicateParentState
702 * @attr ref android.R.styleable#View_id
703 * @attr ref android.R.styleable#View_requiresFadingEdge
704 * @attr ref android.R.styleable#View_fadeScrollbars
705 * @attr ref android.R.styleable#View_fadingEdgeLength
706 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
707 * @attr ref android.R.styleable#View_fitsSystemWindows
708 * @attr ref android.R.styleable#View_isScrollContainer
709 * @attr ref android.R.styleable#View_focusable
710 * @attr ref android.R.styleable#View_focusableInTouchMode
711 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
712 * @attr ref android.R.styleable#View_keepScreenOn
713 * @attr ref android.R.styleable#View_layerType
714 * @attr ref android.R.styleable#View_layoutDirection
715 * @attr ref android.R.styleable#View_longClickable
716 * @attr ref android.R.styleable#View_minHeight
717 * @attr ref android.R.styleable#View_minWidth
718 * @attr ref android.R.styleable#View_nextFocusDown
719 * @attr ref android.R.styleable#View_nextFocusLeft
720 * @attr ref android.R.styleable#View_nextFocusRight
721 * @attr ref android.R.styleable#View_nextFocusUp
722 * @attr ref android.R.styleable#View_onClick
723 * @attr ref android.R.styleable#View_padding
724 * @attr ref android.R.styleable#View_paddingBottom
725 * @attr ref android.R.styleable#View_paddingLeft
726 * @attr ref android.R.styleable#View_paddingRight
727 * @attr ref android.R.styleable#View_paddingTop
728 * @attr ref android.R.styleable#View_paddingStart
729 * @attr ref android.R.styleable#View_paddingEnd
730 * @attr ref android.R.styleable#View_saveEnabled
731 * @attr ref android.R.styleable#View_rotation
732 * @attr ref android.R.styleable#View_rotationX
733 * @attr ref android.R.styleable#View_rotationY
734 * @attr ref android.R.styleable#View_scaleX
735 * @attr ref android.R.styleable#View_scaleY
736 * @attr ref android.R.styleable#View_scrollX
737 * @attr ref android.R.styleable#View_scrollY
738 * @attr ref android.R.styleable#View_scrollbarSize
739 * @attr ref android.R.styleable#View_scrollbarStyle
740 * @attr ref android.R.styleable#View_scrollbars
741 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
742 * @attr ref android.R.styleable#View_scrollbarFadeDuration
743 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
744 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
745 * @attr ref android.R.styleable#View_scrollbarThumbVertical
746 * @attr ref android.R.styleable#View_scrollbarTrackVertical
747 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
748 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
749 * @attr ref android.R.styleable#View_stateListAnimator
750 * @attr ref android.R.styleable#View_transitionName
751 * @attr ref android.R.styleable#View_soundEffectsEnabled
752 * @attr ref android.R.styleable#View_tag
753 * @attr ref android.R.styleable#View_textAlignment
754 * @attr ref android.R.styleable#View_textDirection
755 * @attr ref android.R.styleable#View_transformPivotX
756 * @attr ref android.R.styleable#View_transformPivotY
757 * @attr ref android.R.styleable#View_translationX
758 * @attr ref android.R.styleable#View_translationY
759 * @attr ref android.R.styleable#View_translationZ
760 * @attr ref android.R.styleable#View_visibility
761 * @attr ref android.R.styleable#View_theme
762 *
763 * @see android.view.ViewGroup
764 */
765@UiThread
766public class View implements Drawable.Callback, KeyEvent.Callback,
767        AccessibilityEventSource {
768    private static final boolean DBG = false;
769
770    /** @hide */
771    public static boolean DEBUG_DRAW = false;
772
773    /**
774     * The logging tag used by this class with android.util.Log.
775     */
776    protected static final String VIEW_LOG_TAG = "View";
777
778    /**
779     * When set to true, apps will draw debugging information about their layouts.
780     *
781     * @hide
782     */
783    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
784
785    /**
786     * When set to true, this view will save its attribute data.
787     *
788     * @hide
789     */
790    public static boolean mDebugViewAttributes = false;
791
792    /**
793     * Used to mark a View that has no ID.
794     */
795    public static final int NO_ID = -1;
796
797    /**
798     * Signals that compatibility booleans have been initialized according to
799     * target SDK versions.
800     */
801    private static boolean sCompatibilityDone = false;
802
803    /**
804     * Use the old (broken) way of building MeasureSpecs.
805     */
806    private static boolean sUseBrokenMakeMeasureSpec = false;
807
808    /**
809     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
810     */
811    static boolean sUseZeroUnspecifiedMeasureSpec = false;
812
813    /**
814     * Ignore any optimizations using the measure cache.
815     */
816    private static boolean sIgnoreMeasureCache = false;
817
818    /**
819     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
820     */
821    private static boolean sAlwaysRemeasureExactly = false;
822
823    /**
824     * Relax constraints around whether setLayoutParams() must be called after
825     * modifying the layout params.
826     */
827    private static boolean sLayoutParamsAlwaysChanged = false;
828
829    /**
830     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
831     * without throwing
832     */
833    static boolean sTextureViewIgnoresDrawableSetters = false;
834
835    /**
836     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
837     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
838     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
839     * check is implemented for backwards compatibility.
840     *
841     * {@hide}
842     */
843    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
844
845    /**
846     * Prior to N, when drag enters into child of a view that has already received an
847     * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
848     * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
849     * false from its event handler for these events.
850     * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
851     * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
852     * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
853     */
854    static boolean sCascadedDragDrop;
855
856    /**
857     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
858     * calling setFlags.
859     */
860    private static final int NOT_FOCUSABLE = 0x00000000;
861
862    /**
863     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
864     * setFlags.
865     */
866    private static final int FOCUSABLE = 0x00000001;
867
868    /**
869     * Mask for use with setFlags indicating bits used for focus.
870     */
871    private static final int FOCUSABLE_MASK = 0x00000001;
872
873    /**
874     * This view will adjust its padding to fit sytem windows (e.g. status bar)
875     */
876    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
877
878    /** @hide */
879    @IntDef({VISIBLE, INVISIBLE, GONE})
880    @Retention(RetentionPolicy.SOURCE)
881    public @interface Visibility {}
882
883    /**
884     * This view is visible.
885     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
886     * android:visibility}.
887     */
888    public static final int VISIBLE = 0x00000000;
889
890    /**
891     * This view is invisible, but it still takes up space for layout purposes.
892     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
893     * android:visibility}.
894     */
895    public static final int INVISIBLE = 0x00000004;
896
897    /**
898     * This view is invisible, and it doesn't take any space for layout
899     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
900     * android:visibility}.
901     */
902    public static final int GONE = 0x00000008;
903
904    /**
905     * Mask for use with setFlags indicating bits used for visibility.
906     * {@hide}
907     */
908    static final int VISIBILITY_MASK = 0x0000000C;
909
910    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
911
912    /**
913     * This view is enabled. Interpretation varies by subclass.
914     * Use with ENABLED_MASK when calling setFlags.
915     * {@hide}
916     */
917    static final int ENABLED = 0x00000000;
918
919    /**
920     * This view is disabled. Interpretation varies by subclass.
921     * Use with ENABLED_MASK when calling setFlags.
922     * {@hide}
923     */
924    static final int DISABLED = 0x00000020;
925
926   /**
927    * Mask for use with setFlags indicating bits used for indicating whether
928    * this view is enabled
929    * {@hide}
930    */
931    static final int ENABLED_MASK = 0x00000020;
932
933    /**
934     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
935     * called and further optimizations will be performed. It is okay to have
936     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
937     * {@hide}
938     */
939    static final int WILL_NOT_DRAW = 0x00000080;
940
941    /**
942     * Mask for use with setFlags indicating bits used for indicating whether
943     * this view is will draw
944     * {@hide}
945     */
946    static final int DRAW_MASK = 0x00000080;
947
948    /**
949     * <p>This view doesn't show scrollbars.</p>
950     * {@hide}
951     */
952    static final int SCROLLBARS_NONE = 0x00000000;
953
954    /**
955     * <p>This view shows horizontal scrollbars.</p>
956     * {@hide}
957     */
958    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
959
960    /**
961     * <p>This view shows vertical scrollbars.</p>
962     * {@hide}
963     */
964    static final int SCROLLBARS_VERTICAL = 0x00000200;
965
966    /**
967     * <p>Mask for use with setFlags indicating bits used for indicating which
968     * scrollbars are enabled.</p>
969     * {@hide}
970     */
971    static final int SCROLLBARS_MASK = 0x00000300;
972
973    /**
974     * Indicates that the view should filter touches when its window is obscured.
975     * Refer to the class comments for more information about this security feature.
976     * {@hide}
977     */
978    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
979
980    /**
981     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
982     * that they are optional and should be skipped if the window has
983     * requested system UI flags that ignore those insets for layout.
984     */
985    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
986
987    /**
988     * <p>This view doesn't show fading edges.</p>
989     * {@hide}
990     */
991    static final int FADING_EDGE_NONE = 0x00000000;
992
993    /**
994     * <p>This view shows horizontal fading edges.</p>
995     * {@hide}
996     */
997    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
998
999    /**
1000     * <p>This view shows vertical fading edges.</p>
1001     * {@hide}
1002     */
1003    static final int FADING_EDGE_VERTICAL = 0x00002000;
1004
1005    /**
1006     * <p>Mask for use with setFlags indicating bits used for indicating which
1007     * fading edges are enabled.</p>
1008     * {@hide}
1009     */
1010    static final int FADING_EDGE_MASK = 0x00003000;
1011
1012    /**
1013     * <p>Indicates this view can be clicked. When clickable, a View reacts
1014     * to clicks by notifying the OnClickListener.<p>
1015     * {@hide}
1016     */
1017    static final int CLICKABLE = 0x00004000;
1018
1019    /**
1020     * <p>Indicates this view is caching its drawing into a bitmap.</p>
1021     * {@hide}
1022     */
1023    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1024
1025    /**
1026     * <p>Indicates that no icicle should be saved for this view.<p>
1027     * {@hide}
1028     */
1029    static final int SAVE_DISABLED = 0x000010000;
1030
1031    /**
1032     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1033     * property.</p>
1034     * {@hide}
1035     */
1036    static final int SAVE_DISABLED_MASK = 0x000010000;
1037
1038    /**
1039     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1040     * {@hide}
1041     */
1042    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1043
1044    /**
1045     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1046     * {@hide}
1047     */
1048    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1049
1050    /** @hide */
1051    @Retention(RetentionPolicy.SOURCE)
1052    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1053    public @interface DrawingCacheQuality {}
1054
1055    /**
1056     * <p>Enables low quality mode for the drawing cache.</p>
1057     */
1058    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1059
1060    /**
1061     * <p>Enables high quality mode for the drawing cache.</p>
1062     */
1063    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1064
1065    /**
1066     * <p>Enables automatic quality mode for the drawing cache.</p>
1067     */
1068    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1069
1070    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1071            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1072    };
1073
1074    /**
1075     * <p>Mask for use with setFlags indicating bits used for the cache
1076     * quality property.</p>
1077     * {@hide}
1078     */
1079    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1080
1081    /**
1082     * <p>
1083     * Indicates this view can be long clicked. When long clickable, a View
1084     * reacts to long clicks by notifying the OnLongClickListener or showing a
1085     * context menu.
1086     * </p>
1087     * {@hide}
1088     */
1089    static final int LONG_CLICKABLE = 0x00200000;
1090
1091    /**
1092     * <p>Indicates that this view gets its drawable states from its direct parent
1093     * and ignores its original internal states.</p>
1094     *
1095     * @hide
1096     */
1097    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1098
1099    /**
1100     * <p>
1101     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1102     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1103     * OnContextClickListener.
1104     * </p>
1105     * {@hide}
1106     */
1107    static final int CONTEXT_CLICKABLE = 0x00800000;
1108
1109
1110    /** @hide */
1111    @IntDef({
1112        SCROLLBARS_INSIDE_OVERLAY,
1113        SCROLLBARS_INSIDE_INSET,
1114        SCROLLBARS_OUTSIDE_OVERLAY,
1115        SCROLLBARS_OUTSIDE_INSET
1116    })
1117    @Retention(RetentionPolicy.SOURCE)
1118    public @interface ScrollBarStyle {}
1119
1120    /**
1121     * The scrollbar style to display the scrollbars inside the content area,
1122     * without increasing the padding. The scrollbars will be overlaid with
1123     * translucency on the view's content.
1124     */
1125    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1126
1127    /**
1128     * The scrollbar style to display the scrollbars inside the padded area,
1129     * increasing the padding of the view. The scrollbars will not overlap the
1130     * content area of the view.
1131     */
1132    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1133
1134    /**
1135     * The scrollbar style to display the scrollbars at the edge of the view,
1136     * without increasing the padding. The scrollbars will be overlaid with
1137     * translucency.
1138     */
1139    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1140
1141    /**
1142     * The scrollbar style to display the scrollbars at the edge of the view,
1143     * increasing the padding of the view. The scrollbars will only overlap the
1144     * background, if any.
1145     */
1146    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1147
1148    /**
1149     * Mask to check if the scrollbar style is overlay or inset.
1150     * {@hide}
1151     */
1152    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1153
1154    /**
1155     * Mask to check if the scrollbar style is inside or outside.
1156     * {@hide}
1157     */
1158    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1159
1160    /**
1161     * Mask for scrollbar style.
1162     * {@hide}
1163     */
1164    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1165
1166    /**
1167     * View flag indicating that the screen should remain on while the
1168     * window containing this view is visible to the user.  This effectively
1169     * takes care of automatically setting the WindowManager's
1170     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1171     */
1172    public static final int KEEP_SCREEN_ON = 0x04000000;
1173
1174    /**
1175     * View flag indicating whether this view should have sound effects enabled
1176     * for events such as clicking and touching.
1177     */
1178    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1179
1180    /**
1181     * View flag indicating whether this view should have haptic feedback
1182     * enabled for events such as long presses.
1183     */
1184    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1185
1186    /**
1187     * <p>Indicates that the view hierarchy should stop saving state when
1188     * it reaches this view.  If state saving is initiated immediately at
1189     * the view, it will be allowed.
1190     * {@hide}
1191     */
1192    static final int PARENT_SAVE_DISABLED = 0x20000000;
1193
1194    /**
1195     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1196     * {@hide}
1197     */
1198    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1199
1200    private static Paint sDebugPaint;
1201
1202    /**
1203     * <p>Indicates this view can display a tooltip on hover or long press.</p>
1204     * {@hide}
1205     */
1206    static final int TOOLTIP = 0x40000000;
1207
1208    /** @hide */
1209    @IntDef(flag = true,
1210            value = {
1211                FOCUSABLES_ALL,
1212                FOCUSABLES_TOUCH_MODE
1213            })
1214    @Retention(RetentionPolicy.SOURCE)
1215    public @interface FocusableMode {}
1216
1217    /**
1218     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1219     * should add all focusable Views regardless if they are focusable in touch mode.
1220     */
1221    public static final int FOCUSABLES_ALL = 0x00000000;
1222
1223    /**
1224     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1225     * should add only Views focusable in touch mode.
1226     */
1227    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1228
1229    /** @hide */
1230    @IntDef({
1231            FOCUS_BACKWARD,
1232            FOCUS_FORWARD,
1233            FOCUS_LEFT,
1234            FOCUS_UP,
1235            FOCUS_RIGHT,
1236            FOCUS_DOWN
1237    })
1238    @Retention(RetentionPolicy.SOURCE)
1239    public @interface FocusDirection {}
1240
1241    /** @hide */
1242    @IntDef({
1243            FOCUS_LEFT,
1244            FOCUS_UP,
1245            FOCUS_RIGHT,
1246            FOCUS_DOWN
1247    })
1248    @Retention(RetentionPolicy.SOURCE)
1249    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1250
1251    /** @hide */
1252    @IntDef({
1253            KEYBOARD_NAVIGATION_GROUP_CLUSTER,
1254            KEYBOARD_NAVIGATION_GROUP_SECTION
1255    })
1256    @Retention(RetentionPolicy.SOURCE)
1257    public @interface KeyboardNavigationGroupType {}
1258
1259    /**
1260     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1261     * item.
1262     */
1263    public static final int FOCUS_BACKWARD = 0x00000001;
1264
1265    /**
1266     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1267     * item.
1268     */
1269    public static final int FOCUS_FORWARD = 0x00000002;
1270
1271    /**
1272     * Use with {@link #focusSearch(int)}. Move focus to the left.
1273     */
1274    public static final int FOCUS_LEFT = 0x00000011;
1275
1276    /**
1277     * Use with {@link #focusSearch(int)}. Move focus up.
1278     */
1279    public static final int FOCUS_UP = 0x00000021;
1280
1281    /**
1282     * Use with {@link #focusSearch(int)}. Move focus to the right.
1283     */
1284    public static final int FOCUS_RIGHT = 0x00000042;
1285
1286    /**
1287     * Use with {@link #focusSearch(int)}. Move focus down.
1288     */
1289    public static final int FOCUS_DOWN = 0x00000082;
1290
1291    /**
1292     * Use with {@link #keyboardNavigationGroupSearch(int, View, int)}. Search for a keyboard
1293     * navigation cluster.
1294     */
1295    public static final int KEYBOARD_NAVIGATION_GROUP_CLUSTER = 1;
1296
1297    /**
1298     * Use with {@link #keyboardNavigationGroupSearch(int, View, int)}. Search for a keyboard
1299     * navigation section.
1300     */
1301    public static final int KEYBOARD_NAVIGATION_GROUP_SECTION = 2;
1302
1303    /**
1304     * Bits of {@link #getMeasuredWidthAndState()} and
1305     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1306     */
1307    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1308
1309    /**
1310     * Bits of {@link #getMeasuredWidthAndState()} and
1311     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1312     */
1313    public static final int MEASURED_STATE_MASK = 0xff000000;
1314
1315    /**
1316     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1317     * for functions that combine both width and height into a single int,
1318     * such as {@link #getMeasuredState()} and the childState argument of
1319     * {@link #resolveSizeAndState(int, int, int)}.
1320     */
1321    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1322
1323    /**
1324     * Bit of {@link #getMeasuredWidthAndState()} and
1325     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1326     * is smaller that the space the view would like to have.
1327     */
1328    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1329
1330    /**
1331     * Base View state sets
1332     */
1333    // Singles
1334    /**
1335     * Indicates the view has no states set. States are used with
1336     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1337     * view depending on its state.
1338     *
1339     * @see android.graphics.drawable.Drawable
1340     * @see #getDrawableState()
1341     */
1342    protected static final int[] EMPTY_STATE_SET;
1343    /**
1344     * Indicates the view is enabled. States are used with
1345     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1346     * view depending on its state.
1347     *
1348     * @see android.graphics.drawable.Drawable
1349     * @see #getDrawableState()
1350     */
1351    protected static final int[] ENABLED_STATE_SET;
1352    /**
1353     * Indicates the view is focused. States are used with
1354     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1355     * view depending on its state.
1356     *
1357     * @see android.graphics.drawable.Drawable
1358     * @see #getDrawableState()
1359     */
1360    protected static final int[] FOCUSED_STATE_SET;
1361    /**
1362     * Indicates the view is selected. States are used with
1363     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1364     * view depending on its state.
1365     *
1366     * @see android.graphics.drawable.Drawable
1367     * @see #getDrawableState()
1368     */
1369    protected static final int[] SELECTED_STATE_SET;
1370    /**
1371     * Indicates the view is pressed. States are used with
1372     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1373     * view depending on its state.
1374     *
1375     * @see android.graphics.drawable.Drawable
1376     * @see #getDrawableState()
1377     */
1378    protected static final int[] PRESSED_STATE_SET;
1379    /**
1380     * Indicates the view's window has focus. States are used with
1381     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1382     * view depending on its state.
1383     *
1384     * @see android.graphics.drawable.Drawable
1385     * @see #getDrawableState()
1386     */
1387    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1388    // Doubles
1389    /**
1390     * Indicates the view is enabled and has the focus.
1391     *
1392     * @see #ENABLED_STATE_SET
1393     * @see #FOCUSED_STATE_SET
1394     */
1395    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1396    /**
1397     * Indicates the view is enabled and selected.
1398     *
1399     * @see #ENABLED_STATE_SET
1400     * @see #SELECTED_STATE_SET
1401     */
1402    protected static final int[] ENABLED_SELECTED_STATE_SET;
1403    /**
1404     * Indicates the view is enabled and that its window has focus.
1405     *
1406     * @see #ENABLED_STATE_SET
1407     * @see #WINDOW_FOCUSED_STATE_SET
1408     */
1409    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1410    /**
1411     * Indicates the view is focused and selected.
1412     *
1413     * @see #FOCUSED_STATE_SET
1414     * @see #SELECTED_STATE_SET
1415     */
1416    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1417    /**
1418     * Indicates the view has the focus and that its window has the focus.
1419     *
1420     * @see #FOCUSED_STATE_SET
1421     * @see #WINDOW_FOCUSED_STATE_SET
1422     */
1423    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1424    /**
1425     * Indicates the view is selected and that its window has the focus.
1426     *
1427     * @see #SELECTED_STATE_SET
1428     * @see #WINDOW_FOCUSED_STATE_SET
1429     */
1430    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1431    // Triples
1432    /**
1433     * Indicates the view is enabled, focused and selected.
1434     *
1435     * @see #ENABLED_STATE_SET
1436     * @see #FOCUSED_STATE_SET
1437     * @see #SELECTED_STATE_SET
1438     */
1439    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1440    /**
1441     * Indicates the view is enabled, focused and its window has the focus.
1442     *
1443     * @see #ENABLED_STATE_SET
1444     * @see #FOCUSED_STATE_SET
1445     * @see #WINDOW_FOCUSED_STATE_SET
1446     */
1447    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1448    /**
1449     * Indicates the view is enabled, selected and its window has the focus.
1450     *
1451     * @see #ENABLED_STATE_SET
1452     * @see #SELECTED_STATE_SET
1453     * @see #WINDOW_FOCUSED_STATE_SET
1454     */
1455    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1456    /**
1457     * Indicates the view is focused, selected and its window has the focus.
1458     *
1459     * @see #FOCUSED_STATE_SET
1460     * @see #SELECTED_STATE_SET
1461     * @see #WINDOW_FOCUSED_STATE_SET
1462     */
1463    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1464    /**
1465     * Indicates the view is enabled, focused, selected and its window
1466     * has the focus.
1467     *
1468     * @see #ENABLED_STATE_SET
1469     * @see #FOCUSED_STATE_SET
1470     * @see #SELECTED_STATE_SET
1471     * @see #WINDOW_FOCUSED_STATE_SET
1472     */
1473    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1474    /**
1475     * Indicates the view is pressed and its window has the focus.
1476     *
1477     * @see #PRESSED_STATE_SET
1478     * @see #WINDOW_FOCUSED_STATE_SET
1479     */
1480    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1481    /**
1482     * Indicates the view is pressed and selected.
1483     *
1484     * @see #PRESSED_STATE_SET
1485     * @see #SELECTED_STATE_SET
1486     */
1487    protected static final int[] PRESSED_SELECTED_STATE_SET;
1488    /**
1489     * Indicates the view is pressed, selected and its window has the focus.
1490     *
1491     * @see #PRESSED_STATE_SET
1492     * @see #SELECTED_STATE_SET
1493     * @see #WINDOW_FOCUSED_STATE_SET
1494     */
1495    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1496    /**
1497     * Indicates the view is pressed and focused.
1498     *
1499     * @see #PRESSED_STATE_SET
1500     * @see #FOCUSED_STATE_SET
1501     */
1502    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1503    /**
1504     * Indicates the view is pressed, focused and its window has the focus.
1505     *
1506     * @see #PRESSED_STATE_SET
1507     * @see #FOCUSED_STATE_SET
1508     * @see #WINDOW_FOCUSED_STATE_SET
1509     */
1510    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1511    /**
1512     * Indicates the view is pressed, focused and selected.
1513     *
1514     * @see #PRESSED_STATE_SET
1515     * @see #SELECTED_STATE_SET
1516     * @see #FOCUSED_STATE_SET
1517     */
1518    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1519    /**
1520     * Indicates the view is pressed, focused, selected and its window has the focus.
1521     *
1522     * @see #PRESSED_STATE_SET
1523     * @see #FOCUSED_STATE_SET
1524     * @see #SELECTED_STATE_SET
1525     * @see #WINDOW_FOCUSED_STATE_SET
1526     */
1527    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1528    /**
1529     * Indicates the view is pressed and enabled.
1530     *
1531     * @see #PRESSED_STATE_SET
1532     * @see #ENABLED_STATE_SET
1533     */
1534    protected static final int[] PRESSED_ENABLED_STATE_SET;
1535    /**
1536     * Indicates the view is pressed, enabled and its window has the focus.
1537     *
1538     * @see #PRESSED_STATE_SET
1539     * @see #ENABLED_STATE_SET
1540     * @see #WINDOW_FOCUSED_STATE_SET
1541     */
1542    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1543    /**
1544     * Indicates the view is pressed, enabled and selected.
1545     *
1546     * @see #PRESSED_STATE_SET
1547     * @see #ENABLED_STATE_SET
1548     * @see #SELECTED_STATE_SET
1549     */
1550    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1551    /**
1552     * Indicates the view is pressed, enabled, selected and its window has the
1553     * focus.
1554     *
1555     * @see #PRESSED_STATE_SET
1556     * @see #ENABLED_STATE_SET
1557     * @see #SELECTED_STATE_SET
1558     * @see #WINDOW_FOCUSED_STATE_SET
1559     */
1560    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1561    /**
1562     * Indicates the view is pressed, enabled and focused.
1563     *
1564     * @see #PRESSED_STATE_SET
1565     * @see #ENABLED_STATE_SET
1566     * @see #FOCUSED_STATE_SET
1567     */
1568    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1569    /**
1570     * Indicates the view is pressed, enabled, focused and its window has the
1571     * focus.
1572     *
1573     * @see #PRESSED_STATE_SET
1574     * @see #ENABLED_STATE_SET
1575     * @see #FOCUSED_STATE_SET
1576     * @see #WINDOW_FOCUSED_STATE_SET
1577     */
1578    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1579    /**
1580     * Indicates the view is pressed, enabled, focused and selected.
1581     *
1582     * @see #PRESSED_STATE_SET
1583     * @see #ENABLED_STATE_SET
1584     * @see #SELECTED_STATE_SET
1585     * @see #FOCUSED_STATE_SET
1586     */
1587    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1588    /**
1589     * Indicates the view is pressed, enabled, focused, selected and its window
1590     * has the focus.
1591     *
1592     * @see #PRESSED_STATE_SET
1593     * @see #ENABLED_STATE_SET
1594     * @see #SELECTED_STATE_SET
1595     * @see #FOCUSED_STATE_SET
1596     * @see #WINDOW_FOCUSED_STATE_SET
1597     */
1598    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1599
1600    static {
1601        EMPTY_STATE_SET = StateSet.get(0);
1602
1603        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1604
1605        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1606        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1607                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1608
1609        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1610        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1611                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1612        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1613                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1614        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1615                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1616                        | StateSet.VIEW_STATE_FOCUSED);
1617
1618        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1619        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1620                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1621        ENABLED_SELECTED_STATE_SET = StateSet.get(
1622                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1623        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1624                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1625                        | StateSet.VIEW_STATE_ENABLED);
1626        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1627                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1628        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1629                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1630                        | StateSet.VIEW_STATE_ENABLED);
1631        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1632                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1633                        | StateSet.VIEW_STATE_ENABLED);
1634        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1635                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1636                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1637
1638        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1639        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1640                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1641        PRESSED_SELECTED_STATE_SET = StateSet.get(
1642                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1643        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1644                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1645                        | StateSet.VIEW_STATE_PRESSED);
1646        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1647                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1648        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1649                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1650                        | StateSet.VIEW_STATE_PRESSED);
1651        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1652                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1653                        | StateSet.VIEW_STATE_PRESSED);
1654        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1655                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1656                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1657        PRESSED_ENABLED_STATE_SET = StateSet.get(
1658                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1659        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1660                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1661                        | StateSet.VIEW_STATE_PRESSED);
1662        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1663                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1664                        | StateSet.VIEW_STATE_PRESSED);
1665        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1666                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1667                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1668        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1669                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1670                        | StateSet.VIEW_STATE_PRESSED);
1671        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1672                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1673                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1674        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1675                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1676                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1677        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1678                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1679                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1680                        | StateSet.VIEW_STATE_PRESSED);
1681    }
1682
1683    /**
1684     * Accessibility event types that are dispatched for text population.
1685     */
1686    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1687            AccessibilityEvent.TYPE_VIEW_CLICKED
1688            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1689            | AccessibilityEvent.TYPE_VIEW_SELECTED
1690            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1691            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1692            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1693            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1694            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1695            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1696            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1697            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1698
1699    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
1700
1701    static final int DEBUG_CORNERS_SIZE_DIP = 8;
1702
1703    /**
1704     * Temporary Rect currently for use in setBackground().  This will probably
1705     * be extended in the future to hold our own class with more than just
1706     * a Rect. :)
1707     */
1708    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1709
1710    /**
1711     * Map used to store views' tags.
1712     */
1713    private SparseArray<Object> mKeyedTags;
1714
1715    /**
1716     * The next available accessibility id.
1717     */
1718    private static int sNextAccessibilityViewId;
1719
1720    /**
1721     * The animation currently associated with this view.
1722     * @hide
1723     */
1724    protected Animation mCurrentAnimation = null;
1725
1726    /**
1727     * Width as measured during measure pass.
1728     * {@hide}
1729     */
1730    @ViewDebug.ExportedProperty(category = "measurement")
1731    int mMeasuredWidth;
1732
1733    /**
1734     * Height as measured during measure pass.
1735     * {@hide}
1736     */
1737    @ViewDebug.ExportedProperty(category = "measurement")
1738    int mMeasuredHeight;
1739
1740    /**
1741     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1742     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1743     * its display list. This flag, used only when hw accelerated, allows us to clear the
1744     * flag while retaining this information until it's needed (at getDisplayList() time and
1745     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1746     *
1747     * {@hide}
1748     */
1749    boolean mRecreateDisplayList = false;
1750
1751    /**
1752     * The view's identifier.
1753     * {@hide}
1754     *
1755     * @see #setId(int)
1756     * @see #getId()
1757     */
1758    @IdRes
1759    @ViewDebug.ExportedProperty(resolveId = true)
1760    int mID = NO_ID;
1761
1762    /**
1763     * The stable ID of this view for accessibility purposes.
1764     */
1765    int mAccessibilityViewId = NO_ID;
1766
1767    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1768
1769    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1770
1771    /**
1772     * The view's tag.
1773     * {@hide}
1774     *
1775     * @see #setTag(Object)
1776     * @see #getTag()
1777     */
1778    protected Object mTag = null;
1779
1780    // for mPrivateFlags:
1781    /** {@hide} */
1782    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1783    /** {@hide} */
1784    static final int PFLAG_FOCUSED                     = 0x00000002;
1785    /** {@hide} */
1786    static final int PFLAG_SELECTED                    = 0x00000004;
1787    /** {@hide} */
1788    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1789    /** {@hide} */
1790    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1791    /** {@hide} */
1792    static final int PFLAG_DRAWN                       = 0x00000020;
1793    /**
1794     * When this flag is set, this view is running an animation on behalf of its
1795     * children and should therefore not cancel invalidate requests, even if they
1796     * lie outside of this view's bounds.
1797     *
1798     * {@hide}
1799     */
1800    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1801    /** {@hide} */
1802    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1803    /** {@hide} */
1804    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1805    /** {@hide} */
1806    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1807    /** {@hide} */
1808    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1809    /** {@hide} */
1810    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1811    /** {@hide} */
1812    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1813
1814    private static final int PFLAG_PRESSED             = 0x00004000;
1815
1816    /** {@hide} */
1817    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1818    /**
1819     * Flag used to indicate that this view should be drawn once more (and only once
1820     * more) after its animation has completed.
1821     * {@hide}
1822     */
1823    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1824
1825    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1826
1827    /**
1828     * Indicates that the View returned true when onSetAlpha() was called and that
1829     * the alpha must be restored.
1830     * {@hide}
1831     */
1832    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1833
1834    /**
1835     * Set by {@link #setScrollContainer(boolean)}.
1836     */
1837    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1838
1839    /**
1840     * Set by {@link #setScrollContainer(boolean)}.
1841     */
1842    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1843
1844    /**
1845     * View flag indicating whether this view was invalidated (fully or partially.)
1846     *
1847     * @hide
1848     */
1849    static final int PFLAG_DIRTY                       = 0x00200000;
1850
1851    /**
1852     * View flag indicating whether this view was invalidated by an opaque
1853     * invalidate request.
1854     *
1855     * @hide
1856     */
1857    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1858
1859    /**
1860     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1861     *
1862     * @hide
1863     */
1864    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1865
1866    /**
1867     * Indicates whether the background is opaque.
1868     *
1869     * @hide
1870     */
1871    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1872
1873    /**
1874     * Indicates whether the scrollbars are opaque.
1875     *
1876     * @hide
1877     */
1878    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1879
1880    /**
1881     * Indicates whether the view is opaque.
1882     *
1883     * @hide
1884     */
1885    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1886
1887    /**
1888     * Indicates a prepressed state;
1889     * the short time between ACTION_DOWN and recognizing
1890     * a 'real' press. Prepressed is used to recognize quick taps
1891     * even when they are shorter than ViewConfiguration.getTapTimeout().
1892     *
1893     * @hide
1894     */
1895    private static final int PFLAG_PREPRESSED          = 0x02000000;
1896
1897    /**
1898     * Indicates whether the view is temporarily detached.
1899     *
1900     * @hide
1901     */
1902    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1903
1904    /**
1905     * Indicates that we should awaken scroll bars once attached
1906     *
1907     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1908     * during window attachment and it is no longer needed. Feel free to repurpose it.
1909     *
1910     * @hide
1911     */
1912    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1913
1914    /**
1915     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1916     * @hide
1917     */
1918    private static final int PFLAG_HOVERED             = 0x10000000;
1919
1920    /**
1921     * no longer needed, should be reused
1922     */
1923    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1924
1925    /** {@hide} */
1926    static final int PFLAG_ACTIVATED                   = 0x40000000;
1927
1928    /**
1929     * Indicates that this view was specifically invalidated, not just dirtied because some
1930     * child view was invalidated. The flag is used to determine when we need to recreate
1931     * a view's display list (as opposed to just returning a reference to its existing
1932     * display list).
1933     *
1934     * @hide
1935     */
1936    static final int PFLAG_INVALIDATED                 = 0x80000000;
1937
1938    /**
1939     * Masks for mPrivateFlags2, as generated by dumpFlags():
1940     *
1941     * |-------|-------|-------|-------|
1942     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1943     *                                1  PFLAG2_DRAG_HOVERED
1944     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1945     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1946     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1947     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1948     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1949     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1950     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1951     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1952     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1953     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1954     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1955     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1956     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1957     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1958     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1959     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1960     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1961     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1962     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1963     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1964     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1965     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1966     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1967     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1968     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1969     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1970     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1971     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1972     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1973     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1974     *    1                              PFLAG2_PADDING_RESOLVED
1975     *   1                               PFLAG2_DRAWABLE_RESOLVED
1976     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1977     * |-------|-------|-------|-------|
1978     */
1979
1980    /**
1981     * Indicates that this view has reported that it can accept the current drag's content.
1982     * Cleared when the drag operation concludes.
1983     * @hide
1984     */
1985    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1986
1987    /**
1988     * Indicates that this view is currently directly under the drag location in a
1989     * drag-and-drop operation involving content that it can accept.  Cleared when
1990     * the drag exits the view, or when the drag operation concludes.
1991     * @hide
1992     */
1993    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1994
1995    /** @hide */
1996    @IntDef({
1997        LAYOUT_DIRECTION_LTR,
1998        LAYOUT_DIRECTION_RTL,
1999        LAYOUT_DIRECTION_INHERIT,
2000        LAYOUT_DIRECTION_LOCALE
2001    })
2002    @Retention(RetentionPolicy.SOURCE)
2003    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2004    public @interface LayoutDir {}
2005
2006    /** @hide */
2007    @IntDef({
2008        LAYOUT_DIRECTION_LTR,
2009        LAYOUT_DIRECTION_RTL
2010    })
2011    @Retention(RetentionPolicy.SOURCE)
2012    public @interface ResolvedLayoutDir {}
2013
2014    /**
2015     * A flag to indicate that the layout direction of this view has not been defined yet.
2016     * @hide
2017     */
2018    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2019
2020    /**
2021     * Horizontal layout direction of this view is from Left to Right.
2022     * Use with {@link #setLayoutDirection}.
2023     */
2024    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2025
2026    /**
2027     * Horizontal layout direction of this view is from Right to Left.
2028     * Use with {@link #setLayoutDirection}.
2029     */
2030    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2031
2032    /**
2033     * Horizontal layout direction of this view is inherited from its parent.
2034     * Use with {@link #setLayoutDirection}.
2035     */
2036    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2037
2038    /**
2039     * Horizontal layout direction of this view is from deduced from the default language
2040     * script for the locale. Use with {@link #setLayoutDirection}.
2041     */
2042    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2043
2044    /**
2045     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2046     * @hide
2047     */
2048    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2049
2050    /**
2051     * Mask for use with private flags indicating bits used for horizontal layout direction.
2052     * @hide
2053     */
2054    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2055
2056    /**
2057     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2058     * right-to-left direction.
2059     * @hide
2060     */
2061    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2062
2063    /**
2064     * Indicates whether the view horizontal layout direction has been resolved.
2065     * @hide
2066     */
2067    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2068
2069    /**
2070     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2071     * @hide
2072     */
2073    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2074            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2075
2076    /*
2077     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2078     * flag value.
2079     * @hide
2080     */
2081    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2082            LAYOUT_DIRECTION_LTR,
2083            LAYOUT_DIRECTION_RTL,
2084            LAYOUT_DIRECTION_INHERIT,
2085            LAYOUT_DIRECTION_LOCALE
2086    };
2087
2088    /**
2089     * Default horizontal layout direction.
2090     */
2091    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2092
2093    /**
2094     * Default horizontal layout direction.
2095     * @hide
2096     */
2097    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2098
2099    /**
2100     * Text direction is inherited through {@link ViewGroup}
2101     */
2102    public static final int TEXT_DIRECTION_INHERIT = 0;
2103
2104    /**
2105     * Text direction is using "first strong algorithm". The first strong directional character
2106     * determines the paragraph direction. If there is no strong directional character, the
2107     * paragraph direction is the view's resolved layout direction.
2108     */
2109    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2110
2111    /**
2112     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2113     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2114     * If there are neither, the paragraph direction is the view's resolved layout direction.
2115     */
2116    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2117
2118    /**
2119     * Text direction is forced to LTR.
2120     */
2121    public static final int TEXT_DIRECTION_LTR = 3;
2122
2123    /**
2124     * Text direction is forced to RTL.
2125     */
2126    public static final int TEXT_DIRECTION_RTL = 4;
2127
2128    /**
2129     * Text direction is coming from the system Locale.
2130     */
2131    public static final int TEXT_DIRECTION_LOCALE = 5;
2132
2133    /**
2134     * Text direction is using "first strong algorithm". The first strong directional character
2135     * determines the paragraph direction. If there is no strong directional character, the
2136     * paragraph direction is LTR.
2137     */
2138    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2139
2140    /**
2141     * Text direction is using "first strong algorithm". The first strong directional character
2142     * determines the paragraph direction. If there is no strong directional character, the
2143     * paragraph direction is RTL.
2144     */
2145    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2146
2147    /**
2148     * Default text direction is inherited
2149     */
2150    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2151
2152    /**
2153     * Default resolved text direction
2154     * @hide
2155     */
2156    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2157
2158    /**
2159     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2160     * @hide
2161     */
2162    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2163
2164    /**
2165     * Mask for use with private flags indicating bits used for text direction.
2166     * @hide
2167     */
2168    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2169            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2170
2171    /**
2172     * Array of text direction flags for mapping attribute "textDirection" to correct
2173     * flag value.
2174     * @hide
2175     */
2176    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2177            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2178            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2179            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2180            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2181            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2182            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2183            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2184            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2185    };
2186
2187    /**
2188     * Indicates whether the view text direction has been resolved.
2189     * @hide
2190     */
2191    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2192            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2193
2194    /**
2195     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2196     * @hide
2197     */
2198    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2199
2200    /**
2201     * Mask for use with private flags indicating bits used for resolved text direction.
2202     * @hide
2203     */
2204    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2205            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2206
2207    /**
2208     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2209     * @hide
2210     */
2211    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2212            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2213
2214    /** @hide */
2215    @IntDef({
2216        TEXT_ALIGNMENT_INHERIT,
2217        TEXT_ALIGNMENT_GRAVITY,
2218        TEXT_ALIGNMENT_CENTER,
2219        TEXT_ALIGNMENT_TEXT_START,
2220        TEXT_ALIGNMENT_TEXT_END,
2221        TEXT_ALIGNMENT_VIEW_START,
2222        TEXT_ALIGNMENT_VIEW_END
2223    })
2224    @Retention(RetentionPolicy.SOURCE)
2225    public @interface TextAlignment {}
2226
2227    /**
2228     * Default text alignment. The text alignment of this View is inherited from its parent.
2229     * Use with {@link #setTextAlignment(int)}
2230     */
2231    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2232
2233    /**
2234     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2235     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2236     *
2237     * Use with {@link #setTextAlignment(int)}
2238     */
2239    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2240
2241    /**
2242     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2243     *
2244     * Use with {@link #setTextAlignment(int)}
2245     */
2246    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2247
2248    /**
2249     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2250     *
2251     * Use with {@link #setTextAlignment(int)}
2252     */
2253    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2254
2255    /**
2256     * Center the paragraph, e.g. ALIGN_CENTER.
2257     *
2258     * Use with {@link #setTextAlignment(int)}
2259     */
2260    public static final int TEXT_ALIGNMENT_CENTER = 4;
2261
2262    /**
2263     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2264     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2265     *
2266     * Use with {@link #setTextAlignment(int)}
2267     */
2268    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2269
2270    /**
2271     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2272     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2273     *
2274     * Use with {@link #setTextAlignment(int)}
2275     */
2276    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2277
2278    /**
2279     * Default text alignment is inherited
2280     */
2281    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2282
2283    /**
2284     * Default resolved text alignment
2285     * @hide
2286     */
2287    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2288
2289    /**
2290      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2291      * @hide
2292      */
2293    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2294
2295    /**
2296      * Mask for use with private flags indicating bits used for text alignment.
2297      * @hide
2298      */
2299    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2300
2301    /**
2302     * Array of text direction flags for mapping attribute "textAlignment" to correct
2303     * flag value.
2304     * @hide
2305     */
2306    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2307            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2308            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2309            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2310            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2311            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2312            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2313            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2314    };
2315
2316    /**
2317     * Indicates whether the view text alignment has been resolved.
2318     * @hide
2319     */
2320    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2321
2322    /**
2323     * Bit shift to get the resolved text alignment.
2324     * @hide
2325     */
2326    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2327
2328    /**
2329     * Mask for use with private flags indicating bits used for text alignment.
2330     * @hide
2331     */
2332    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2333            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2334
2335    /**
2336     * Indicates whether if the view text alignment has been resolved to gravity
2337     */
2338    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2339            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2340
2341    // Accessiblity constants for mPrivateFlags2
2342
2343    /**
2344     * Shift for the bits in {@link #mPrivateFlags2} related to the
2345     * "importantForAccessibility" attribute.
2346     */
2347    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2348
2349    /**
2350     * Automatically determine whether a view is important for accessibility.
2351     */
2352    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2353
2354    /**
2355     * The view is important for accessibility.
2356     */
2357    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2358
2359    /**
2360     * The view is not important for accessibility.
2361     */
2362    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2363
2364    /**
2365     * The view is not important for accessibility, nor are any of its
2366     * descendant views.
2367     */
2368    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2369
2370    /**
2371     * The default whether the view is important for accessibility.
2372     */
2373    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2374
2375    /**
2376     * Mask for obtaining the bits which specify how to determine
2377     * whether a view is important for accessibility.
2378     */
2379    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2380        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2381        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2382        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2383
2384    /**
2385     * Shift for the bits in {@link #mPrivateFlags2} related to the
2386     * "accessibilityLiveRegion" attribute.
2387     */
2388    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2389
2390    /**
2391     * Live region mode specifying that accessibility services should not
2392     * automatically announce changes to this view. This is the default live
2393     * region mode for most views.
2394     * <p>
2395     * Use with {@link #setAccessibilityLiveRegion(int)}.
2396     */
2397    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2398
2399    /**
2400     * Live region mode specifying that accessibility services should announce
2401     * changes to this view.
2402     * <p>
2403     * Use with {@link #setAccessibilityLiveRegion(int)}.
2404     */
2405    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2406
2407    /**
2408     * Live region mode specifying that accessibility services should interrupt
2409     * ongoing speech to immediately announce changes to this view.
2410     * <p>
2411     * Use with {@link #setAccessibilityLiveRegion(int)}.
2412     */
2413    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2414
2415    /**
2416     * The default whether the view is important for accessibility.
2417     */
2418    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2419
2420    /**
2421     * Mask for obtaining the bits which specify a view's accessibility live
2422     * region mode.
2423     */
2424    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2425            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2426            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2427
2428    /**
2429     * Flag indicating whether a view has accessibility focus.
2430     */
2431    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2432
2433    /**
2434     * Flag whether the accessibility state of the subtree rooted at this view changed.
2435     */
2436    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2437
2438    /**
2439     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2440     * is used to check whether later changes to the view's transform should invalidate the
2441     * view to force the quickReject test to run again.
2442     */
2443    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2444
2445    /**
2446     * Flag indicating that start/end padding has been resolved into left/right padding
2447     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2448     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2449     * during measurement. In some special cases this is required such as when an adapter-based
2450     * view measures prospective children without attaching them to a window.
2451     */
2452    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2453
2454    /**
2455     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2456     */
2457    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2458
2459    /**
2460     * Indicates that the view is tracking some sort of transient state
2461     * that the app should not need to be aware of, but that the framework
2462     * should take special care to preserve.
2463     */
2464    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2465
2466    /**
2467     * Group of bits indicating that RTL properties resolution is done.
2468     */
2469    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2470            PFLAG2_TEXT_DIRECTION_RESOLVED |
2471            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2472            PFLAG2_PADDING_RESOLVED |
2473            PFLAG2_DRAWABLE_RESOLVED;
2474
2475    // There are a couple of flags left in mPrivateFlags2
2476
2477    /* End of masks for mPrivateFlags2 */
2478
2479    /**
2480     * Masks for mPrivateFlags3, as generated by dumpFlags():
2481     *
2482     * |-------|-------|-------|-------|
2483     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2484     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2485     *                               1   PFLAG3_IS_LAID_OUT
2486     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2487     *                             1     PFLAG3_CALLED_SUPER
2488     *                            1      PFLAG3_APPLYING_INSETS
2489     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2490     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2491     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2492     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2493     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2494     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2495     *                     1             PFLAG3_SCROLL_INDICATOR_START
2496     *                    1              PFLAG3_SCROLL_INDICATOR_END
2497     *                   1               PFLAG3_ASSIST_BLOCKED
2498     *                  1                PFLAG3_CLUSTER
2499     *                 1                 PFLAG3_SECTION
2500     *                1                  PFLAG3_FINGER_DOWN
2501     *           xxxxx                   * NO LONGER NEEDED, SHOULD BE REUSED *
2502     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2503     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2504     *        1                          PFLAG3_TEMPORARY_DETACH
2505     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2506     * |-------|-------|-------|-------|
2507     */
2508
2509    /**
2510     * Flag indicating that view has a transform animation set on it. This is used to track whether
2511     * an animation is cleared between successive frames, in order to tell the associated
2512     * DisplayList to clear its animation matrix.
2513     */
2514    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2515
2516    /**
2517     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2518     * animation is cleared between successive frames, in order to tell the associated
2519     * DisplayList to restore its alpha value.
2520     */
2521    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2522
2523    /**
2524     * Flag indicating that the view has been through at least one layout since it
2525     * was last attached to a window.
2526     */
2527    static final int PFLAG3_IS_LAID_OUT = 0x4;
2528
2529    /**
2530     * Flag indicating that a call to measure() was skipped and should be done
2531     * instead when layout() is invoked.
2532     */
2533    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2534
2535    /**
2536     * Flag indicating that an overridden method correctly called down to
2537     * the superclass implementation as required by the API spec.
2538     */
2539    static final int PFLAG3_CALLED_SUPER = 0x10;
2540
2541    /**
2542     * Flag indicating that we're in the process of applying window insets.
2543     */
2544    static final int PFLAG3_APPLYING_INSETS = 0x20;
2545
2546    /**
2547     * Flag indicating that we're in the process of fitting system windows using the old method.
2548     */
2549    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2550
2551    /**
2552     * Flag indicating that nested scrolling is enabled for this view.
2553     * The view will optionally cooperate with views up its parent chain to allow for
2554     * integrated nested scrolling along the same axis.
2555     */
2556    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2557
2558    /**
2559     * Flag indicating that the bottom scroll indicator should be displayed
2560     * when this view can scroll up.
2561     */
2562    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2563
2564    /**
2565     * Flag indicating that the bottom scroll indicator should be displayed
2566     * when this view can scroll down.
2567     */
2568    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2569
2570    /**
2571     * Flag indicating that the left scroll indicator should be displayed
2572     * when this view can scroll left.
2573     */
2574    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2575
2576    /**
2577     * Flag indicating that the right scroll indicator should be displayed
2578     * when this view can scroll right.
2579     */
2580    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2581
2582    /**
2583     * Flag indicating that the start scroll indicator should be displayed
2584     * when this view can scroll in the start direction.
2585     */
2586    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2587
2588    /**
2589     * Flag indicating that the end scroll indicator should be displayed
2590     * when this view can scroll in the end direction.
2591     */
2592    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2593
2594    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2595
2596    static final int SCROLL_INDICATORS_NONE = 0x0000;
2597
2598    /**
2599     * Mask for use with setFlags indicating bits used for indicating which
2600     * scroll indicators are enabled.
2601     */
2602    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2603            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2604            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2605            | PFLAG3_SCROLL_INDICATOR_END;
2606
2607    /**
2608     * Left-shift required to translate between public scroll indicator flags
2609     * and internal PFLAGS3 flags. When used as a right-shift, translates
2610     * PFLAGS3 flags to public flags.
2611     */
2612    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2613
2614    /** @hide */
2615    @Retention(RetentionPolicy.SOURCE)
2616    @IntDef(flag = true,
2617            value = {
2618                    SCROLL_INDICATOR_TOP,
2619                    SCROLL_INDICATOR_BOTTOM,
2620                    SCROLL_INDICATOR_LEFT,
2621                    SCROLL_INDICATOR_RIGHT,
2622                    SCROLL_INDICATOR_START,
2623                    SCROLL_INDICATOR_END,
2624            })
2625    public @interface ScrollIndicators {}
2626
2627    /**
2628     * Scroll indicator direction for the top edge of the view.
2629     *
2630     * @see #setScrollIndicators(int)
2631     * @see #setScrollIndicators(int, int)
2632     * @see #getScrollIndicators()
2633     */
2634    public static final int SCROLL_INDICATOR_TOP =
2635            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2636
2637    /**
2638     * Scroll indicator direction for the bottom edge of the view.
2639     *
2640     * @see #setScrollIndicators(int)
2641     * @see #setScrollIndicators(int, int)
2642     * @see #getScrollIndicators()
2643     */
2644    public static final int SCROLL_INDICATOR_BOTTOM =
2645            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2646
2647    /**
2648     * Scroll indicator direction for the left edge of the view.
2649     *
2650     * @see #setScrollIndicators(int)
2651     * @see #setScrollIndicators(int, int)
2652     * @see #getScrollIndicators()
2653     */
2654    public static final int SCROLL_INDICATOR_LEFT =
2655            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2656
2657    /**
2658     * Scroll indicator direction for the right edge of the view.
2659     *
2660     * @see #setScrollIndicators(int)
2661     * @see #setScrollIndicators(int, int)
2662     * @see #getScrollIndicators()
2663     */
2664    public static final int SCROLL_INDICATOR_RIGHT =
2665            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2666
2667    /**
2668     * Scroll indicator direction for the starting edge of the view.
2669     * <p>
2670     * Resolved according to the view's layout direction, see
2671     * {@link #getLayoutDirection()} for more information.
2672     *
2673     * @see #setScrollIndicators(int)
2674     * @see #setScrollIndicators(int, int)
2675     * @see #getScrollIndicators()
2676     */
2677    public static final int SCROLL_INDICATOR_START =
2678            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2679
2680    /**
2681     * Scroll indicator direction for the ending edge of the view.
2682     * <p>
2683     * Resolved according to the view's layout direction, see
2684     * {@link #getLayoutDirection()} for more information.
2685     *
2686     * @see #setScrollIndicators(int)
2687     * @see #setScrollIndicators(int, int)
2688     * @see #getScrollIndicators()
2689     */
2690    public static final int SCROLL_INDICATOR_END =
2691            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2692
2693    /**
2694     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2695     * into this view.<p>
2696     */
2697    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2698
2699    /**
2700     * Flag indicating that the view is a root of a keyboard navigation cluster.
2701     *
2702     * @see #isKeyboardNavigationCluster()
2703     * @see #setKeyboardNavigationCluster(boolean)
2704     */
2705    private static final int PFLAG3_CLUSTER = 0x8000;
2706
2707    /**
2708     * Flag indicating that the view is a root of a keyboard navigation section.
2709     *
2710     * @see #isKeyboardNavigationSection()
2711     * @see #setKeyboardNavigationSection(boolean)
2712     */
2713    private static final int PFLAG3_SECTION = 0x10000;
2714
2715    /**
2716     * Indicates that the user is currently touching the screen.
2717     * Currently used for the tooltip positioning only.
2718     */
2719    private static final int PFLAG3_FINGER_DOWN = 0x20000;
2720
2721    /**
2722     * Whether this view has rendered elements that overlap (see {@link
2723     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2724     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2725     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2726     * determined by whatever {@link #hasOverlappingRendering()} returns.
2727     */
2728    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2729
2730    /**
2731     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2732     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2733     */
2734    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2735
2736    /**
2737     * Flag indicating that the view is temporarily detached from the parent view.
2738     *
2739     * @see #onStartTemporaryDetach()
2740     * @see #onFinishTemporaryDetach()
2741     */
2742    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
2743
2744    /**
2745     * Flag indicating that the view does not wish to be revealed within its parent
2746     * hierarchy when it gains focus. Expressed in the negative since the historical
2747     * default behavior is to reveal on focus; this flag suppresses that behavior.
2748     *
2749     * @see #setRevealOnFocusHint(boolean)
2750     * @see #getRevealOnFocusHint()
2751     */
2752    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
2753
2754    /* End of masks for mPrivateFlags3 */
2755
2756    /**
2757     * Always allow a user to over-scroll this view, provided it is a
2758     * view that can scroll.
2759     *
2760     * @see #getOverScrollMode()
2761     * @see #setOverScrollMode(int)
2762     */
2763    public static final int OVER_SCROLL_ALWAYS = 0;
2764
2765    /**
2766     * Allow a user to over-scroll this view only if the content is large
2767     * enough to meaningfully scroll, provided it is a view that can scroll.
2768     *
2769     * @see #getOverScrollMode()
2770     * @see #setOverScrollMode(int)
2771     */
2772    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2773
2774    /**
2775     * Never allow a user to over-scroll this view.
2776     *
2777     * @see #getOverScrollMode()
2778     * @see #setOverScrollMode(int)
2779     */
2780    public static final int OVER_SCROLL_NEVER = 2;
2781
2782    /**
2783     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2784     * requested the system UI (status bar) to be visible (the default).
2785     *
2786     * @see #setSystemUiVisibility(int)
2787     */
2788    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2789
2790    /**
2791     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2792     * system UI to enter an unobtrusive "low profile" mode.
2793     *
2794     * <p>This is for use in games, book readers, video players, or any other
2795     * "immersive" application where the usual system chrome is deemed too distracting.
2796     *
2797     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2798     *
2799     * @see #setSystemUiVisibility(int)
2800     */
2801    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2802
2803    /**
2804     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2805     * system navigation be temporarily hidden.
2806     *
2807     * <p>This is an even less obtrusive state than that called for by
2808     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2809     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2810     * those to disappear. This is useful (in conjunction with the
2811     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2812     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2813     * window flags) for displaying content using every last pixel on the display.
2814     *
2815     * <p>There is a limitation: because navigation controls are so important, the least user
2816     * interaction will cause them to reappear immediately.  When this happens, both
2817     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2818     * so that both elements reappear at the same time.
2819     *
2820     * @see #setSystemUiVisibility(int)
2821     */
2822    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2823
2824    /**
2825     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2826     * into the normal fullscreen mode so that its content can take over the screen
2827     * while still allowing the user to interact with the application.
2828     *
2829     * <p>This has the same visual effect as
2830     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2831     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2832     * meaning that non-critical screen decorations (such as the status bar) will be
2833     * hidden while the user is in the View's window, focusing the experience on
2834     * that content.  Unlike the window flag, if you are using ActionBar in
2835     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2836     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2837     * hide the action bar.
2838     *
2839     * <p>This approach to going fullscreen is best used over the window flag when
2840     * it is a transient state -- that is, the application does this at certain
2841     * points in its user interaction where it wants to allow the user to focus
2842     * on content, but not as a continuous state.  For situations where the application
2843     * would like to simply stay full screen the entire time (such as a game that
2844     * wants to take over the screen), the
2845     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2846     * is usually a better approach.  The state set here will be removed by the system
2847     * in various situations (such as the user moving to another application) like
2848     * the other system UI states.
2849     *
2850     * <p>When using this flag, the application should provide some easy facility
2851     * for the user to go out of it.  A common example would be in an e-book
2852     * reader, where tapping on the screen brings back whatever screen and UI
2853     * decorations that had been hidden while the user was immersed in reading
2854     * the book.
2855     *
2856     * @see #setSystemUiVisibility(int)
2857     */
2858    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2859
2860    /**
2861     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2862     * flags, we would like a stable view of the content insets given to
2863     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2864     * will always represent the worst case that the application can expect
2865     * as a continuous state.  In the stock Android UI this is the space for
2866     * the system bar, nav bar, and status bar, but not more transient elements
2867     * such as an input method.
2868     *
2869     * The stable layout your UI sees is based on the system UI modes you can
2870     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2871     * then you will get a stable layout for changes of the
2872     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2873     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2874     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2875     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2876     * with a stable layout.  (Note that you should avoid using
2877     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2878     *
2879     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2880     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2881     * then a hidden status bar will be considered a "stable" state for purposes
2882     * here.  This allows your UI to continually hide the status bar, while still
2883     * using the system UI flags to hide the action bar while still retaining
2884     * a stable layout.  Note that changing the window fullscreen flag will never
2885     * provide a stable layout for a clean transition.
2886     *
2887     * <p>If you are using ActionBar in
2888     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2889     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2890     * insets it adds to those given to the application.
2891     */
2892    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2893
2894    /**
2895     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2896     * to be laid out as if it has requested
2897     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2898     * allows it to avoid artifacts when switching in and out of that mode, at
2899     * the expense that some of its user interface may be covered by screen
2900     * decorations when they are shown.  You can perform layout of your inner
2901     * UI elements to account for the navigation system UI through the
2902     * {@link #fitSystemWindows(Rect)} method.
2903     */
2904    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2905
2906    /**
2907     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2908     * to be laid out as if it has requested
2909     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2910     * allows it to avoid artifacts when switching in and out of that mode, at
2911     * the expense that some of its user interface may be covered by screen
2912     * decorations when they are shown.  You can perform layout of your inner
2913     * UI elements to account for non-fullscreen system UI through the
2914     * {@link #fitSystemWindows(Rect)} method.
2915     */
2916    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2917
2918    /**
2919     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2920     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2921     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2922     * user interaction.
2923     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2924     * has an effect when used in combination with that flag.</p>
2925     */
2926    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2927
2928    /**
2929     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2930     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2931     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2932     * experience while also hiding the system bars.  If this flag is not set,
2933     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2934     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2935     * if the user swipes from the top of the screen.
2936     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2937     * system gestures, such as swiping from the top of the screen.  These transient system bars
2938     * will overlay app’s content, may have some degree of transparency, and will automatically
2939     * hide after a short timeout.
2940     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2941     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2942     * with one or both of those flags.</p>
2943     */
2944    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2945
2946    /**
2947     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2948     * is compatible with light status bar backgrounds.
2949     *
2950     * <p>For this to take effect, the window must request
2951     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2952     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2953     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2954     *         FLAG_TRANSLUCENT_STATUS}.
2955     *
2956     * @see android.R.attr#windowLightStatusBar
2957     */
2958    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2959
2960    /**
2961     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
2962     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
2963     */
2964    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
2965
2966    /**
2967     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
2968     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
2969     */
2970    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
2971
2972    /**
2973     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
2974     * that is compatible with light navigation bar backgrounds.
2975     *
2976     * <p>For this to take effect, the window must request
2977     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2978     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2979     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
2980     *         FLAG_TRANSLUCENT_NAVIGATION}.
2981     */
2982    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
2983
2984    /**
2985     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2986     */
2987    @Deprecated
2988    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2989
2990    /**
2991     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2992     */
2993    @Deprecated
2994    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2995
2996    /**
2997     * @hide
2998     *
2999     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3000     * out of the public fields to keep the undefined bits out of the developer's way.
3001     *
3002     * Flag to make the status bar not expandable.  Unless you also
3003     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3004     */
3005    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3006
3007    /**
3008     * @hide
3009     *
3010     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3011     * out of the public fields to keep the undefined bits out of the developer's way.
3012     *
3013     * Flag to hide notification icons and scrolling ticker text.
3014     */
3015    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3016
3017    /**
3018     * @hide
3019     *
3020     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3021     * out of the public fields to keep the undefined bits out of the developer's way.
3022     *
3023     * Flag to disable incoming notification alerts.  This will not block
3024     * icons, but it will block sound, vibrating and other visual or aural notifications.
3025     */
3026    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3027
3028    /**
3029     * @hide
3030     *
3031     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3032     * out of the public fields to keep the undefined bits out of the developer's way.
3033     *
3034     * Flag to hide only the scrolling ticker.  Note that
3035     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3036     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3037     */
3038    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3039
3040    /**
3041     * @hide
3042     *
3043     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3044     * out of the public fields to keep the undefined bits out of the developer's way.
3045     *
3046     * Flag to hide the center system info area.
3047     */
3048    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3049
3050    /**
3051     * @hide
3052     *
3053     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3054     * out of the public fields to keep the undefined bits out of the developer's way.
3055     *
3056     * Flag to hide only the home button.  Don't use this
3057     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3058     */
3059    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3060
3061    /**
3062     * @hide
3063     *
3064     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3065     * out of the public fields to keep the undefined bits out of the developer's way.
3066     *
3067     * Flag to hide only the back button. Don't use this
3068     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3069     */
3070    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3071
3072    /**
3073     * @hide
3074     *
3075     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3076     * out of the public fields to keep the undefined bits out of the developer's way.
3077     *
3078     * Flag to hide only the clock.  You might use this if your activity has
3079     * its own clock making the status bar's clock redundant.
3080     */
3081    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3082
3083    /**
3084     * @hide
3085     *
3086     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3087     * out of the public fields to keep the undefined bits out of the developer's way.
3088     *
3089     * Flag to hide only the recent apps button. Don't use this
3090     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3091     */
3092    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3093
3094    /**
3095     * @hide
3096     *
3097     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3098     * out of the public fields to keep the undefined bits out of the developer's way.
3099     *
3100     * Flag to disable the global search gesture. Don't use this
3101     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3102     */
3103    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3104
3105    /**
3106     * @hide
3107     *
3108     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3109     * out of the public fields to keep the undefined bits out of the developer's way.
3110     *
3111     * Flag to specify that the status bar is displayed in transient mode.
3112     */
3113    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3114
3115    /**
3116     * @hide
3117     *
3118     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3119     * out of the public fields to keep the undefined bits out of the developer's way.
3120     *
3121     * Flag to specify that the navigation bar is displayed in transient mode.
3122     */
3123    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3124
3125    /**
3126     * @hide
3127     *
3128     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3129     * out of the public fields to keep the undefined bits out of the developer's way.
3130     *
3131     * Flag to specify that the hidden status bar would like to be shown.
3132     */
3133    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3134
3135    /**
3136     * @hide
3137     *
3138     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3139     * out of the public fields to keep the undefined bits out of the developer's way.
3140     *
3141     * Flag to specify that the hidden navigation bar would like to be shown.
3142     */
3143    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3144
3145    /**
3146     * @hide
3147     *
3148     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3149     * out of the public fields to keep the undefined bits out of the developer's way.
3150     *
3151     * Flag to specify that the status bar is displayed in translucent mode.
3152     */
3153    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3154
3155    /**
3156     * @hide
3157     *
3158     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3159     * out of the public fields to keep the undefined bits out of the developer's way.
3160     *
3161     * Flag to specify that the navigation bar is displayed in translucent mode.
3162     */
3163    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3164
3165    /**
3166     * @hide
3167     *
3168     * Makes navigation bar transparent (but not the status bar).
3169     */
3170    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3171
3172    /**
3173     * @hide
3174     *
3175     * Makes status bar transparent (but not the navigation bar).
3176     */
3177    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3178
3179    /**
3180     * @hide
3181     *
3182     * Makes both status bar and navigation bar transparent.
3183     */
3184    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3185            | STATUS_BAR_TRANSPARENT;
3186
3187    /**
3188     * @hide
3189     */
3190    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3191
3192    /**
3193     * These are the system UI flags that can be cleared by events outside
3194     * of an application.  Currently this is just the ability to tap on the
3195     * screen while hiding the navigation bar to have it return.
3196     * @hide
3197     */
3198    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3199            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3200            | SYSTEM_UI_FLAG_FULLSCREEN;
3201
3202    /**
3203     * Flags that can impact the layout in relation to system UI.
3204     */
3205    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3206            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3207            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3208
3209    /** @hide */
3210    @IntDef(flag = true,
3211            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3212    @Retention(RetentionPolicy.SOURCE)
3213    public @interface FindViewFlags {}
3214
3215    /**
3216     * Find views that render the specified text.
3217     *
3218     * @see #findViewsWithText(ArrayList, CharSequence, int)
3219     */
3220    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3221
3222    /**
3223     * Find find views that contain the specified content description.
3224     *
3225     * @see #findViewsWithText(ArrayList, CharSequence, int)
3226     */
3227    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3228
3229    /**
3230     * Find views that contain {@link AccessibilityNodeProvider}. Such
3231     * a View is a root of virtual view hierarchy and may contain the searched
3232     * text. If this flag is set Views with providers are automatically
3233     * added and it is a responsibility of the client to call the APIs of
3234     * the provider to determine whether the virtual tree rooted at this View
3235     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3236     * representing the virtual views with this text.
3237     *
3238     * @see #findViewsWithText(ArrayList, CharSequence, int)
3239     *
3240     * @hide
3241     */
3242    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3243
3244    /**
3245     * The undefined cursor position.
3246     *
3247     * @hide
3248     */
3249    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3250
3251    /**
3252     * Indicates that the screen has changed state and is now off.
3253     *
3254     * @see #onScreenStateChanged(int)
3255     */
3256    public static final int SCREEN_STATE_OFF = 0x0;
3257
3258    /**
3259     * Indicates that the screen has changed state and is now on.
3260     *
3261     * @see #onScreenStateChanged(int)
3262     */
3263    public static final int SCREEN_STATE_ON = 0x1;
3264
3265    /**
3266     * Indicates no axis of view scrolling.
3267     */
3268    public static final int SCROLL_AXIS_NONE = 0;
3269
3270    /**
3271     * Indicates scrolling along the horizontal axis.
3272     */
3273    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3274
3275    /**
3276     * Indicates scrolling along the vertical axis.
3277     */
3278    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3279
3280    /**
3281     * Controls the over-scroll mode for this view.
3282     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3283     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3284     * and {@link #OVER_SCROLL_NEVER}.
3285     */
3286    private int mOverScrollMode;
3287
3288    /**
3289     * The parent this view is attached to.
3290     * {@hide}
3291     *
3292     * @see #getParent()
3293     */
3294    protected ViewParent mParent;
3295
3296    /**
3297     * {@hide}
3298     */
3299    AttachInfo mAttachInfo;
3300
3301    /**
3302     * {@hide}
3303     */
3304    @ViewDebug.ExportedProperty(flagMapping = {
3305        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3306                name = "FORCE_LAYOUT"),
3307        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3308                name = "LAYOUT_REQUIRED"),
3309        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3310            name = "DRAWING_CACHE_INVALID", outputIf = false),
3311        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3312        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3313        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3314        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3315    }, formatToHexString = true)
3316    int mPrivateFlags;
3317    int mPrivateFlags2;
3318    int mPrivateFlags3;
3319
3320    /**
3321     * This view's request for the visibility of the status bar.
3322     * @hide
3323     */
3324    @ViewDebug.ExportedProperty(flagMapping = {
3325        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3326                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3327                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3328        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3329                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3330                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3331        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3332                                equals = SYSTEM_UI_FLAG_VISIBLE,
3333                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3334    }, formatToHexString = true)
3335    int mSystemUiVisibility;
3336
3337    /**
3338     * Reference count for transient state.
3339     * @see #setHasTransientState(boolean)
3340     */
3341    int mTransientStateCount = 0;
3342
3343    /**
3344     * Count of how many windows this view has been attached to.
3345     */
3346    int mWindowAttachCount;
3347
3348    /**
3349     * The layout parameters associated with this view and used by the parent
3350     * {@link android.view.ViewGroup} to determine how this view should be
3351     * laid out.
3352     * {@hide}
3353     */
3354    protected ViewGroup.LayoutParams mLayoutParams;
3355
3356    /**
3357     * The view flags hold various views states.
3358     * {@hide}
3359     */
3360    @ViewDebug.ExportedProperty(formatToHexString = true)
3361    int mViewFlags;
3362
3363    static class TransformationInfo {
3364        /**
3365         * The transform matrix for the View. This transform is calculated internally
3366         * based on the translation, rotation, and scale properties.
3367         *
3368         * Do *not* use this variable directly; instead call getMatrix(), which will
3369         * load the value from the View's RenderNode.
3370         */
3371        private final Matrix mMatrix = new Matrix();
3372
3373        /**
3374         * The inverse transform matrix for the View. This transform is calculated
3375         * internally based on the translation, rotation, and scale properties.
3376         *
3377         * Do *not* use this variable directly; instead call getInverseMatrix(),
3378         * which will load the value from the View's RenderNode.
3379         */
3380        private Matrix mInverseMatrix;
3381
3382        /**
3383         * The opacity of the View. This is a value from 0 to 1, where 0 means
3384         * completely transparent and 1 means completely opaque.
3385         */
3386        @ViewDebug.ExportedProperty
3387        float mAlpha = 1f;
3388
3389        /**
3390         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3391         * property only used by transitions, which is composited with the other alpha
3392         * values to calculate the final visual alpha value.
3393         */
3394        float mTransitionAlpha = 1f;
3395    }
3396
3397    TransformationInfo mTransformationInfo;
3398
3399    /**
3400     * Current clip bounds. to which all drawing of this view are constrained.
3401     */
3402    Rect mClipBounds = null;
3403
3404    private boolean mLastIsOpaque;
3405
3406    /**
3407     * The distance in pixels from the left edge of this view's parent
3408     * to the left edge of this view.
3409     * {@hide}
3410     */
3411    @ViewDebug.ExportedProperty(category = "layout")
3412    protected int mLeft;
3413    /**
3414     * The distance in pixels from the left edge of this view's parent
3415     * to the right edge of this view.
3416     * {@hide}
3417     */
3418    @ViewDebug.ExportedProperty(category = "layout")
3419    protected int mRight;
3420    /**
3421     * The distance in pixels from the top edge of this view's parent
3422     * to the top edge of this view.
3423     * {@hide}
3424     */
3425    @ViewDebug.ExportedProperty(category = "layout")
3426    protected int mTop;
3427    /**
3428     * The distance in pixels from the top edge of this view's parent
3429     * to the bottom edge of this view.
3430     * {@hide}
3431     */
3432    @ViewDebug.ExportedProperty(category = "layout")
3433    protected int mBottom;
3434
3435    /**
3436     * The offset, in pixels, by which the content of this view is scrolled
3437     * horizontally.
3438     * {@hide}
3439     */
3440    @ViewDebug.ExportedProperty(category = "scrolling")
3441    protected int mScrollX;
3442    /**
3443     * The offset, in pixels, by which the content of this view is scrolled
3444     * vertically.
3445     * {@hide}
3446     */
3447    @ViewDebug.ExportedProperty(category = "scrolling")
3448    protected int mScrollY;
3449
3450    /**
3451     * The left padding in pixels, that is the distance in pixels between the
3452     * left edge of this view and the left edge of its content.
3453     * {@hide}
3454     */
3455    @ViewDebug.ExportedProperty(category = "padding")
3456    protected int mPaddingLeft = 0;
3457    /**
3458     * The right padding in pixels, that is the distance in pixels between the
3459     * right edge of this view and the right edge of its content.
3460     * {@hide}
3461     */
3462    @ViewDebug.ExportedProperty(category = "padding")
3463    protected int mPaddingRight = 0;
3464    /**
3465     * The top padding in pixels, that is the distance in pixels between the
3466     * top edge of this view and the top edge of its content.
3467     * {@hide}
3468     */
3469    @ViewDebug.ExportedProperty(category = "padding")
3470    protected int mPaddingTop;
3471    /**
3472     * The bottom padding in pixels, that is the distance in pixels between the
3473     * bottom edge of this view and the bottom edge of its content.
3474     * {@hide}
3475     */
3476    @ViewDebug.ExportedProperty(category = "padding")
3477    protected int mPaddingBottom;
3478
3479    /**
3480     * The layout insets in pixels, that is the distance in pixels between the
3481     * visible edges of this view its bounds.
3482     */
3483    private Insets mLayoutInsets;
3484
3485    /**
3486     * Briefly describes the view and is primarily used for accessibility support.
3487     */
3488    private CharSequence mContentDescription;
3489
3490    /**
3491     * Specifies the id of a view for which this view serves as a label for
3492     * accessibility purposes.
3493     */
3494    private int mLabelForId = View.NO_ID;
3495
3496    /**
3497     * Predicate for matching labeled view id with its label for
3498     * accessibility purposes.
3499     */
3500    private MatchLabelForPredicate mMatchLabelForPredicate;
3501
3502    /**
3503     * Specifies a view before which this one is visited in accessibility traversal.
3504     */
3505    private int mAccessibilityTraversalBeforeId = NO_ID;
3506
3507    /**
3508     * Specifies a view after which this one is visited in accessibility traversal.
3509     */
3510    private int mAccessibilityTraversalAfterId = NO_ID;
3511
3512    /**
3513     * Predicate for matching a view by its id.
3514     */
3515    private MatchIdPredicate mMatchIdPredicate;
3516
3517    /**
3518     * Cache the paddingRight set by the user to append to the scrollbar's size.
3519     *
3520     * @hide
3521     */
3522    @ViewDebug.ExportedProperty(category = "padding")
3523    protected int mUserPaddingRight;
3524
3525    /**
3526     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3527     *
3528     * @hide
3529     */
3530    @ViewDebug.ExportedProperty(category = "padding")
3531    protected int mUserPaddingBottom;
3532
3533    /**
3534     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3535     *
3536     * @hide
3537     */
3538    @ViewDebug.ExportedProperty(category = "padding")
3539    protected int mUserPaddingLeft;
3540
3541    /**
3542     * Cache the paddingStart set by the user to append to the scrollbar's size.
3543     *
3544     */
3545    @ViewDebug.ExportedProperty(category = "padding")
3546    int mUserPaddingStart;
3547
3548    /**
3549     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3550     *
3551     */
3552    @ViewDebug.ExportedProperty(category = "padding")
3553    int mUserPaddingEnd;
3554
3555    /**
3556     * Cache initial left padding.
3557     *
3558     * @hide
3559     */
3560    int mUserPaddingLeftInitial;
3561
3562    /**
3563     * Cache initial right padding.
3564     *
3565     * @hide
3566     */
3567    int mUserPaddingRightInitial;
3568
3569    /**
3570     * Default undefined padding
3571     */
3572    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3573
3574    /**
3575     * Cache if a left padding has been defined
3576     */
3577    private boolean mLeftPaddingDefined = false;
3578
3579    /**
3580     * Cache if a right padding has been defined
3581     */
3582    private boolean mRightPaddingDefined = false;
3583
3584    /**
3585     * @hide
3586     */
3587    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3588    /**
3589     * @hide
3590     */
3591    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3592
3593    private LongSparseLongArray mMeasureCache;
3594
3595    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3596    private Drawable mBackground;
3597    private TintInfo mBackgroundTint;
3598
3599    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3600    private ForegroundInfo mForegroundInfo;
3601
3602    private Drawable mScrollIndicatorDrawable;
3603
3604    /**
3605     * RenderNode used for backgrounds.
3606     * <p>
3607     * When non-null and valid, this is expected to contain an up-to-date copy
3608     * of the background drawable. It is cleared on temporary detach, and reset
3609     * on cleanup.
3610     */
3611    private RenderNode mBackgroundRenderNode;
3612
3613    private int mBackgroundResource;
3614    private boolean mBackgroundSizeChanged;
3615
3616    private String mTransitionName;
3617
3618    static class TintInfo {
3619        ColorStateList mTintList;
3620        PorterDuff.Mode mTintMode;
3621        boolean mHasTintMode;
3622        boolean mHasTintList;
3623    }
3624
3625    private static class ForegroundInfo {
3626        private Drawable mDrawable;
3627        private TintInfo mTintInfo;
3628        private int mGravity = Gravity.FILL;
3629        private boolean mInsidePadding = true;
3630        private boolean mBoundsChanged = true;
3631        private final Rect mSelfBounds = new Rect();
3632        private final Rect mOverlayBounds = new Rect();
3633    }
3634
3635    static class ListenerInfo {
3636        /**
3637         * Listener used to dispatch focus change events.
3638         * This field should be made private, so it is hidden from the SDK.
3639         * {@hide}
3640         */
3641        protected OnFocusChangeListener mOnFocusChangeListener;
3642
3643        /**
3644         * Listeners for layout change events.
3645         */
3646        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3647
3648        protected OnScrollChangeListener mOnScrollChangeListener;
3649
3650        /**
3651         * Listeners for attach events.
3652         */
3653        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3654
3655        /**
3656         * Listener used to dispatch click events.
3657         * This field should be made private, so it is hidden from the SDK.
3658         * {@hide}
3659         */
3660        public OnClickListener mOnClickListener;
3661
3662        /**
3663         * Listener used to dispatch long click events.
3664         * This field should be made private, so it is hidden from the SDK.
3665         * {@hide}
3666         */
3667        protected OnLongClickListener mOnLongClickListener;
3668
3669        /**
3670         * Listener used to dispatch context click events. This field should be made private, so it
3671         * is hidden from the SDK.
3672         * {@hide}
3673         */
3674        protected OnContextClickListener mOnContextClickListener;
3675
3676        /**
3677         * Listener used to build the context menu.
3678         * This field should be made private, so it is hidden from the SDK.
3679         * {@hide}
3680         */
3681        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3682
3683        private OnKeyListener mOnKeyListener;
3684
3685        private OnTouchListener mOnTouchListener;
3686
3687        private OnHoverListener mOnHoverListener;
3688
3689        private OnGenericMotionListener mOnGenericMotionListener;
3690
3691        private OnDragListener mOnDragListener;
3692
3693        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3694
3695        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3696    }
3697
3698    ListenerInfo mListenerInfo;
3699
3700    private static class TooltipInfo {
3701        /**
3702         * Text to be displayed in a tooltip popup.
3703         */
3704        @Nullable
3705        CharSequence mTooltip;
3706
3707        /**
3708         * View-relative position of the tooltip anchor point.
3709         */
3710        int mAnchorX;
3711        int mAnchorY;
3712
3713        /**
3714         * The tooltip popup.
3715         */
3716        @Nullable
3717        TooltipPopup mTooltipPopup;
3718
3719        /**
3720         * Set to true if the tooltip was shown as a result of a long click.
3721         */
3722        boolean mTooltipFromLongClick;
3723
3724        /**
3725         * Keep these Runnables so that they can be used to reschedule.
3726         */
3727        Runnable mShowTooltipRunnable;
3728        Runnable mHideTooltipRunnable;
3729    }
3730
3731    TooltipInfo mTooltipInfo;
3732
3733    // Temporary values used to hold (x,y) coordinates when delegating from the
3734    // two-arg performLongClick() method to the legacy no-arg version.
3735    private float mLongClickX = Float.NaN;
3736    private float mLongClickY = Float.NaN;
3737
3738    /**
3739     * The application environment this view lives in.
3740     * This field should be made private, so it is hidden from the SDK.
3741     * {@hide}
3742     */
3743    @ViewDebug.ExportedProperty(deepExport = true)
3744    protected Context mContext;
3745
3746    private final Resources mResources;
3747
3748    private ScrollabilityCache mScrollCache;
3749
3750    private int[] mDrawableState = null;
3751
3752    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3753
3754    /**
3755     * Animator that automatically runs based on state changes.
3756     */
3757    private StateListAnimator mStateListAnimator;
3758
3759    /**
3760     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3761     * the user may specify which view to go to next.
3762     */
3763    private int mNextFocusLeftId = View.NO_ID;
3764
3765    /**
3766     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3767     * the user may specify which view to go to next.
3768     */
3769    private int mNextFocusRightId = View.NO_ID;
3770
3771    /**
3772     * When this view has focus and the next focus is {@link #FOCUS_UP},
3773     * the user may specify which view to go to next.
3774     */
3775    private int mNextFocusUpId = View.NO_ID;
3776
3777    /**
3778     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3779     * the user may specify which view to go to next.
3780     */
3781    private int mNextFocusDownId = View.NO_ID;
3782
3783    /**
3784     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3785     * the user may specify which view to go to next.
3786     */
3787    int mNextFocusForwardId = View.NO_ID;
3788
3789    /**
3790     * User-specified next keyboard navigation cluster.
3791     */
3792    int mNextClusterForwardId = View.NO_ID;
3793
3794    /**
3795     * User-specified next keyboard navigation section.
3796     */
3797    int mNextSectionForwardId = View.NO_ID;
3798
3799    private CheckForLongPress mPendingCheckForLongPress;
3800    private CheckForTap mPendingCheckForTap = null;
3801    private PerformClick mPerformClick;
3802    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3803
3804    private UnsetPressedState mUnsetPressedState;
3805
3806    /**
3807     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3808     * up event while a long press is invoked as soon as the long press duration is reached, so
3809     * a long press could be performed before the tap is checked, in which case the tap's action
3810     * should not be invoked.
3811     */
3812    private boolean mHasPerformedLongPress;
3813
3814    /**
3815     * Whether a context click button is currently pressed down. This is true when the stylus is
3816     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3817     * pressed. This is false once the button is released or if the stylus has been lifted.
3818     */
3819    private boolean mInContextButtonPress;
3820
3821    /**
3822     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3823     * true after a stylus button press has occured, when the next up event should not be recognized
3824     * as a tap.
3825     */
3826    private boolean mIgnoreNextUpEvent;
3827
3828    /**
3829     * The minimum height of the view. We'll try our best to have the height
3830     * of this view to at least this amount.
3831     */
3832    @ViewDebug.ExportedProperty(category = "measurement")
3833    private int mMinHeight;
3834
3835    /**
3836     * The minimum width of the view. We'll try our best to have the width
3837     * of this view to at least this amount.
3838     */
3839    @ViewDebug.ExportedProperty(category = "measurement")
3840    private int mMinWidth;
3841
3842    /**
3843     * The delegate to handle touch events that are physically in this view
3844     * but should be handled by another view.
3845     */
3846    private TouchDelegate mTouchDelegate = null;
3847
3848    /**
3849     * Solid color to use as a background when creating the drawing cache. Enables
3850     * the cache to use 16 bit bitmaps instead of 32 bit.
3851     */
3852    private int mDrawingCacheBackgroundColor = 0;
3853
3854    /**
3855     * Special tree observer used when mAttachInfo is null.
3856     */
3857    private ViewTreeObserver mFloatingTreeObserver;
3858
3859    /**
3860     * Cache the touch slop from the context that created the view.
3861     */
3862    private int mTouchSlop;
3863
3864    /**
3865     * Object that handles automatic animation of view properties.
3866     */
3867    private ViewPropertyAnimator mAnimator = null;
3868
3869    /**
3870     * List of registered FrameMetricsObservers.
3871     */
3872    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
3873
3874    /**
3875     * Flag indicating that a drag can cross window boundaries.  When
3876     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3877     * with this flag set, all visible applications with targetSdkVersion >=
3878     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
3879     * in the drag operation and receive the dragged content.
3880     *
3881     * <p>If this is the only flag set, then the drag recipient will only have access to text data
3882     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3883     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
3884     */
3885    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3886
3887    /**
3888     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3889     * request read access to the content URI(s) contained in the {@link ClipData} object.
3890     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3891     */
3892    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3893
3894    /**
3895     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3896     * request write access to the content URI(s) contained in the {@link ClipData} object.
3897     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3898     */
3899    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3900
3901    /**
3902     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3903     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3904     * reboots until explicitly revoked with
3905     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3906     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3907     */
3908    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3909            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3910
3911    /**
3912     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3913     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3914     * match against the original granted URI.
3915     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3916     */
3917    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3918            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3919
3920    /**
3921     * Flag indicating that the drag shadow will be opaque.  When
3922     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3923     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3924     */
3925    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3926
3927    /**
3928     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3929     */
3930    private float mVerticalScrollFactor;
3931
3932    /**
3933     * Position of the vertical scroll bar.
3934     */
3935    private int mVerticalScrollbarPosition;
3936
3937    /**
3938     * Position the scroll bar at the default position as determined by the system.
3939     */
3940    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3941
3942    /**
3943     * Position the scroll bar along the left edge.
3944     */
3945    public static final int SCROLLBAR_POSITION_LEFT = 1;
3946
3947    /**
3948     * Position the scroll bar along the right edge.
3949     */
3950    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3951
3952    /**
3953     * Indicates that the view does not have a layer.
3954     *
3955     * @see #getLayerType()
3956     * @see #setLayerType(int, android.graphics.Paint)
3957     * @see #LAYER_TYPE_SOFTWARE
3958     * @see #LAYER_TYPE_HARDWARE
3959     */
3960    public static final int LAYER_TYPE_NONE = 0;
3961
3962    /**
3963     * <p>Indicates that the view has a software layer. A software layer is backed
3964     * by a bitmap and causes the view to be rendered using Android's software
3965     * rendering pipeline, even if hardware acceleration is enabled.</p>
3966     *
3967     * <p>Software layers have various usages:</p>
3968     * <p>When the application is not using hardware acceleration, a software layer
3969     * is useful to apply a specific color filter and/or blending mode and/or
3970     * translucency to a view and all its children.</p>
3971     * <p>When the application is using hardware acceleration, a software layer
3972     * is useful to render drawing primitives not supported by the hardware
3973     * accelerated pipeline. It can also be used to cache a complex view tree
3974     * into a texture and reduce the complexity of drawing operations. For instance,
3975     * when animating a complex view tree with a translation, a software layer can
3976     * be used to render the view tree only once.</p>
3977     * <p>Software layers should be avoided when the affected view tree updates
3978     * often. Every update will require to re-render the software layer, which can
3979     * potentially be slow (particularly when hardware acceleration is turned on
3980     * since the layer will have to be uploaded into a hardware texture after every
3981     * update.)</p>
3982     *
3983     * @see #getLayerType()
3984     * @see #setLayerType(int, android.graphics.Paint)
3985     * @see #LAYER_TYPE_NONE
3986     * @see #LAYER_TYPE_HARDWARE
3987     */
3988    public static final int LAYER_TYPE_SOFTWARE = 1;
3989
3990    /**
3991     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3992     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3993     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3994     * rendering pipeline, but only if hardware acceleration is turned on for the
3995     * view hierarchy. When hardware acceleration is turned off, hardware layers
3996     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3997     *
3998     * <p>A hardware layer is useful to apply a specific color filter and/or
3999     * blending mode and/or translucency to a view and all its children.</p>
4000     * <p>A hardware layer can be used to cache a complex view tree into a
4001     * texture and reduce the complexity of drawing operations. For instance,
4002     * when animating a complex view tree with a translation, a hardware layer can
4003     * be used to render the view tree only once.</p>
4004     * <p>A hardware layer can also be used to increase the rendering quality when
4005     * rotation transformations are applied on a view. It can also be used to
4006     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4007     *
4008     * @see #getLayerType()
4009     * @see #setLayerType(int, android.graphics.Paint)
4010     * @see #LAYER_TYPE_NONE
4011     * @see #LAYER_TYPE_SOFTWARE
4012     */
4013    public static final int LAYER_TYPE_HARDWARE = 2;
4014
4015    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4016            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4017            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4018            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4019    })
4020    int mLayerType = LAYER_TYPE_NONE;
4021    Paint mLayerPaint;
4022
4023
4024    /**
4025     * <p>When setting a {@link android.app.assist.AssistStructure}, its nodes should not contain
4026     * PII (Personally Identifiable Information).
4027     */
4028    // TODO(b/33197203) (b/33269702): improve documentation: mention all cases, show examples, etc.
4029    public static final int ASSIST_FLAG_SANITIZED_TEXT = 0x1;
4030
4031    /**
4032     * <p>When setting a {@link android.app.assist.AssistStructure}, its nodes should contain all
4033     * type of data, even sensitive PII (Personally Identifiable Information) like passwords or
4034     * credit card numbers.
4035     */
4036    public static final int ASSIST_FLAG_NON_SANITIZED_TEXT = 0x2;
4037
4038    /**
4039     * Set to true when drawing cache is enabled and cannot be created.
4040     *
4041     * @hide
4042     */
4043    public boolean mCachingFailed;
4044    private Bitmap mDrawingCache;
4045    private Bitmap mUnscaledDrawingCache;
4046
4047    /**
4048     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4049     * <p>
4050     * When non-null and valid, this is expected to contain an up-to-date copy
4051     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4052     * cleanup.
4053     */
4054    final RenderNode mRenderNode;
4055
4056    /**
4057     * Set to true when the view is sending hover accessibility events because it
4058     * is the innermost hovered view.
4059     */
4060    private boolean mSendingHoverAccessibilityEvents;
4061
4062    /**
4063     * Delegate for injecting accessibility functionality.
4064     */
4065    AccessibilityDelegate mAccessibilityDelegate;
4066
4067    /**
4068     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4069     * and add/remove objects to/from the overlay directly through the Overlay methods.
4070     */
4071    ViewOverlay mOverlay;
4072
4073    /**
4074     * The currently active parent view for receiving delegated nested scrolling events.
4075     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4076     * by {@link #stopNestedScroll()} at the same point where we clear
4077     * requestDisallowInterceptTouchEvent.
4078     */
4079    private ViewParent mNestedScrollingParent;
4080
4081    /**
4082     * Consistency verifier for debugging purposes.
4083     * @hide
4084     */
4085    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4086            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4087                    new InputEventConsistencyVerifier(this, 0) : null;
4088
4089    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4090
4091    private int[] mTempNestedScrollConsumed;
4092
4093    /**
4094     * An overlay is going to draw this View instead of being drawn as part of this
4095     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4096     * when this view is invalidated.
4097     */
4098    GhostView mGhostView;
4099
4100    /**
4101     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4102     * @hide
4103     */
4104    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4105    public String[] mAttributes;
4106
4107    /**
4108     * Maps a Resource id to its name.
4109     */
4110    private static SparseArray<String> mAttributeMap;
4111
4112    /**
4113     * Queue of pending runnables. Used to postpone calls to post() until this
4114     * view is attached and has a handler.
4115     */
4116    private HandlerActionQueue mRunQueue;
4117
4118    /**
4119     * The pointer icon when the mouse hovers on this view. The default is null.
4120     */
4121    private PointerIcon mPointerIcon;
4122
4123    /**
4124     * @hide
4125     */
4126    String mStartActivityRequestWho;
4127
4128    @Nullable
4129    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4130
4131    /**
4132     * Simple constructor to use when creating a view from code.
4133     *
4134     * @param context The Context the view is running in, through which it can
4135     *        access the current theme, resources, etc.
4136     */
4137    public View(Context context) {
4138        mContext = context;
4139        mResources = context != null ? context.getResources() : null;
4140        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
4141        // Set some flags defaults
4142        mPrivateFlags2 =
4143                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4144                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4145                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4146                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4147                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4148                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4149        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4150        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4151        mUserPaddingStart = UNDEFINED_PADDING;
4152        mUserPaddingEnd = UNDEFINED_PADDING;
4153        mRenderNode = RenderNode.create(getClass().getName(), this);
4154
4155        if (!sCompatibilityDone && context != null) {
4156            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4157
4158            // Older apps may need this compatibility hack for measurement.
4159            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
4160
4161            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4162            // of whether a layout was requested on that View.
4163            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
4164
4165            Canvas.sCompatibilityRestore = targetSdkVersion < M;
4166
4167            // In M and newer, our widgets can pass a "hint" value in the size
4168            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4169            // know what the expected parent size is going to be, so e.g. list items can size
4170            // themselves at 1/3 the size of their container. It breaks older apps though,
4171            // specifically apps that use some popular open source libraries.
4172            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
4173
4174            // Old versions of the platform would give different results from
4175            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4176            // modes, so we always need to run an additional EXACTLY pass.
4177            sAlwaysRemeasureExactly = targetSdkVersion <= M;
4178
4179            // Prior to N, layout params could change without requiring a
4180            // subsequent call to setLayoutParams() and they would usually
4181            // work. Partial layout breaks this assumption.
4182            sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
4183
4184            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4185            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4186            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
4187
4188            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4189            // in apps so we target check it to avoid breaking existing apps.
4190            sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N;
4191
4192            sCascadedDragDrop = targetSdkVersion < N;
4193
4194            sCompatibilityDone = true;
4195        }
4196    }
4197
4198    /**
4199     * Constructor that is called when inflating a view from XML. This is called
4200     * when a view is being constructed from an XML file, supplying attributes
4201     * that were specified in the XML file. This version uses a default style of
4202     * 0, so the only attribute values applied are those in the Context's Theme
4203     * and the given AttributeSet.
4204     *
4205     * <p>
4206     * The method onFinishInflate() will be called after all children have been
4207     * added.
4208     *
4209     * @param context The Context the view is running in, through which it can
4210     *        access the current theme, resources, etc.
4211     * @param attrs The attributes of the XML tag that is inflating the view.
4212     * @see #View(Context, AttributeSet, int)
4213     */
4214    public View(Context context, @Nullable AttributeSet attrs) {
4215        this(context, attrs, 0);
4216    }
4217
4218    /**
4219     * Perform inflation from XML and apply a class-specific base style from a
4220     * theme attribute. This constructor of View allows subclasses to use their
4221     * own base style when they are inflating. For example, a Button class's
4222     * constructor would call this version of the super class constructor and
4223     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4224     * allows the theme's button style to modify all of the base view attributes
4225     * (in particular its background) as well as the Button class's attributes.
4226     *
4227     * @param context The Context the view is running in, through which it can
4228     *        access the current theme, resources, etc.
4229     * @param attrs The attributes of the XML tag that is inflating the view.
4230     * @param defStyleAttr An attribute in the current theme that contains a
4231     *        reference to a style resource that supplies default values for
4232     *        the view. Can be 0 to not look for defaults.
4233     * @see #View(Context, AttributeSet)
4234     */
4235    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4236        this(context, attrs, defStyleAttr, 0);
4237    }
4238
4239    /**
4240     * Perform inflation from XML and apply a class-specific base style from a
4241     * theme attribute or style resource. This constructor of View allows
4242     * subclasses to use their own base style when they are inflating.
4243     * <p>
4244     * When determining the final value of a particular attribute, there are
4245     * four inputs that come into play:
4246     * <ol>
4247     * <li>Any attribute values in the given AttributeSet.
4248     * <li>The style resource specified in the AttributeSet (named "style").
4249     * <li>The default style specified by <var>defStyleAttr</var>.
4250     * <li>The default style specified by <var>defStyleRes</var>.
4251     * <li>The base values in this theme.
4252     * </ol>
4253     * <p>
4254     * Each of these inputs is considered in-order, with the first listed taking
4255     * precedence over the following ones. In other words, if in the
4256     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4257     * , then the button's text will <em>always</em> be black, regardless of
4258     * what is specified in any of the styles.
4259     *
4260     * @param context The Context the view is running in, through which it can
4261     *        access the current theme, resources, etc.
4262     * @param attrs The attributes of the XML tag that is inflating the view.
4263     * @param defStyleAttr An attribute in the current theme that contains a
4264     *        reference to a style resource that supplies default values for
4265     *        the view. Can be 0 to not look for defaults.
4266     * @param defStyleRes A resource identifier of a style resource that
4267     *        supplies default values for the view, used only if
4268     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4269     *        to not look for defaults.
4270     * @see #View(Context, AttributeSet, int)
4271     */
4272    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4273        this(context);
4274
4275        final TypedArray a = context.obtainStyledAttributes(
4276                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4277
4278        if (mDebugViewAttributes) {
4279            saveAttributeData(attrs, a);
4280        }
4281
4282        Drawable background = null;
4283
4284        int leftPadding = -1;
4285        int topPadding = -1;
4286        int rightPadding = -1;
4287        int bottomPadding = -1;
4288        int startPadding = UNDEFINED_PADDING;
4289        int endPadding = UNDEFINED_PADDING;
4290
4291        int padding = -1;
4292        int paddingHorizontal = -1;
4293        int paddingVertical = -1;
4294
4295        int viewFlagValues = 0;
4296        int viewFlagMasks = 0;
4297
4298        boolean setScrollContainer = false;
4299
4300        int x = 0;
4301        int y = 0;
4302
4303        float tx = 0;
4304        float ty = 0;
4305        float tz = 0;
4306        float elevation = 0;
4307        float rotation = 0;
4308        float rotationX = 0;
4309        float rotationY = 0;
4310        float sx = 1f;
4311        float sy = 1f;
4312        boolean transformSet = false;
4313
4314        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4315        int overScrollMode = mOverScrollMode;
4316        boolean initializeScrollbars = false;
4317        boolean initializeScrollIndicators = false;
4318
4319        boolean startPaddingDefined = false;
4320        boolean endPaddingDefined = false;
4321        boolean leftPaddingDefined = false;
4322        boolean rightPaddingDefined = false;
4323
4324        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4325
4326        final int N = a.getIndexCount();
4327        for (int i = 0; i < N; i++) {
4328            int attr = a.getIndex(i);
4329            switch (attr) {
4330                case com.android.internal.R.styleable.View_background:
4331                    background = a.getDrawable(attr);
4332                    break;
4333                case com.android.internal.R.styleable.View_padding:
4334                    padding = a.getDimensionPixelSize(attr, -1);
4335                    mUserPaddingLeftInitial = padding;
4336                    mUserPaddingRightInitial = padding;
4337                    leftPaddingDefined = true;
4338                    rightPaddingDefined = true;
4339                    break;
4340                case com.android.internal.R.styleable.View_paddingHorizontal:
4341                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4342                    mUserPaddingLeftInitial = paddingHorizontal;
4343                    mUserPaddingRightInitial = paddingHorizontal;
4344                    leftPaddingDefined = true;
4345                    rightPaddingDefined = true;
4346                    break;
4347                case com.android.internal.R.styleable.View_paddingVertical:
4348                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4349                    break;
4350                 case com.android.internal.R.styleable.View_paddingLeft:
4351                    leftPadding = a.getDimensionPixelSize(attr, -1);
4352                    mUserPaddingLeftInitial = leftPadding;
4353                    leftPaddingDefined = true;
4354                    break;
4355                case com.android.internal.R.styleable.View_paddingTop:
4356                    topPadding = a.getDimensionPixelSize(attr, -1);
4357                    break;
4358                case com.android.internal.R.styleable.View_paddingRight:
4359                    rightPadding = a.getDimensionPixelSize(attr, -1);
4360                    mUserPaddingRightInitial = rightPadding;
4361                    rightPaddingDefined = true;
4362                    break;
4363                case com.android.internal.R.styleable.View_paddingBottom:
4364                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4365                    break;
4366                case com.android.internal.R.styleable.View_paddingStart:
4367                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4368                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4369                    break;
4370                case com.android.internal.R.styleable.View_paddingEnd:
4371                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4372                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4373                    break;
4374                case com.android.internal.R.styleable.View_scrollX:
4375                    x = a.getDimensionPixelOffset(attr, 0);
4376                    break;
4377                case com.android.internal.R.styleable.View_scrollY:
4378                    y = a.getDimensionPixelOffset(attr, 0);
4379                    break;
4380                case com.android.internal.R.styleable.View_alpha:
4381                    setAlpha(a.getFloat(attr, 1f));
4382                    break;
4383                case com.android.internal.R.styleable.View_transformPivotX:
4384                    setPivotX(a.getDimension(attr, 0));
4385                    break;
4386                case com.android.internal.R.styleable.View_transformPivotY:
4387                    setPivotY(a.getDimension(attr, 0));
4388                    break;
4389                case com.android.internal.R.styleable.View_translationX:
4390                    tx = a.getDimension(attr, 0);
4391                    transformSet = true;
4392                    break;
4393                case com.android.internal.R.styleable.View_translationY:
4394                    ty = a.getDimension(attr, 0);
4395                    transformSet = true;
4396                    break;
4397                case com.android.internal.R.styleable.View_translationZ:
4398                    tz = a.getDimension(attr, 0);
4399                    transformSet = true;
4400                    break;
4401                case com.android.internal.R.styleable.View_elevation:
4402                    elevation = a.getDimension(attr, 0);
4403                    transformSet = true;
4404                    break;
4405                case com.android.internal.R.styleable.View_rotation:
4406                    rotation = a.getFloat(attr, 0);
4407                    transformSet = true;
4408                    break;
4409                case com.android.internal.R.styleable.View_rotationX:
4410                    rotationX = a.getFloat(attr, 0);
4411                    transformSet = true;
4412                    break;
4413                case com.android.internal.R.styleable.View_rotationY:
4414                    rotationY = a.getFloat(attr, 0);
4415                    transformSet = true;
4416                    break;
4417                case com.android.internal.R.styleable.View_scaleX:
4418                    sx = a.getFloat(attr, 1f);
4419                    transformSet = true;
4420                    break;
4421                case com.android.internal.R.styleable.View_scaleY:
4422                    sy = a.getFloat(attr, 1f);
4423                    transformSet = true;
4424                    break;
4425                case com.android.internal.R.styleable.View_id:
4426                    mID = a.getResourceId(attr, NO_ID);
4427                    break;
4428                case com.android.internal.R.styleable.View_tag:
4429                    mTag = a.getText(attr);
4430                    break;
4431                case com.android.internal.R.styleable.View_fitsSystemWindows:
4432                    if (a.getBoolean(attr, false)) {
4433                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4434                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4435                    }
4436                    break;
4437                case com.android.internal.R.styleable.View_focusable:
4438                    if (a.getBoolean(attr, false)) {
4439                        viewFlagValues |= FOCUSABLE;
4440                        viewFlagMasks |= FOCUSABLE_MASK;
4441                    }
4442                    break;
4443                case com.android.internal.R.styleable.View_focusableInTouchMode:
4444                    if (a.getBoolean(attr, false)) {
4445                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4446                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4447                    }
4448                    break;
4449                case com.android.internal.R.styleable.View_clickable:
4450                    if (a.getBoolean(attr, false)) {
4451                        viewFlagValues |= CLICKABLE;
4452                        viewFlagMasks |= CLICKABLE;
4453                    }
4454                    break;
4455                case com.android.internal.R.styleable.View_longClickable:
4456                    if (a.getBoolean(attr, false)) {
4457                        viewFlagValues |= LONG_CLICKABLE;
4458                        viewFlagMasks |= LONG_CLICKABLE;
4459                    }
4460                    break;
4461                case com.android.internal.R.styleable.View_contextClickable:
4462                    if (a.getBoolean(attr, false)) {
4463                        viewFlagValues |= CONTEXT_CLICKABLE;
4464                        viewFlagMasks |= CONTEXT_CLICKABLE;
4465                    }
4466                    break;
4467                case com.android.internal.R.styleable.View_saveEnabled:
4468                    if (!a.getBoolean(attr, true)) {
4469                        viewFlagValues |= SAVE_DISABLED;
4470                        viewFlagMasks |= SAVE_DISABLED_MASK;
4471                    }
4472                    break;
4473                case com.android.internal.R.styleable.View_duplicateParentState:
4474                    if (a.getBoolean(attr, false)) {
4475                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4476                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4477                    }
4478                    break;
4479                case com.android.internal.R.styleable.View_visibility:
4480                    final int visibility = a.getInt(attr, 0);
4481                    if (visibility != 0) {
4482                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4483                        viewFlagMasks |= VISIBILITY_MASK;
4484                    }
4485                    break;
4486                case com.android.internal.R.styleable.View_layoutDirection:
4487                    // Clear any layout direction flags (included resolved bits) already set
4488                    mPrivateFlags2 &=
4489                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4490                    // Set the layout direction flags depending on the value of the attribute
4491                    final int layoutDirection = a.getInt(attr, -1);
4492                    final int value = (layoutDirection != -1) ?
4493                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4494                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4495                    break;
4496                case com.android.internal.R.styleable.View_drawingCacheQuality:
4497                    final int cacheQuality = a.getInt(attr, 0);
4498                    if (cacheQuality != 0) {
4499                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4500                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4501                    }
4502                    break;
4503                case com.android.internal.R.styleable.View_contentDescription:
4504                    setContentDescription(a.getString(attr));
4505                    break;
4506                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4507                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4508                    break;
4509                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4510                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4511                    break;
4512                case com.android.internal.R.styleable.View_labelFor:
4513                    setLabelFor(a.getResourceId(attr, NO_ID));
4514                    break;
4515                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4516                    if (!a.getBoolean(attr, true)) {
4517                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4518                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4519                    }
4520                    break;
4521                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4522                    if (!a.getBoolean(attr, true)) {
4523                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4524                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4525                    }
4526                    break;
4527                case R.styleable.View_scrollbars:
4528                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4529                    if (scrollbars != SCROLLBARS_NONE) {
4530                        viewFlagValues |= scrollbars;
4531                        viewFlagMasks |= SCROLLBARS_MASK;
4532                        initializeScrollbars = true;
4533                    }
4534                    break;
4535                //noinspection deprecation
4536                case R.styleable.View_fadingEdge:
4537                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4538                        // Ignore the attribute starting with ICS
4539                        break;
4540                    }
4541                    // With builds < ICS, fall through and apply fading edges
4542                case R.styleable.View_requiresFadingEdge:
4543                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4544                    if (fadingEdge != FADING_EDGE_NONE) {
4545                        viewFlagValues |= fadingEdge;
4546                        viewFlagMasks |= FADING_EDGE_MASK;
4547                        initializeFadingEdgeInternal(a);
4548                    }
4549                    break;
4550                case R.styleable.View_scrollbarStyle:
4551                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4552                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4553                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4554                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4555                    }
4556                    break;
4557                case R.styleable.View_isScrollContainer:
4558                    setScrollContainer = true;
4559                    if (a.getBoolean(attr, false)) {
4560                        setScrollContainer(true);
4561                    }
4562                    break;
4563                case com.android.internal.R.styleable.View_keepScreenOn:
4564                    if (a.getBoolean(attr, false)) {
4565                        viewFlagValues |= KEEP_SCREEN_ON;
4566                        viewFlagMasks |= KEEP_SCREEN_ON;
4567                    }
4568                    break;
4569                case R.styleable.View_filterTouchesWhenObscured:
4570                    if (a.getBoolean(attr, false)) {
4571                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4572                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4573                    }
4574                    break;
4575                case R.styleable.View_nextFocusLeft:
4576                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4577                    break;
4578                case R.styleable.View_nextFocusRight:
4579                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4580                    break;
4581                case R.styleable.View_nextFocusUp:
4582                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4583                    break;
4584                case R.styleable.View_nextFocusDown:
4585                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4586                    break;
4587                case R.styleable.View_nextFocusForward:
4588                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4589                    break;
4590                case R.styleable.View_nextClusterForward:
4591                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4592                    break;
4593                case R.styleable.View_nextSectionForward:
4594                    mNextSectionForwardId = a.getResourceId(attr, View.NO_ID);
4595                    break;
4596                case R.styleable.View_minWidth:
4597                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4598                    break;
4599                case R.styleable.View_minHeight:
4600                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4601                    break;
4602                case R.styleable.View_onClick:
4603                    if (context.isRestricted()) {
4604                        throw new IllegalStateException("The android:onClick attribute cannot "
4605                                + "be used within a restricted context");
4606                    }
4607
4608                    final String handlerName = a.getString(attr);
4609                    if (handlerName != null) {
4610                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4611                    }
4612                    break;
4613                case R.styleable.View_overScrollMode:
4614                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4615                    break;
4616                case R.styleable.View_verticalScrollbarPosition:
4617                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4618                    break;
4619                case R.styleable.View_layerType:
4620                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4621                    break;
4622                case R.styleable.View_textDirection:
4623                    // Clear any text direction flag already set
4624                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4625                    // Set the text direction flags depending on the value of the attribute
4626                    final int textDirection = a.getInt(attr, -1);
4627                    if (textDirection != -1) {
4628                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4629                    }
4630                    break;
4631                case R.styleable.View_textAlignment:
4632                    // Clear any text alignment flag already set
4633                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4634                    // Set the text alignment flag depending on the value of the attribute
4635                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4636                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4637                    break;
4638                case R.styleable.View_importantForAccessibility:
4639                    setImportantForAccessibility(a.getInt(attr,
4640                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4641                    break;
4642                case R.styleable.View_accessibilityLiveRegion:
4643                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4644                    break;
4645                case R.styleable.View_transitionName:
4646                    setTransitionName(a.getString(attr));
4647                    break;
4648                case R.styleable.View_nestedScrollingEnabled:
4649                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4650                    break;
4651                case R.styleable.View_stateListAnimator:
4652                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4653                            a.getResourceId(attr, 0)));
4654                    break;
4655                case R.styleable.View_backgroundTint:
4656                    // This will get applied later during setBackground().
4657                    if (mBackgroundTint == null) {
4658                        mBackgroundTint = new TintInfo();
4659                    }
4660                    mBackgroundTint.mTintList = a.getColorStateList(
4661                            R.styleable.View_backgroundTint);
4662                    mBackgroundTint.mHasTintList = true;
4663                    break;
4664                case R.styleable.View_backgroundTintMode:
4665                    // This will get applied later during setBackground().
4666                    if (mBackgroundTint == null) {
4667                        mBackgroundTint = new TintInfo();
4668                    }
4669                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4670                            R.styleable.View_backgroundTintMode, -1), null);
4671                    mBackgroundTint.mHasTintMode = true;
4672                    break;
4673                case R.styleable.View_outlineProvider:
4674                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4675                            PROVIDER_BACKGROUND));
4676                    break;
4677                case R.styleable.View_foreground:
4678                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4679                        setForeground(a.getDrawable(attr));
4680                    }
4681                    break;
4682                case R.styleable.View_foregroundGravity:
4683                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4684                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4685                    }
4686                    break;
4687                case R.styleable.View_foregroundTintMode:
4688                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4689                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4690                    }
4691                    break;
4692                case R.styleable.View_foregroundTint:
4693                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4694                        setForegroundTintList(a.getColorStateList(attr));
4695                    }
4696                    break;
4697                case R.styleable.View_foregroundInsidePadding:
4698                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4699                        if (mForegroundInfo == null) {
4700                            mForegroundInfo = new ForegroundInfo();
4701                        }
4702                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4703                                mForegroundInfo.mInsidePadding);
4704                    }
4705                    break;
4706                case R.styleable.View_scrollIndicators:
4707                    final int scrollIndicators =
4708                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4709                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4710                    if (scrollIndicators != 0) {
4711                        mPrivateFlags3 |= scrollIndicators;
4712                        initializeScrollIndicators = true;
4713                    }
4714                    break;
4715                case R.styleable.View_pointerIcon:
4716                    final int resourceId = a.getResourceId(attr, 0);
4717                    if (resourceId != 0) {
4718                        setPointerIcon(PointerIcon.load(
4719                                context.getResources(), resourceId));
4720                    } else {
4721                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4722                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4723                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
4724                        }
4725                    }
4726                    break;
4727                case R.styleable.View_forceHasOverlappingRendering:
4728                    if (a.peekValue(attr) != null) {
4729                        forceHasOverlappingRendering(a.getBoolean(attr, true));
4730                    }
4731                    break;
4732                case R.styleable.View_tooltip:
4733                    setTooltip(a.getText(attr));
4734                    break;
4735                case R.styleable.View_keyboardNavigationCluster:
4736                    if (a.peekValue(attr) != null) {
4737                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
4738                    }
4739                    break;
4740                case R.styleable.View_keyboardNavigationSection:
4741                    if (a.peekValue(attr) != null) {
4742                        setKeyboardNavigationSection(a.getBoolean(attr, true));
4743                    }
4744                    break;
4745            }
4746        }
4747
4748        setOverScrollMode(overScrollMode);
4749
4750        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4751        // the resolved layout direction). Those cached values will be used later during padding
4752        // resolution.
4753        mUserPaddingStart = startPadding;
4754        mUserPaddingEnd = endPadding;
4755
4756        if (background != null) {
4757            setBackground(background);
4758        }
4759
4760        // setBackground above will record that padding is currently provided by the background.
4761        // If we have padding specified via xml, record that here instead and use it.
4762        mLeftPaddingDefined = leftPaddingDefined;
4763        mRightPaddingDefined = rightPaddingDefined;
4764
4765        if (padding >= 0) {
4766            leftPadding = padding;
4767            topPadding = padding;
4768            rightPadding = padding;
4769            bottomPadding = padding;
4770            mUserPaddingLeftInitial = padding;
4771            mUserPaddingRightInitial = padding;
4772        } else {
4773            if (paddingHorizontal >= 0) {
4774                leftPadding = paddingHorizontal;
4775                rightPadding = paddingHorizontal;
4776                mUserPaddingLeftInitial = paddingHorizontal;
4777                mUserPaddingRightInitial = paddingHorizontal;
4778            }
4779            if (paddingVertical >= 0) {
4780                topPadding = paddingVertical;
4781                bottomPadding = paddingVertical;
4782            }
4783        }
4784
4785        if (isRtlCompatibilityMode()) {
4786            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4787            // left / right padding are used if defined (meaning here nothing to do). If they are not
4788            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4789            // start / end and resolve them as left / right (layout direction is not taken into account).
4790            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4791            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4792            // defined.
4793            if (!mLeftPaddingDefined && startPaddingDefined) {
4794                leftPadding = startPadding;
4795            }
4796            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4797            if (!mRightPaddingDefined && endPaddingDefined) {
4798                rightPadding = endPadding;
4799            }
4800            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4801        } else {
4802            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4803            // values defined. Otherwise, left /right values are used.
4804            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4805            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4806            // defined.
4807            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4808
4809            if (mLeftPaddingDefined && !hasRelativePadding) {
4810                mUserPaddingLeftInitial = leftPadding;
4811            }
4812            if (mRightPaddingDefined && !hasRelativePadding) {
4813                mUserPaddingRightInitial = rightPadding;
4814            }
4815        }
4816
4817        internalSetPadding(
4818                mUserPaddingLeftInitial,
4819                topPadding >= 0 ? topPadding : mPaddingTop,
4820                mUserPaddingRightInitial,
4821                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4822
4823        if (viewFlagMasks != 0) {
4824            setFlags(viewFlagValues, viewFlagMasks);
4825        }
4826
4827        if (initializeScrollbars) {
4828            initializeScrollbarsInternal(a);
4829        }
4830
4831        if (initializeScrollIndicators) {
4832            initializeScrollIndicatorsInternal();
4833        }
4834
4835        a.recycle();
4836
4837        // Needs to be called after mViewFlags is set
4838        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4839            recomputePadding();
4840        }
4841
4842        if (x != 0 || y != 0) {
4843            scrollTo(x, y);
4844        }
4845
4846        if (transformSet) {
4847            setTranslationX(tx);
4848            setTranslationY(ty);
4849            setTranslationZ(tz);
4850            setElevation(elevation);
4851            setRotation(rotation);
4852            setRotationX(rotationX);
4853            setRotationY(rotationY);
4854            setScaleX(sx);
4855            setScaleY(sy);
4856        }
4857
4858        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4859            setScrollContainer(true);
4860        }
4861
4862        computeOpaqueFlags();
4863    }
4864
4865    /**
4866     * An implementation of OnClickListener that attempts to lazily load a
4867     * named click handling method from a parent or ancestor context.
4868     */
4869    private static class DeclaredOnClickListener implements OnClickListener {
4870        private final View mHostView;
4871        private final String mMethodName;
4872
4873        private Method mResolvedMethod;
4874        private Context mResolvedContext;
4875
4876        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4877            mHostView = hostView;
4878            mMethodName = methodName;
4879        }
4880
4881        @Override
4882        public void onClick(@NonNull View v) {
4883            if (mResolvedMethod == null) {
4884                resolveMethod(mHostView.getContext(), mMethodName);
4885            }
4886
4887            try {
4888                mResolvedMethod.invoke(mResolvedContext, v);
4889            } catch (IllegalAccessException e) {
4890                throw new IllegalStateException(
4891                        "Could not execute non-public method for android:onClick", e);
4892            } catch (InvocationTargetException e) {
4893                throw new IllegalStateException(
4894                        "Could not execute method for android:onClick", e);
4895            }
4896        }
4897
4898        @NonNull
4899        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4900            while (context != null) {
4901                try {
4902                    if (!context.isRestricted()) {
4903                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4904                        if (method != null) {
4905                            mResolvedMethod = method;
4906                            mResolvedContext = context;
4907                            return;
4908                        }
4909                    }
4910                } catch (NoSuchMethodException e) {
4911                    // Failed to find method, keep searching up the hierarchy.
4912                }
4913
4914                if (context instanceof ContextWrapper) {
4915                    context = ((ContextWrapper) context).getBaseContext();
4916                } else {
4917                    // Can't search up the hierarchy, null out and fail.
4918                    context = null;
4919                }
4920            }
4921
4922            final int id = mHostView.getId();
4923            final String idText = id == NO_ID ? "" : " with id '"
4924                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4925            throw new IllegalStateException("Could not find method " + mMethodName
4926                    + "(View) in a parent or ancestor Context for android:onClick "
4927                    + "attribute defined on view " + mHostView.getClass() + idText);
4928        }
4929    }
4930
4931    /**
4932     * Non-public constructor for use in testing
4933     */
4934    View() {
4935        mResources = null;
4936        mRenderNode = RenderNode.create(getClass().getName(), this);
4937    }
4938
4939    final boolean debugDraw() {
4940        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
4941    }
4942
4943    private static SparseArray<String> getAttributeMap() {
4944        if (mAttributeMap == null) {
4945            mAttributeMap = new SparseArray<>();
4946        }
4947        return mAttributeMap;
4948    }
4949
4950    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4951        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4952        final int indexCount = t.getIndexCount();
4953        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4954
4955        int i = 0;
4956
4957        // Store raw XML attributes.
4958        for (int j = 0; j < attrsCount; ++j) {
4959            attributes[i] = attrs.getAttributeName(j);
4960            attributes[i + 1] = attrs.getAttributeValue(j);
4961            i += 2;
4962        }
4963
4964        // Store resolved styleable attributes.
4965        final Resources res = t.getResources();
4966        final SparseArray<String> attributeMap = getAttributeMap();
4967        for (int j = 0; j < indexCount; ++j) {
4968            final int index = t.getIndex(j);
4969            if (!t.hasValueOrEmpty(index)) {
4970                // Value is undefined. Skip it.
4971                continue;
4972            }
4973
4974            final int resourceId = t.getResourceId(index, 0);
4975            if (resourceId == 0) {
4976                // Value is not a reference. Skip it.
4977                continue;
4978            }
4979
4980            String resourceName = attributeMap.get(resourceId);
4981            if (resourceName == null) {
4982                try {
4983                    resourceName = res.getResourceName(resourceId);
4984                } catch (Resources.NotFoundException e) {
4985                    resourceName = "0x" + Integer.toHexString(resourceId);
4986                }
4987                attributeMap.put(resourceId, resourceName);
4988            }
4989
4990            attributes[i] = resourceName;
4991            attributes[i + 1] = t.getString(index);
4992            i += 2;
4993        }
4994
4995        // Trim to fit contents.
4996        final String[] trimmed = new String[i];
4997        System.arraycopy(attributes, 0, trimmed, 0, i);
4998        mAttributes = trimmed;
4999    }
5000
5001    public String toString() {
5002        StringBuilder out = new StringBuilder(128);
5003        out.append(getClass().getName());
5004        out.append('{');
5005        out.append(Integer.toHexString(System.identityHashCode(this)));
5006        out.append(' ');
5007        switch (mViewFlags&VISIBILITY_MASK) {
5008            case VISIBLE: out.append('V'); break;
5009            case INVISIBLE: out.append('I'); break;
5010            case GONE: out.append('G'); break;
5011            default: out.append('.'); break;
5012        }
5013        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
5014        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5015        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5016        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5017        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5018        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5019        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5020        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5021        out.append(' ');
5022        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5023        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5024        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5025        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5026            out.append('p');
5027        } else {
5028            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5029        }
5030        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5031        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5032        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5033        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5034        out.append(' ');
5035        out.append(mLeft);
5036        out.append(',');
5037        out.append(mTop);
5038        out.append('-');
5039        out.append(mRight);
5040        out.append(',');
5041        out.append(mBottom);
5042        final int id = getId();
5043        if (id != NO_ID) {
5044            out.append(" #");
5045            out.append(Integer.toHexString(id));
5046            final Resources r = mResources;
5047            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5048                try {
5049                    String pkgname;
5050                    switch (id&0xff000000) {
5051                        case 0x7f000000:
5052                            pkgname="app";
5053                            break;
5054                        case 0x01000000:
5055                            pkgname="android";
5056                            break;
5057                        default:
5058                            pkgname = r.getResourcePackageName(id);
5059                            break;
5060                    }
5061                    String typename = r.getResourceTypeName(id);
5062                    String entryname = r.getResourceEntryName(id);
5063                    out.append(" ");
5064                    out.append(pkgname);
5065                    out.append(":");
5066                    out.append(typename);
5067                    out.append("/");
5068                    out.append(entryname);
5069                } catch (Resources.NotFoundException e) {
5070                }
5071            }
5072        }
5073        out.append("}");
5074        return out.toString();
5075    }
5076
5077    /**
5078     * <p>
5079     * Initializes the fading edges from a given set of styled attributes. This
5080     * method should be called by subclasses that need fading edges and when an
5081     * instance of these subclasses is created programmatically rather than
5082     * being inflated from XML. This method is automatically called when the XML
5083     * is inflated.
5084     * </p>
5085     *
5086     * @param a the styled attributes set to initialize the fading edges from
5087     *
5088     * @removed
5089     */
5090    protected void initializeFadingEdge(TypedArray a) {
5091        // This method probably shouldn't have been included in the SDK to begin with.
5092        // It relies on 'a' having been initialized using an attribute filter array that is
5093        // not publicly available to the SDK. The old method has been renamed
5094        // to initializeFadingEdgeInternal and hidden for framework use only;
5095        // this one initializes using defaults to make it safe to call for apps.
5096
5097        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5098
5099        initializeFadingEdgeInternal(arr);
5100
5101        arr.recycle();
5102    }
5103
5104    /**
5105     * <p>
5106     * Initializes the fading edges from a given set of styled attributes. This
5107     * method should be called by subclasses that need fading edges and when an
5108     * instance of these subclasses is created programmatically rather than
5109     * being inflated from XML. This method is automatically called when the XML
5110     * is inflated.
5111     * </p>
5112     *
5113     * @param a the styled attributes set to initialize the fading edges from
5114     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5115     */
5116    protected void initializeFadingEdgeInternal(TypedArray a) {
5117        initScrollCache();
5118
5119        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5120                R.styleable.View_fadingEdgeLength,
5121                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5122    }
5123
5124    /**
5125     * Returns the size of the vertical faded edges used to indicate that more
5126     * content in this view is visible.
5127     *
5128     * @return The size in pixels of the vertical faded edge or 0 if vertical
5129     *         faded edges are not enabled for this view.
5130     * @attr ref android.R.styleable#View_fadingEdgeLength
5131     */
5132    public int getVerticalFadingEdgeLength() {
5133        if (isVerticalFadingEdgeEnabled()) {
5134            ScrollabilityCache cache = mScrollCache;
5135            if (cache != null) {
5136                return cache.fadingEdgeLength;
5137            }
5138        }
5139        return 0;
5140    }
5141
5142    /**
5143     * Set the size of the faded edge used to indicate that more content in this
5144     * view is available.  Will not change whether the fading edge is enabled; use
5145     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5146     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5147     * for the vertical or horizontal fading edges.
5148     *
5149     * @param length The size in pixels of the faded edge used to indicate that more
5150     *        content in this view is visible.
5151     */
5152    public void setFadingEdgeLength(int length) {
5153        initScrollCache();
5154        mScrollCache.fadingEdgeLength = length;
5155    }
5156
5157    /**
5158     * Returns the size of the horizontal faded edges used to indicate that more
5159     * content in this view is visible.
5160     *
5161     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5162     *         faded edges are not enabled for this view.
5163     * @attr ref android.R.styleable#View_fadingEdgeLength
5164     */
5165    public int getHorizontalFadingEdgeLength() {
5166        if (isHorizontalFadingEdgeEnabled()) {
5167            ScrollabilityCache cache = mScrollCache;
5168            if (cache != null) {
5169                return cache.fadingEdgeLength;
5170            }
5171        }
5172        return 0;
5173    }
5174
5175    /**
5176     * Returns the width of the vertical scrollbar.
5177     *
5178     * @return The width in pixels of the vertical scrollbar or 0 if there
5179     *         is no vertical scrollbar.
5180     */
5181    public int getVerticalScrollbarWidth() {
5182        ScrollabilityCache cache = mScrollCache;
5183        if (cache != null) {
5184            ScrollBarDrawable scrollBar = cache.scrollBar;
5185            if (scrollBar != null) {
5186                int size = scrollBar.getSize(true);
5187                if (size <= 0) {
5188                    size = cache.scrollBarSize;
5189                }
5190                return size;
5191            }
5192            return 0;
5193        }
5194        return 0;
5195    }
5196
5197    /**
5198     * Returns the height of the horizontal scrollbar.
5199     *
5200     * @return The height in pixels of the horizontal scrollbar or 0 if
5201     *         there is no horizontal scrollbar.
5202     */
5203    protected int getHorizontalScrollbarHeight() {
5204        ScrollabilityCache cache = mScrollCache;
5205        if (cache != null) {
5206            ScrollBarDrawable scrollBar = cache.scrollBar;
5207            if (scrollBar != null) {
5208                int size = scrollBar.getSize(false);
5209                if (size <= 0) {
5210                    size = cache.scrollBarSize;
5211                }
5212                return size;
5213            }
5214            return 0;
5215        }
5216        return 0;
5217    }
5218
5219    /**
5220     * <p>
5221     * Initializes the scrollbars from a given set of styled attributes. This
5222     * method should be called by subclasses that need scrollbars and when an
5223     * instance of these subclasses is created programmatically rather than
5224     * being inflated from XML. This method is automatically called when the XML
5225     * is inflated.
5226     * </p>
5227     *
5228     * @param a the styled attributes set to initialize the scrollbars from
5229     *
5230     * @removed
5231     */
5232    protected void initializeScrollbars(TypedArray a) {
5233        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5234        // using the View filter array which is not available to the SDK. As such, internal
5235        // framework usage now uses initializeScrollbarsInternal and we grab a default
5236        // TypedArray with the right filter instead here.
5237        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5238
5239        initializeScrollbarsInternal(arr);
5240
5241        // We ignored the method parameter. Recycle the one we actually did use.
5242        arr.recycle();
5243    }
5244
5245    /**
5246     * <p>
5247     * Initializes the scrollbars from a given set of styled attributes. This
5248     * method should be called by subclasses that need scrollbars and when an
5249     * instance of these subclasses is created programmatically rather than
5250     * being inflated from XML. This method is automatically called when the XML
5251     * is inflated.
5252     * </p>
5253     *
5254     * @param a the styled attributes set to initialize the scrollbars from
5255     * @hide
5256     */
5257    protected void initializeScrollbarsInternal(TypedArray a) {
5258        initScrollCache();
5259
5260        final ScrollabilityCache scrollabilityCache = mScrollCache;
5261
5262        if (scrollabilityCache.scrollBar == null) {
5263            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5264            scrollabilityCache.scrollBar.setState(getDrawableState());
5265            scrollabilityCache.scrollBar.setCallback(this);
5266        }
5267
5268        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5269
5270        if (!fadeScrollbars) {
5271            scrollabilityCache.state = ScrollabilityCache.ON;
5272        }
5273        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5274
5275
5276        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5277                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5278                        .getScrollBarFadeDuration());
5279        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5280                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5281                ViewConfiguration.getScrollDefaultDelay());
5282
5283
5284        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5285                com.android.internal.R.styleable.View_scrollbarSize,
5286                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5287
5288        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5289        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5290
5291        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5292        if (thumb != null) {
5293            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5294        }
5295
5296        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5297                false);
5298        if (alwaysDraw) {
5299            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5300        }
5301
5302        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5303        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5304
5305        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5306        if (thumb != null) {
5307            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5308        }
5309
5310        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5311                false);
5312        if (alwaysDraw) {
5313            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5314        }
5315
5316        // Apply layout direction to the new Drawables if needed
5317        final int layoutDirection = getLayoutDirection();
5318        if (track != null) {
5319            track.setLayoutDirection(layoutDirection);
5320        }
5321        if (thumb != null) {
5322            thumb.setLayoutDirection(layoutDirection);
5323        }
5324
5325        // Re-apply user/background padding so that scrollbar(s) get added
5326        resolvePadding();
5327    }
5328
5329    private void initializeScrollIndicatorsInternal() {
5330        // Some day maybe we'll break this into top/left/start/etc. and let the
5331        // client control it. Until then, you can have any scroll indicator you
5332        // want as long as it's a 1dp foreground-colored rectangle.
5333        if (mScrollIndicatorDrawable == null) {
5334            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5335        }
5336    }
5337
5338    /**
5339     * <p>
5340     * Initalizes the scrollability cache if necessary.
5341     * </p>
5342     */
5343    private void initScrollCache() {
5344        if (mScrollCache == null) {
5345            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5346        }
5347    }
5348
5349    private ScrollabilityCache getScrollCache() {
5350        initScrollCache();
5351        return mScrollCache;
5352    }
5353
5354    /**
5355     * Set the position of the vertical scroll bar. Should be one of
5356     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5357     * {@link #SCROLLBAR_POSITION_RIGHT}.
5358     *
5359     * @param position Where the vertical scroll bar should be positioned.
5360     */
5361    public void setVerticalScrollbarPosition(int position) {
5362        if (mVerticalScrollbarPosition != position) {
5363            mVerticalScrollbarPosition = position;
5364            computeOpaqueFlags();
5365            resolvePadding();
5366        }
5367    }
5368
5369    /**
5370     * @return The position where the vertical scroll bar will show, if applicable.
5371     * @see #setVerticalScrollbarPosition(int)
5372     */
5373    public int getVerticalScrollbarPosition() {
5374        return mVerticalScrollbarPosition;
5375    }
5376
5377    boolean isOnScrollbar(float x, float y) {
5378        if (mScrollCache == null) {
5379            return false;
5380        }
5381        x += getScrollX();
5382        y += getScrollY();
5383        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5384            final Rect bounds = mScrollCache.mScrollBarBounds;
5385            getVerticalScrollBarBounds(bounds);
5386            if (bounds.contains((int)x, (int)y)) {
5387                return true;
5388            }
5389        }
5390        if (isHorizontalScrollBarEnabled()) {
5391            final Rect bounds = mScrollCache.mScrollBarBounds;
5392            getHorizontalScrollBarBounds(bounds);
5393            if (bounds.contains((int)x, (int)y)) {
5394                return true;
5395            }
5396        }
5397        return false;
5398    }
5399
5400    boolean isOnScrollbarThumb(float x, float y) {
5401        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5402    }
5403
5404    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5405        if (mScrollCache == null) {
5406            return false;
5407        }
5408        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5409            x += getScrollX();
5410            y += getScrollY();
5411            final Rect bounds = mScrollCache.mScrollBarBounds;
5412            getVerticalScrollBarBounds(bounds);
5413            final int range = computeVerticalScrollRange();
5414            final int offset = computeVerticalScrollOffset();
5415            final int extent = computeVerticalScrollExtent();
5416            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5417                    extent, range);
5418            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5419                    extent, range, offset);
5420            final int thumbTop = bounds.top + thumbOffset;
5421            if (x >= bounds.left && x <= bounds.right && y >= thumbTop
5422                    && y <= thumbTop + thumbLength) {
5423                return true;
5424            }
5425        }
5426        return false;
5427    }
5428
5429    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5430        if (mScrollCache == null) {
5431            return false;
5432        }
5433        if (isHorizontalScrollBarEnabled()) {
5434            x += getScrollX();
5435            y += getScrollY();
5436            final Rect bounds = mScrollCache.mScrollBarBounds;
5437            getHorizontalScrollBarBounds(bounds);
5438            final int range = computeHorizontalScrollRange();
5439            final int offset = computeHorizontalScrollOffset();
5440            final int extent = computeHorizontalScrollExtent();
5441            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5442                    extent, range);
5443            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5444                    extent, range, offset);
5445            final int thumbLeft = bounds.left + thumbOffset;
5446            if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
5447                    && y <= bounds.bottom) {
5448                return true;
5449            }
5450        }
5451        return false;
5452    }
5453
5454    boolean isDraggingScrollBar() {
5455        return mScrollCache != null
5456                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5457    }
5458
5459    /**
5460     * Sets the state of all scroll indicators.
5461     * <p>
5462     * See {@link #setScrollIndicators(int, int)} for usage information.
5463     *
5464     * @param indicators a bitmask of indicators that should be enabled, or
5465     *                   {@code 0} to disable all indicators
5466     * @see #setScrollIndicators(int, int)
5467     * @see #getScrollIndicators()
5468     * @attr ref android.R.styleable#View_scrollIndicators
5469     */
5470    public void setScrollIndicators(@ScrollIndicators int indicators) {
5471        setScrollIndicators(indicators,
5472                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5473    }
5474
5475    /**
5476     * Sets the state of the scroll indicators specified by the mask. To change
5477     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5478     * <p>
5479     * When a scroll indicator is enabled, it will be displayed if the view
5480     * can scroll in the direction of the indicator.
5481     * <p>
5482     * Multiple indicator types may be enabled or disabled by passing the
5483     * logical OR of the desired types. If multiple types are specified, they
5484     * will all be set to the same enabled state.
5485     * <p>
5486     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5487     *
5488     * @param indicators the indicator direction, or the logical OR of multiple
5489     *             indicator directions. One or more of:
5490     *             <ul>
5491     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5492     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5493     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5494     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5495     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5496     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5497     *             </ul>
5498     * @see #setScrollIndicators(int)
5499     * @see #getScrollIndicators()
5500     * @attr ref android.R.styleable#View_scrollIndicators
5501     */
5502    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5503        // Shift and sanitize mask.
5504        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5505        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5506
5507        // Shift and mask indicators.
5508        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5509        indicators &= mask;
5510
5511        // Merge with non-masked flags.
5512        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5513
5514        if (mPrivateFlags3 != updatedFlags) {
5515            mPrivateFlags3 = updatedFlags;
5516
5517            if (indicators != 0) {
5518                initializeScrollIndicatorsInternal();
5519            }
5520            invalidate();
5521        }
5522    }
5523
5524    /**
5525     * Returns a bitmask representing the enabled scroll indicators.
5526     * <p>
5527     * For example, if the top and left scroll indicators are enabled and all
5528     * other indicators are disabled, the return value will be
5529     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5530     * <p>
5531     * To check whether the bottom scroll indicator is enabled, use the value
5532     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5533     *
5534     * @return a bitmask representing the enabled scroll indicators
5535     */
5536    @ScrollIndicators
5537    public int getScrollIndicators() {
5538        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5539                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5540    }
5541
5542    ListenerInfo getListenerInfo() {
5543        if (mListenerInfo != null) {
5544            return mListenerInfo;
5545        }
5546        mListenerInfo = new ListenerInfo();
5547        return mListenerInfo;
5548    }
5549
5550    /**
5551     * Register a callback to be invoked when the scroll X or Y positions of
5552     * this view change.
5553     * <p>
5554     * <b>Note:</b> Some views handle scrolling independently from View and may
5555     * have their own separate listeners for scroll-type events. For example,
5556     * {@link android.widget.ListView ListView} allows clients to register an
5557     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5558     * to listen for changes in list scroll position.
5559     *
5560     * @param l The listener to notify when the scroll X or Y position changes.
5561     * @see android.view.View#getScrollX()
5562     * @see android.view.View#getScrollY()
5563     */
5564    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5565        getListenerInfo().mOnScrollChangeListener = l;
5566    }
5567
5568    /**
5569     * Register a callback to be invoked when focus of this view changed.
5570     *
5571     * @param l The callback that will run.
5572     */
5573    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5574        getListenerInfo().mOnFocusChangeListener = l;
5575    }
5576
5577    /**
5578     * Add a listener that will be called when the bounds of the view change due to
5579     * layout processing.
5580     *
5581     * @param listener The listener that will be called when layout bounds change.
5582     */
5583    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5584        ListenerInfo li = getListenerInfo();
5585        if (li.mOnLayoutChangeListeners == null) {
5586            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5587        }
5588        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5589            li.mOnLayoutChangeListeners.add(listener);
5590        }
5591    }
5592
5593    /**
5594     * Remove a listener for layout changes.
5595     *
5596     * @param listener The listener for layout bounds change.
5597     */
5598    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5599        ListenerInfo li = mListenerInfo;
5600        if (li == null || li.mOnLayoutChangeListeners == null) {
5601            return;
5602        }
5603        li.mOnLayoutChangeListeners.remove(listener);
5604    }
5605
5606    /**
5607     * Add a listener for attach state changes.
5608     *
5609     * This listener will be called whenever this view is attached or detached
5610     * from a window. Remove the listener using
5611     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5612     *
5613     * @param listener Listener to attach
5614     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5615     */
5616    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5617        ListenerInfo li = getListenerInfo();
5618        if (li.mOnAttachStateChangeListeners == null) {
5619            li.mOnAttachStateChangeListeners
5620                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5621        }
5622        li.mOnAttachStateChangeListeners.add(listener);
5623    }
5624
5625    /**
5626     * Remove a listener for attach state changes. The listener will receive no further
5627     * notification of window attach/detach events.
5628     *
5629     * @param listener Listener to remove
5630     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5631     */
5632    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5633        ListenerInfo li = mListenerInfo;
5634        if (li == null || li.mOnAttachStateChangeListeners == null) {
5635            return;
5636        }
5637        li.mOnAttachStateChangeListeners.remove(listener);
5638    }
5639
5640    /**
5641     * Returns the focus-change callback registered for this view.
5642     *
5643     * @return The callback, or null if one is not registered.
5644     */
5645    public OnFocusChangeListener getOnFocusChangeListener() {
5646        ListenerInfo li = mListenerInfo;
5647        return li != null ? li.mOnFocusChangeListener : null;
5648    }
5649
5650    /**
5651     * Register a callback to be invoked when this view is clicked. If this view is not
5652     * clickable, it becomes clickable.
5653     *
5654     * @param l The callback that will run
5655     *
5656     * @see #setClickable(boolean)
5657     */
5658    public void setOnClickListener(@Nullable OnClickListener l) {
5659        if (!isClickable()) {
5660            setClickable(true);
5661        }
5662        getListenerInfo().mOnClickListener = l;
5663    }
5664
5665    /**
5666     * Return whether this view has an attached OnClickListener.  Returns
5667     * true if there is a listener, false if there is none.
5668     */
5669    public boolean hasOnClickListeners() {
5670        ListenerInfo li = mListenerInfo;
5671        return (li != null && li.mOnClickListener != null);
5672    }
5673
5674    /**
5675     * Register a callback to be invoked when this view is clicked and held. If this view is not
5676     * long clickable, it becomes long clickable.
5677     *
5678     * @param l The callback that will run
5679     *
5680     * @see #setLongClickable(boolean)
5681     */
5682    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5683        if (!isLongClickable()) {
5684            setLongClickable(true);
5685        }
5686        getListenerInfo().mOnLongClickListener = l;
5687    }
5688
5689    /**
5690     * Register a callback to be invoked when this view is context clicked. If the view is not
5691     * context clickable, it becomes context clickable.
5692     *
5693     * @param l The callback that will run
5694     * @see #setContextClickable(boolean)
5695     */
5696    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5697        if (!isContextClickable()) {
5698            setContextClickable(true);
5699        }
5700        getListenerInfo().mOnContextClickListener = l;
5701    }
5702
5703    /**
5704     * Register a callback to be invoked when the context menu for this view is
5705     * being built. If this view is not long clickable, it becomes long clickable.
5706     *
5707     * @param l The callback that will run
5708     *
5709     */
5710    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5711        if (!isLongClickable()) {
5712            setLongClickable(true);
5713        }
5714        getListenerInfo().mOnCreateContextMenuListener = l;
5715    }
5716
5717    /**
5718     * Set an observer to collect stats for each frame rendered for this view.
5719     *
5720     * @hide
5721     */
5722    public void addFrameMetricsListener(Window window,
5723            Window.OnFrameMetricsAvailableListener listener,
5724            Handler handler) {
5725        if (mAttachInfo != null) {
5726            if (mAttachInfo.mThreadedRenderer != null) {
5727                if (mFrameMetricsObservers == null) {
5728                    mFrameMetricsObservers = new ArrayList<>();
5729                }
5730
5731                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5732                        handler.getLooper(), listener);
5733                mFrameMetricsObservers.add(fmo);
5734                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
5735            } else {
5736                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5737            }
5738        } else {
5739            if (mFrameMetricsObservers == null) {
5740                mFrameMetricsObservers = new ArrayList<>();
5741            }
5742
5743            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5744                    handler.getLooper(), listener);
5745            mFrameMetricsObservers.add(fmo);
5746        }
5747    }
5748
5749    /**
5750     * Remove observer configured to collect frame stats for this view.
5751     *
5752     * @hide
5753     */
5754    public void removeFrameMetricsListener(
5755            Window.OnFrameMetricsAvailableListener listener) {
5756        ThreadedRenderer renderer = getThreadedRenderer();
5757        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
5758        if (fmo == null) {
5759            throw new IllegalArgumentException(
5760                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
5761        }
5762
5763        if (mFrameMetricsObservers != null) {
5764            mFrameMetricsObservers.remove(fmo);
5765            if (renderer != null) {
5766                renderer.removeFrameMetricsObserver(fmo);
5767            }
5768        }
5769    }
5770
5771    private void registerPendingFrameMetricsObservers() {
5772        if (mFrameMetricsObservers != null) {
5773            ThreadedRenderer renderer = getThreadedRenderer();
5774            if (renderer != null) {
5775                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
5776                    renderer.addFrameMetricsObserver(fmo);
5777                }
5778            } else {
5779                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5780            }
5781        }
5782    }
5783
5784    private FrameMetricsObserver findFrameMetricsObserver(
5785            Window.OnFrameMetricsAvailableListener listener) {
5786        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
5787            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
5788            if (observer.mListener == listener) {
5789                return observer;
5790            }
5791        }
5792
5793        return null;
5794    }
5795
5796    /**
5797     * Call this view's OnClickListener, if it is defined.  Performs all normal
5798     * actions associated with clicking: reporting accessibility event, playing
5799     * a sound, etc.
5800     *
5801     * @return True there was an assigned OnClickListener that was called, false
5802     *         otherwise is returned.
5803     */
5804    public boolean performClick() {
5805        final boolean result;
5806        final ListenerInfo li = mListenerInfo;
5807        if (li != null && li.mOnClickListener != null) {
5808            playSoundEffect(SoundEffectConstants.CLICK);
5809            li.mOnClickListener.onClick(this);
5810            result = true;
5811        } else {
5812            result = false;
5813        }
5814
5815        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5816        return result;
5817    }
5818
5819    /**
5820     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5821     * this only calls the listener, and does not do any associated clicking
5822     * actions like reporting an accessibility event.
5823     *
5824     * @return True there was an assigned OnClickListener that was called, false
5825     *         otherwise is returned.
5826     */
5827    public boolean callOnClick() {
5828        ListenerInfo li = mListenerInfo;
5829        if (li != null && li.mOnClickListener != null) {
5830            li.mOnClickListener.onClick(this);
5831            return true;
5832        }
5833        return false;
5834    }
5835
5836    /**
5837     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5838     * context menu if the OnLongClickListener did not consume the event.
5839     *
5840     * @return {@code true} if one of the above receivers consumed the event,
5841     *         {@code false} otherwise
5842     */
5843    public boolean performLongClick() {
5844        return performLongClickInternal(mLongClickX, mLongClickY);
5845    }
5846
5847    /**
5848     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5849     * context menu if the OnLongClickListener did not consume the event,
5850     * anchoring it to an (x,y) coordinate.
5851     *
5852     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5853     *          to disable anchoring
5854     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5855     *          to disable anchoring
5856     * @return {@code true} if one of the above receivers consumed the event,
5857     *         {@code false} otherwise
5858     */
5859    public boolean performLongClick(float x, float y) {
5860        mLongClickX = x;
5861        mLongClickY = y;
5862        final boolean handled = performLongClick();
5863        mLongClickX = Float.NaN;
5864        mLongClickY = Float.NaN;
5865        return handled;
5866    }
5867
5868    /**
5869     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5870     * context menu if the OnLongClickListener did not consume the event,
5871     * optionally anchoring it to an (x,y) coordinate.
5872     *
5873     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5874     *          to disable anchoring
5875     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5876     *          to disable anchoring
5877     * @return {@code true} if one of the above receivers consumed the event,
5878     *         {@code false} otherwise
5879     */
5880    private boolean performLongClickInternal(float x, float y) {
5881        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5882
5883        boolean handled = false;
5884        final ListenerInfo li = mListenerInfo;
5885        if (li != null && li.mOnLongClickListener != null) {
5886            handled = li.mOnLongClickListener.onLongClick(View.this);
5887        }
5888        if (!handled) {
5889            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5890            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5891        }
5892        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
5893            if (!handled) {
5894                handled = showLongClickTooltip((int) x, (int) y);
5895            }
5896        }
5897        if (handled) {
5898            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5899        }
5900        return handled;
5901    }
5902
5903    /**
5904     * Call this view's OnContextClickListener, if it is defined.
5905     *
5906     * @param x the x coordinate of the context click
5907     * @param y the y coordinate of the context click
5908     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5909     *         otherwise.
5910     */
5911    public boolean performContextClick(float x, float y) {
5912        return performContextClick();
5913    }
5914
5915    /**
5916     * Call this view's OnContextClickListener, if it is defined.
5917     *
5918     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5919     *         otherwise.
5920     */
5921    public boolean performContextClick() {
5922        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5923
5924        boolean handled = false;
5925        ListenerInfo li = mListenerInfo;
5926        if (li != null && li.mOnContextClickListener != null) {
5927            handled = li.mOnContextClickListener.onContextClick(View.this);
5928        }
5929        if (handled) {
5930            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5931        }
5932        return handled;
5933    }
5934
5935    /**
5936     * Performs button-related actions during a touch down event.
5937     *
5938     * @param event The event.
5939     * @return True if the down was consumed.
5940     *
5941     * @hide
5942     */
5943    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5944        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5945            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5946            showContextMenu(event.getX(), event.getY());
5947            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5948            return true;
5949        }
5950        return false;
5951    }
5952
5953    /**
5954     * Shows the context menu for this view.
5955     *
5956     * @return {@code true} if the context menu was shown, {@code false}
5957     *         otherwise
5958     * @see #showContextMenu(float, float)
5959     */
5960    public boolean showContextMenu() {
5961        return getParent().showContextMenuForChild(this);
5962    }
5963
5964    /**
5965     * Shows the context menu for this view anchored to the specified
5966     * view-relative coordinate.
5967     *
5968     * @param x the X coordinate in pixels relative to the view to which the
5969     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5970     * @param y the Y coordinate in pixels relative to the view to which the
5971     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5972     * @return {@code true} if the context menu was shown, {@code false}
5973     *         otherwise
5974     */
5975    public boolean showContextMenu(float x, float y) {
5976        return getParent().showContextMenuForChild(this, x, y);
5977    }
5978
5979    /**
5980     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5981     *
5982     * @param callback Callback that will control the lifecycle of the action mode
5983     * @return The new action mode if it is started, null otherwise
5984     *
5985     * @see ActionMode
5986     * @see #startActionMode(android.view.ActionMode.Callback, int)
5987     */
5988    public ActionMode startActionMode(ActionMode.Callback callback) {
5989        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5990    }
5991
5992    /**
5993     * Start an action mode with the given type.
5994     *
5995     * @param callback Callback that will control the lifecycle of the action mode
5996     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5997     * @return The new action mode if it is started, null otherwise
5998     *
5999     * @see ActionMode
6000     */
6001    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6002        ViewParent parent = getParent();
6003        if (parent == null) return null;
6004        try {
6005            return parent.startActionModeForChild(this, callback, type);
6006        } catch (AbstractMethodError ame) {
6007            // Older implementations of custom views might not implement this.
6008            return parent.startActionModeForChild(this, callback);
6009        }
6010    }
6011
6012    /**
6013     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6014     * Context, creating a unique View identifier to retrieve the result.
6015     *
6016     * @param intent The Intent to be started.
6017     * @param requestCode The request code to use.
6018     * @hide
6019     */
6020    public void startActivityForResult(Intent intent, int requestCode) {
6021        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6022        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6023    }
6024
6025    /**
6026     * If this View corresponds to the calling who, dispatches the activity result.
6027     * @param who The identifier for the targeted View to receive the result.
6028     * @param requestCode The integer request code originally supplied to
6029     *                    startActivityForResult(), allowing you to identify who this
6030     *                    result came from.
6031     * @param resultCode The integer result code returned by the child activity
6032     *                   through its setResult().
6033     * @param data An Intent, which can return result data to the caller
6034     *               (various data can be attached to Intent "extras").
6035     * @return {@code true} if the activity result was dispatched.
6036     * @hide
6037     */
6038    public boolean dispatchActivityResult(
6039            String who, int requestCode, int resultCode, Intent data) {
6040        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6041            onActivityResult(requestCode, resultCode, data);
6042            mStartActivityRequestWho = null;
6043            return true;
6044        }
6045        return false;
6046    }
6047
6048    /**
6049     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6050     *
6051     * @param requestCode The integer request code originally supplied to
6052     *                    startActivityForResult(), allowing you to identify who this
6053     *                    result came from.
6054     * @param resultCode The integer result code returned by the child activity
6055     *                   through its setResult().
6056     * @param data An Intent, which can return result data to the caller
6057     *               (various data can be attached to Intent "extras").
6058     * @hide
6059     */
6060    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6061        // Do nothing.
6062    }
6063
6064    /**
6065     * Register a callback to be invoked when a hardware key is pressed in this view.
6066     * Key presses in software input methods will generally not trigger the methods of
6067     * this listener.
6068     * @param l the key listener to attach to this view
6069     */
6070    public void setOnKeyListener(OnKeyListener l) {
6071        getListenerInfo().mOnKeyListener = l;
6072    }
6073
6074    /**
6075     * Register a callback to be invoked when a touch event is sent to this view.
6076     * @param l the touch listener to attach to this view
6077     */
6078    public void setOnTouchListener(OnTouchListener l) {
6079        getListenerInfo().mOnTouchListener = l;
6080    }
6081
6082    /**
6083     * Register a callback to be invoked when a generic motion event is sent to this view.
6084     * @param l the generic motion listener to attach to this view
6085     */
6086    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6087        getListenerInfo().mOnGenericMotionListener = l;
6088    }
6089
6090    /**
6091     * Register a callback to be invoked when a hover event is sent to this view.
6092     * @param l the hover listener to attach to this view
6093     */
6094    public void setOnHoverListener(OnHoverListener l) {
6095        getListenerInfo().mOnHoverListener = l;
6096    }
6097
6098    /**
6099     * Register a drag event listener callback object for this View. The parameter is
6100     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6101     * View, the system calls the
6102     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6103     * @param l An implementation of {@link android.view.View.OnDragListener}.
6104     */
6105    public void setOnDragListener(OnDragListener l) {
6106        getListenerInfo().mOnDragListener = l;
6107    }
6108
6109    /**
6110     * Give this view focus. This will cause
6111     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6112     *
6113     * Note: this does not check whether this {@link View} should get focus, it just
6114     * gives it focus no matter what.  It should only be called internally by framework
6115     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6116     *
6117     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6118     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6119     *        focus moved when requestFocus() is called. It may not always
6120     *        apply, in which case use the default View.FOCUS_DOWN.
6121     * @param previouslyFocusedRect The rectangle of the view that had focus
6122     *        prior in this View's coordinate system.
6123     */
6124    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6125        if (DBG) {
6126            System.out.println(this + " requestFocus()");
6127        }
6128
6129        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6130            mPrivateFlags |= PFLAG_FOCUSED;
6131
6132            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6133
6134            if (mParent != null) {
6135                mParent.requestChildFocus(this, this);
6136                if (!isKeyboardNavigationCluster() && mParent instanceof ViewGroup) {
6137                    ((ViewGroup) mParent).saveFocus();
6138                }
6139            }
6140
6141            if (mAttachInfo != null) {
6142                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6143            }
6144
6145            onFocusChanged(true, direction, previouslyFocusedRect);
6146            refreshDrawableState();
6147        }
6148    }
6149
6150    /**
6151     * Sets this view's preference for reveal behavior when it gains focus.
6152     *
6153     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6154     * this view would prefer to be brought fully into view when it gains focus.
6155     * For example, a text field that a user is meant to type into. Other views such
6156     * as scrolling containers may prefer to opt-out of this behavior.</p>
6157     *
6158     * <p>The default value for views is true, though subclasses may change this
6159     * based on their preferred behavior.</p>
6160     *
6161     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6162     *
6163     * @see #getRevealOnFocusHint()
6164     */
6165    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6166        if (revealOnFocus) {
6167            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6168        } else {
6169            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6170        }
6171    }
6172
6173    /**
6174     * Returns this view's preference for reveal behavior when it gains focus.
6175     *
6176     * <p>When this method returns true for a child view requesting focus, ancestor
6177     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6178     * should make a best effort to make the newly focused child fully visible to the user.
6179     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6180     * other properties affecting visibility to the user as part of the focus change.</p>
6181     *
6182     * @return true if this view would prefer to become fully visible when it gains focus,
6183     *         false if it would prefer not to disrupt scroll positioning
6184     *
6185     * @see #setRevealOnFocusHint(boolean)
6186     */
6187    public final boolean getRevealOnFocusHint() {
6188        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6189    }
6190
6191    /**
6192     * Populates <code>outRect</code> with the hotspot bounds. By default,
6193     * the hotspot bounds are identical to the screen bounds.
6194     *
6195     * @param outRect rect to populate with hotspot bounds
6196     * @hide Only for internal use by views and widgets.
6197     */
6198    public void getHotspotBounds(Rect outRect) {
6199        final Drawable background = getBackground();
6200        if (background != null) {
6201            background.getHotspotBounds(outRect);
6202        } else {
6203            getBoundsOnScreen(outRect);
6204        }
6205    }
6206
6207    /**
6208     * Request that a rectangle of this view be visible on the screen,
6209     * scrolling if necessary just enough.
6210     *
6211     * <p>A View should call this if it maintains some notion of which part
6212     * of its content is interesting.  For example, a text editing view
6213     * should call this when its cursor moves.
6214     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6215     * It should not be affected by which part of the View is currently visible or its scroll
6216     * position.
6217     *
6218     * @param rectangle The rectangle in the View's content coordinate space
6219     * @return Whether any parent scrolled.
6220     */
6221    public boolean requestRectangleOnScreen(Rect rectangle) {
6222        return requestRectangleOnScreen(rectangle, false);
6223    }
6224
6225    /**
6226     * Request that a rectangle of this view be visible on the screen,
6227     * scrolling if necessary just enough.
6228     *
6229     * <p>A View should call this if it maintains some notion of which part
6230     * of its content is interesting.  For example, a text editing view
6231     * should call this when its cursor moves.
6232     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6233     * It should not be affected by which part of the View is currently visible or its scroll
6234     * position.
6235     * <p>When <code>immediate</code> is set to true, scrolling will not be
6236     * animated.
6237     *
6238     * @param rectangle The rectangle in the View's content coordinate space
6239     * @param immediate True to forbid animated scrolling, false otherwise
6240     * @return Whether any parent scrolled.
6241     */
6242    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6243        if (mParent == null) {
6244            return false;
6245        }
6246
6247        View child = this;
6248
6249        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6250        position.set(rectangle);
6251
6252        ViewParent parent = mParent;
6253        boolean scrolled = false;
6254        while (parent != null) {
6255            rectangle.set((int) position.left, (int) position.top,
6256                    (int) position.right, (int) position.bottom);
6257
6258            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6259
6260            if (!(parent instanceof View)) {
6261                break;
6262            }
6263
6264            // move it from child's content coordinate space to parent's content coordinate space
6265            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6266
6267            child = (View) parent;
6268            parent = child.getParent();
6269        }
6270
6271        return scrolled;
6272    }
6273
6274    /**
6275     * Called when this view wants to give up focus. If focus is cleared
6276     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6277     * <p>
6278     * <strong>Note:</strong> When a View clears focus the framework is trying
6279     * to give focus to the first focusable View from the top. Hence, if this
6280     * View is the first from the top that can take focus, then all callbacks
6281     * related to clearing focus will be invoked after which the framework will
6282     * give focus to this view.
6283     * </p>
6284     */
6285    public void clearFocus() {
6286        if (DBG) {
6287            System.out.println(this + " clearFocus()");
6288        }
6289
6290        clearFocusInternal(null, true, true);
6291    }
6292
6293    /**
6294     * Clears focus from the view, optionally propagating the change up through
6295     * the parent hierarchy and requesting that the root view place new focus.
6296     *
6297     * @param propagate whether to propagate the change up through the parent
6298     *            hierarchy
6299     * @param refocus when propagate is true, specifies whether to request the
6300     *            root view place new focus
6301     */
6302    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6303        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6304            mPrivateFlags &= ~PFLAG_FOCUSED;
6305
6306            if (propagate && mParent != null) {
6307                mParent.clearChildFocus(this);
6308            }
6309
6310            onFocusChanged(false, 0, null);
6311            refreshDrawableState();
6312
6313            if (propagate && (!refocus || !rootViewRequestFocus())) {
6314                notifyGlobalFocusCleared(this);
6315            }
6316        }
6317    }
6318
6319    void notifyGlobalFocusCleared(View oldFocus) {
6320        if (oldFocus != null && mAttachInfo != null) {
6321            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6322        }
6323    }
6324
6325    boolean rootViewRequestFocus() {
6326        final View root = getRootView();
6327        return root != null && root.requestFocus();
6328    }
6329
6330    /**
6331     * Called internally by the view system when a new view is getting focus.
6332     * This is what clears the old focus.
6333     * <p>
6334     * <b>NOTE:</b> The parent view's focused child must be updated manually
6335     * after calling this method. Otherwise, the view hierarchy may be left in
6336     * an inconstent state.
6337     */
6338    void unFocus(View focused) {
6339        if (DBG) {
6340            System.out.println(this + " unFocus()");
6341        }
6342
6343        clearFocusInternal(focused, false, false);
6344    }
6345
6346    /**
6347     * Returns true if this view has focus itself, or is the ancestor of the
6348     * view that has focus.
6349     *
6350     * @return True if this view has or contains focus, false otherwise.
6351     */
6352    @ViewDebug.ExportedProperty(category = "focus")
6353    public boolean hasFocus() {
6354        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6355    }
6356
6357    /**
6358     * Returns true if this view is focusable or if it contains a reachable View
6359     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
6360     * is a View whose parents do not block descendants focus.
6361     *
6362     * Only {@link #VISIBLE} views are considered focusable.
6363     *
6364     * @return True if the view is focusable or if the view contains a focusable
6365     *         View, false otherwise.
6366     *
6367     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6368     * @see ViewGroup#getTouchscreenBlocksFocus()
6369     */
6370    public boolean hasFocusable() {
6371        if (!isFocusableInTouchMode()) {
6372            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6373                final ViewGroup g = (ViewGroup) p;
6374                if (g.shouldBlockFocusForTouchscreen()) {
6375                    return false;
6376                }
6377            }
6378        }
6379        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
6380    }
6381
6382    /**
6383     * Called by the view system when the focus state of this view changes.
6384     * When the focus change event is caused by directional navigation, direction
6385     * and previouslyFocusedRect provide insight into where the focus is coming from.
6386     * When overriding, be sure to call up through to the super class so that
6387     * the standard focus handling will occur.
6388     *
6389     * @param gainFocus True if the View has focus; false otherwise.
6390     * @param direction The direction focus has moved when requestFocus()
6391     *                  is called to give this view focus. Values are
6392     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6393     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6394     *                  It may not always apply, in which case use the default.
6395     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6396     *        system, of the previously focused view.  If applicable, this will be
6397     *        passed in as finer grained information about where the focus is coming
6398     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6399     */
6400    @CallSuper
6401    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6402            @Nullable Rect previouslyFocusedRect) {
6403        if (gainFocus) {
6404            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6405        } else {
6406            notifyViewAccessibilityStateChangedIfNeeded(
6407                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6408        }
6409
6410        InputMethodManager imm = InputMethodManager.peekInstance();
6411        if (!gainFocus) {
6412            if (isPressed()) {
6413                setPressed(false);
6414            }
6415            if (imm != null && mAttachInfo != null
6416                    && mAttachInfo.mHasWindowFocus) {
6417                imm.focusOut(this);
6418            }
6419            onFocusLost();
6420        } else if (imm != null && mAttachInfo != null
6421                && mAttachInfo.mHasWindowFocus) {
6422            imm.focusIn(this);
6423        }
6424
6425        invalidate(true);
6426        ListenerInfo li = mListenerInfo;
6427        if (li != null && li.mOnFocusChangeListener != null) {
6428            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6429        }
6430
6431        if (mAttachInfo != null) {
6432            mAttachInfo.mKeyDispatchState.reset(this);
6433        }
6434    }
6435
6436    /**
6437     * Sends an accessibility event of the given type. If accessibility is
6438     * not enabled this method has no effect. The default implementation calls
6439     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6440     * to populate information about the event source (this View), then calls
6441     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6442     * populate the text content of the event source including its descendants,
6443     * and last calls
6444     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6445     * on its parent to request sending of the event to interested parties.
6446     * <p>
6447     * If an {@link AccessibilityDelegate} has been specified via calling
6448     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6449     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6450     * responsible for handling this call.
6451     * </p>
6452     *
6453     * @param eventType The type of the event to send, as defined by several types from
6454     * {@link android.view.accessibility.AccessibilityEvent}, such as
6455     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6456     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6457     *
6458     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6459     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6460     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6461     * @see AccessibilityDelegate
6462     */
6463    public void sendAccessibilityEvent(int eventType) {
6464        if (mAccessibilityDelegate != null) {
6465            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6466        } else {
6467            sendAccessibilityEventInternal(eventType);
6468        }
6469    }
6470
6471    /**
6472     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6473     * {@link AccessibilityEvent} to make an announcement which is related to some
6474     * sort of a context change for which none of the events representing UI transitions
6475     * is a good fit. For example, announcing a new page in a book. If accessibility
6476     * is not enabled this method does nothing.
6477     *
6478     * @param text The announcement text.
6479     */
6480    public void announceForAccessibility(CharSequence text) {
6481        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6482            AccessibilityEvent event = AccessibilityEvent.obtain(
6483                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6484            onInitializeAccessibilityEvent(event);
6485            event.getText().add(text);
6486            event.setContentDescription(null);
6487            mParent.requestSendAccessibilityEvent(this, event);
6488        }
6489    }
6490
6491    /**
6492     * @see #sendAccessibilityEvent(int)
6493     *
6494     * Note: Called from the default {@link AccessibilityDelegate}.
6495     *
6496     * @hide
6497     */
6498    public void sendAccessibilityEventInternal(int eventType) {
6499        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6500            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6501        }
6502    }
6503
6504    /**
6505     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6506     * takes as an argument an empty {@link AccessibilityEvent} and does not
6507     * perform a check whether accessibility is enabled.
6508     * <p>
6509     * If an {@link AccessibilityDelegate} has been specified via calling
6510     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6511     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6512     * is responsible for handling this call.
6513     * </p>
6514     *
6515     * @param event The event to send.
6516     *
6517     * @see #sendAccessibilityEvent(int)
6518     */
6519    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6520        if (mAccessibilityDelegate != null) {
6521            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6522        } else {
6523            sendAccessibilityEventUncheckedInternal(event);
6524        }
6525    }
6526
6527    /**
6528     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6529     *
6530     * Note: Called from the default {@link AccessibilityDelegate}.
6531     *
6532     * @hide
6533     */
6534    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6535        if (!isShown()) {
6536            return;
6537        }
6538        onInitializeAccessibilityEvent(event);
6539        // Only a subset of accessibility events populates text content.
6540        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6541            dispatchPopulateAccessibilityEvent(event);
6542        }
6543        // In the beginning we called #isShown(), so we know that getParent() is not null.
6544        getParent().requestSendAccessibilityEvent(this, event);
6545    }
6546
6547    /**
6548     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6549     * to its children for adding their text content to the event. Note that the
6550     * event text is populated in a separate dispatch path since we add to the
6551     * event not only the text of the source but also the text of all its descendants.
6552     * A typical implementation will call
6553     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6554     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6555     * on each child. Override this method if custom population of the event text
6556     * content is required.
6557     * <p>
6558     * If an {@link AccessibilityDelegate} has been specified via calling
6559     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6560     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6561     * is responsible for handling this call.
6562     * </p>
6563     * <p>
6564     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6565     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6566     * </p>
6567     *
6568     * @param event The event.
6569     *
6570     * @return True if the event population was completed.
6571     */
6572    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6573        if (mAccessibilityDelegate != null) {
6574            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6575        } else {
6576            return dispatchPopulateAccessibilityEventInternal(event);
6577        }
6578    }
6579
6580    /**
6581     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6582     *
6583     * Note: Called from the default {@link AccessibilityDelegate}.
6584     *
6585     * @hide
6586     */
6587    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6588        onPopulateAccessibilityEvent(event);
6589        return false;
6590    }
6591
6592    /**
6593     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6594     * giving a chance to this View to populate the accessibility event with its
6595     * text content. While this method is free to modify event
6596     * attributes other than text content, doing so should normally be performed in
6597     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6598     * <p>
6599     * Example: Adding formatted date string to an accessibility event in addition
6600     *          to the text added by the super implementation:
6601     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6602     *     super.onPopulateAccessibilityEvent(event);
6603     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6604     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6605     *         mCurrentDate.getTimeInMillis(), flags);
6606     *     event.getText().add(selectedDateUtterance);
6607     * }</pre>
6608     * <p>
6609     * If an {@link AccessibilityDelegate} has been specified via calling
6610     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6611     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6612     * is responsible for handling this call.
6613     * </p>
6614     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6615     * information to the event, in case the default implementation has basic information to add.
6616     * </p>
6617     *
6618     * @param event The accessibility event which to populate.
6619     *
6620     * @see #sendAccessibilityEvent(int)
6621     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6622     */
6623    @CallSuper
6624    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6625        if (mAccessibilityDelegate != null) {
6626            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6627        } else {
6628            onPopulateAccessibilityEventInternal(event);
6629        }
6630    }
6631
6632    /**
6633     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6634     *
6635     * Note: Called from the default {@link AccessibilityDelegate}.
6636     *
6637     * @hide
6638     */
6639    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6640    }
6641
6642    /**
6643     * Initializes an {@link AccessibilityEvent} with information about
6644     * this View which is the event source. In other words, the source of
6645     * an accessibility event is the view whose state change triggered firing
6646     * the event.
6647     * <p>
6648     * Example: Setting the password property of an event in addition
6649     *          to properties set by the super implementation:
6650     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6651     *     super.onInitializeAccessibilityEvent(event);
6652     *     event.setPassword(true);
6653     * }</pre>
6654     * <p>
6655     * If an {@link AccessibilityDelegate} has been specified via calling
6656     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6657     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6658     * is responsible for handling this call.
6659     * </p>
6660     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6661     * information to the event, in case the default implementation has basic information to add.
6662     * </p>
6663     * @param event The event to initialize.
6664     *
6665     * @see #sendAccessibilityEvent(int)
6666     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6667     */
6668    @CallSuper
6669    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6670        if (mAccessibilityDelegate != null) {
6671            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6672        } else {
6673            onInitializeAccessibilityEventInternal(event);
6674        }
6675    }
6676
6677    /**
6678     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6679     *
6680     * Note: Called from the default {@link AccessibilityDelegate}.
6681     *
6682     * @hide
6683     */
6684    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6685        event.setSource(this);
6686        event.setClassName(getAccessibilityClassName());
6687        event.setPackageName(getContext().getPackageName());
6688        event.setEnabled(isEnabled());
6689        event.setContentDescription(mContentDescription);
6690
6691        switch (event.getEventType()) {
6692            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6693                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6694                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6695                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6696                event.setItemCount(focusablesTempList.size());
6697                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6698                if (mAttachInfo != null) {
6699                    focusablesTempList.clear();
6700                }
6701            } break;
6702            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6703                CharSequence text = getIterableTextForAccessibility();
6704                if (text != null && text.length() > 0) {
6705                    event.setFromIndex(getAccessibilitySelectionStart());
6706                    event.setToIndex(getAccessibilitySelectionEnd());
6707                    event.setItemCount(text.length());
6708                }
6709            } break;
6710        }
6711    }
6712
6713    /**
6714     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6715     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6716     * This method is responsible for obtaining an accessibility node info from a
6717     * pool of reusable instances and calling
6718     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6719     * initialize the former.
6720     * <p>
6721     * Note: The client is responsible for recycling the obtained instance by calling
6722     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6723     * </p>
6724     *
6725     * @return A populated {@link AccessibilityNodeInfo}.
6726     *
6727     * @see AccessibilityNodeInfo
6728     */
6729    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6730        if (mAccessibilityDelegate != null) {
6731            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6732        } else {
6733            return createAccessibilityNodeInfoInternal();
6734        }
6735    }
6736
6737    /**
6738     * @see #createAccessibilityNodeInfo()
6739     *
6740     * @hide
6741     */
6742    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6743        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6744        if (provider != null) {
6745            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6746        } else {
6747            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6748            onInitializeAccessibilityNodeInfo(info);
6749            return info;
6750        }
6751    }
6752
6753    /**
6754     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6755     * The base implementation sets:
6756     * <ul>
6757     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6758     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6759     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6760     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6761     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6762     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6763     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6764     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6765     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6766     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6767     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6768     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6769     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6770     * </ul>
6771     * <p>
6772     * Subclasses should override this method, call the super implementation,
6773     * and set additional attributes.
6774     * </p>
6775     * <p>
6776     * If an {@link AccessibilityDelegate} has been specified via calling
6777     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6778     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6779     * is responsible for handling this call.
6780     * </p>
6781     *
6782     * @param info The instance to initialize.
6783     */
6784    @CallSuper
6785    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6786        if (mAccessibilityDelegate != null) {
6787            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6788        } else {
6789            onInitializeAccessibilityNodeInfoInternal(info);
6790        }
6791    }
6792
6793    /**
6794     * Gets the location of this view in screen coordinates.
6795     *
6796     * @param outRect The output location
6797     * @hide
6798     */
6799    public void getBoundsOnScreen(Rect outRect) {
6800        getBoundsOnScreen(outRect, false);
6801    }
6802
6803    /**
6804     * Gets the location of this view in screen coordinates.
6805     *
6806     * @param outRect The output location
6807     * @param clipToParent Whether to clip child bounds to the parent ones.
6808     * @hide
6809     */
6810    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6811        if (mAttachInfo == null) {
6812            return;
6813        }
6814
6815        RectF position = mAttachInfo.mTmpTransformRect;
6816        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6817
6818        if (!hasIdentityMatrix()) {
6819            getMatrix().mapRect(position);
6820        }
6821
6822        position.offset(mLeft, mTop);
6823
6824        ViewParent parent = mParent;
6825        while (parent instanceof View) {
6826            View parentView = (View) parent;
6827
6828            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6829
6830            if (clipToParent) {
6831                position.left = Math.max(position.left, 0);
6832                position.top = Math.max(position.top, 0);
6833                position.right = Math.min(position.right, parentView.getWidth());
6834                position.bottom = Math.min(position.bottom, parentView.getHeight());
6835            }
6836
6837            if (!parentView.hasIdentityMatrix()) {
6838                parentView.getMatrix().mapRect(position);
6839            }
6840
6841            position.offset(parentView.mLeft, parentView.mTop);
6842
6843            parent = parentView.mParent;
6844        }
6845
6846        if (parent instanceof ViewRootImpl) {
6847            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6848            position.offset(0, -viewRootImpl.mCurScrollY);
6849        }
6850
6851        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6852
6853        outRect.set(Math.round(position.left), Math.round(position.top),
6854                Math.round(position.right), Math.round(position.bottom));
6855    }
6856
6857    /**
6858     * Return the class name of this object to be used for accessibility purposes.
6859     * Subclasses should only override this if they are implementing something that
6860     * should be seen as a completely new class of view when used by accessibility,
6861     * unrelated to the class it is deriving from.  This is used to fill in
6862     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6863     */
6864    public CharSequence getAccessibilityClassName() {
6865        return View.class.getName();
6866    }
6867
6868    /**
6869     * Called when assist structure is being retrieved from a view as part of
6870     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6871     * @param structure Fill in with structured view data.  The default implementation
6872     * fills in all data that can be inferred from the view itself.
6873     *
6874     * @deprecated As of API O sub-classes should override
6875     * {@link #onProvideStructure(ViewStructure, int)} instead.
6876     */
6877    // TODO(b/33197203): set proper API above
6878    @Deprecated
6879    public void onProvideStructure(ViewStructure structure) {
6880        onProvideStructure(structure, 0);
6881    }
6882
6883    /**
6884     * Called when assist structure is being retrieved from a view as part of
6885     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} or as part
6886     * of an auto-fill request.
6887     *
6888     * <p>The default implementation fills in all data that can be inferred from the view itself.
6889     *
6890     * <p>The structure must be filled according to the request type, which is set in the
6891     * {@code flags} parameter - see the documentation on each flag for more details.
6892     *
6893     * @param structure Fill in with structured view data. The default implementation
6894     * fills in all data that can be inferred from the view itself.
6895     * @param flags optional flags (see {@link #ASSIST_FLAG_SANITIZED_TEXT} and
6896     * {@link #ASSIST_FLAG_NON_SANITIZED_TEXT} for more info).
6897     */
6898    public void onProvideStructure(ViewStructure structure, int flags) {
6899        boolean forAutoFill = (flags
6900                & (View.ASSIST_FLAG_SANITIZED_TEXT
6901                        | View.ASSIST_FLAG_NON_SANITIZED_TEXT)) != 0;
6902        final int id = mID;
6903        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6904                && (id&0x0000ffff) != 0) {
6905            String pkg, type, entry;
6906            try {
6907                final Resources res = getResources();
6908                entry = res.getResourceEntryName(id);
6909                type = res.getResourceTypeName(id);
6910                pkg = res.getResourcePackageName(id);
6911            } catch (Resources.NotFoundException e) {
6912                entry = type = pkg = null;
6913            }
6914            structure.setId(id, pkg, type, entry);
6915        } else {
6916            structure.setId(id, null, null, null);
6917        }
6918
6919        if (forAutoFill) {
6920            // The auto-fill id needs to be unique, but its value doesn't matter, so it's better to
6921            // reuse the accessibility id to save space.
6922            structure.setAutoFillId(getAccessibilityViewId());
6923        }
6924
6925        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6926        if (!hasIdentityMatrix()) {
6927            structure.setTransformation(getMatrix());
6928        }
6929        structure.setElevation(getZ());
6930        structure.setVisibility(getVisibility());
6931        structure.setEnabled(isEnabled());
6932        if (isClickable()) {
6933            structure.setClickable(true);
6934        }
6935        if (isFocusable()) {
6936            structure.setFocusable(true);
6937        }
6938        if (isFocused()) {
6939            structure.setFocused(true);
6940        }
6941        if (isAccessibilityFocused()) {
6942            structure.setAccessibilityFocused(true);
6943        }
6944        if (isSelected()) {
6945            structure.setSelected(true);
6946        }
6947        if (isActivated()) {
6948            structure.setActivated(true);
6949        }
6950        if (isLongClickable()) {
6951            structure.setLongClickable(true);
6952        }
6953        if (this instanceof Checkable) {
6954            structure.setCheckable(true);
6955            if (((Checkable)this).isChecked()) {
6956                structure.setChecked(true);
6957            }
6958        }
6959        if (isContextClickable()) {
6960            structure.setContextClickable(true);
6961        }
6962        structure.setClassName(getAccessibilityClassName().toString());
6963        structure.setContentDescription(getContentDescription());
6964    }
6965
6966    /**
6967     * Called when assist structure is being retrieved from a view as part of
6968     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6969     * generate additional virtual structure under this view.  The defaullt implementation
6970     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6971     * view's virtual accessibility nodes, if any.  You can override this for a more
6972     * optimal implementation providing this data.
6973     *
6974     * @deprecated As of API O, sub-classes should override
6975     * {@link #onProvideVirtualStructure(ViewStructure, int)} instead.
6976     */
6977    // TODO(b/33197203): set proper API above
6978    @Deprecated
6979    public void onProvideVirtualStructure(ViewStructure structure) {
6980        onProvideVirtualStructure(structure, 0);
6981    }
6982
6983    /**
6984     * Called when assist structure is being retrieved from a view as part of
6985     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} or as part
6986     * of an auto-fill request to generate additional virtual structure under this view.
6987     *
6988     * <p>The defaullt implementation uses {@link #getAccessibilityNodeProvider()} to try to
6989     * generate this from the view's virtual accessibility nodes, if any.  You can override this
6990     * for a more optimal implementation providing this data.
6991     *
6992     * <p>The structure must be filled according to the request type, which is set in the
6993     * {@code flags} parameter - see the documentation on each flag for more details.
6994     *
6995     * @param structure Fill in with structured view data.
6996     * @param flags optional flags (see {@link #ASSIST_FLAG_SANITIZED_TEXT} and
6997     * {@link #ASSIST_FLAG_NON_SANITIZED_TEXT} for more info).
6998     */
6999    public void onProvideVirtualStructure(ViewStructure structure, int flags) {
7000        boolean sanitize = (flags & View.ASSIST_FLAG_SANITIZED_TEXT) != 0;
7001
7002        if (sanitize) {
7003            // TODO(b/33197203): change populateVirtualStructure so it sanitizes data in this case.
7004            return;
7005        }
7006
7007        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7008        if (provider != null) {
7009            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7010            structure.setChildCount(1);
7011            ViewStructure root = structure.newChild(0);
7012            populateVirtualStructure(root, provider, info, flags);
7013            info.recycle();
7014        }
7015    }
7016
7017    private void populateVirtualStructure(ViewStructure structure,
7018            AccessibilityNodeProvider provider, AccessibilityNodeInfo info, int flags) {
7019        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7020                null, null, null);
7021        Rect rect = structure.getTempRect();
7022        info.getBoundsInParent(rect);
7023        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7024        structure.setVisibility(VISIBLE);
7025        structure.setEnabled(info.isEnabled());
7026        if (info.isClickable()) {
7027            structure.setClickable(true);
7028        }
7029        if (info.isFocusable()) {
7030            structure.setFocusable(true);
7031        }
7032        if (info.isFocused()) {
7033            structure.setFocused(true);
7034        }
7035        if (info.isAccessibilityFocused()) {
7036            structure.setAccessibilityFocused(true);
7037        }
7038        if (info.isSelected()) {
7039            structure.setSelected(true);
7040        }
7041        if (info.isLongClickable()) {
7042            structure.setLongClickable(true);
7043        }
7044        if (info.isCheckable()) {
7045            structure.setCheckable(true);
7046            if (info.isChecked()) {
7047                structure.setChecked(true);
7048            }
7049        }
7050        if (info.isContextClickable()) {
7051            structure.setContextClickable(true);
7052        }
7053        CharSequence cname = info.getClassName();
7054        structure.setClassName(cname != null ? cname.toString() : null);
7055        structure.setContentDescription(info.getContentDescription());
7056        if (info.getText() != null || info.getError() != null) {
7057            structure.setText(info.getText(), info.getTextSelectionStart(),
7058                    info.getTextSelectionEnd());
7059        }
7060        final int NCHILDREN = info.getChildCount();
7061        if (NCHILDREN > 0) {
7062            structure.setChildCount(NCHILDREN);
7063            for (int i=0; i<NCHILDREN; i++) {
7064                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
7065                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
7066                ViewStructure child = structure.newChild(i);
7067                populateVirtualStructure(child, provider, cinfo, flags);
7068                cinfo.recycle();
7069            }
7070        }
7071    }
7072
7073    /**
7074     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
7075     * implementation calls {@link #onProvideStructure} and
7076     * {@link #onProvideVirtualStructure}.
7077     *
7078     * @deprecated As of API O,  sub-classes should override
7079     * {@link #dispatchProvideStructure(ViewStructure, int)} instead.
7080     */
7081    // TODO(b/33197203): set proper API above
7082    @Deprecated
7083    public void dispatchProvideStructure(ViewStructure structure) {
7084        dispatchProvideStructure(structure, 0);
7085    }
7086
7087    /**
7088     * Dispatch creation of {@link ViewStructure} down the hierarchy.
7089     *
7090     * <p>The structure must be filled according to the request type, which is set in the
7091     * {@code flags} parameter - see the documentation on each flag for more details.
7092     *
7093     * <p>The default implementation calls {@link #onProvideStructure(ViewStructure, int)} and
7094     * {@link #onProvideVirtualStructure(ViewStructure, int)}.
7095     *
7096     * @param structure Fill in with structured view data.
7097     * @param flags optional flags (see {@link #ASSIST_FLAG_SANITIZED_TEXT} and
7098     * {@link #ASSIST_FLAG_NON_SANITIZED_TEXT} for more info).
7099     */
7100    public void dispatchProvideStructure(ViewStructure structure, int flags) {
7101        boolean forAutoFill = (flags
7102                & (View.ASSIST_FLAG_SANITIZED_TEXT
7103                        | View.ASSIST_FLAG_NON_SANITIZED_TEXT)) != 0;
7104
7105        boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
7106        if (!blocked) {
7107            onProvideStructure(structure, flags);
7108            onProvideVirtualStructure(structure, flags);
7109        } else {
7110            structure.setClassName(getAccessibilityClassName().toString());
7111            structure.setAssistBlocked(true);
7112        }
7113    }
7114
7115    /**
7116     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
7117     *
7118     * Note: Called from the default {@link AccessibilityDelegate}.
7119     *
7120     * @hide
7121     */
7122    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
7123        if (mAttachInfo == null) {
7124            return;
7125        }
7126
7127        Rect bounds = mAttachInfo.mTmpInvalRect;
7128
7129        getDrawingRect(bounds);
7130        info.setBoundsInParent(bounds);
7131
7132        getBoundsOnScreen(bounds, true);
7133        info.setBoundsInScreen(bounds);
7134
7135        ViewParent parent = getParentForAccessibility();
7136        if (parent instanceof View) {
7137            info.setParent((View) parent);
7138        }
7139
7140        if (mID != View.NO_ID) {
7141            View rootView = getRootView();
7142            if (rootView == null) {
7143                rootView = this;
7144            }
7145
7146            View label = rootView.findLabelForView(this, mID);
7147            if (label != null) {
7148                info.setLabeledBy(label);
7149            }
7150
7151            if ((mAttachInfo.mAccessibilityFetchFlags
7152                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
7153                    && Resources.resourceHasPackage(mID)) {
7154                try {
7155                    String viewId = getResources().getResourceName(mID);
7156                    info.setViewIdResourceName(viewId);
7157                } catch (Resources.NotFoundException nfe) {
7158                    /* ignore */
7159                }
7160            }
7161        }
7162
7163        if (mLabelForId != View.NO_ID) {
7164            View rootView = getRootView();
7165            if (rootView == null) {
7166                rootView = this;
7167            }
7168            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
7169            if (labeled != null) {
7170                info.setLabelFor(labeled);
7171            }
7172        }
7173
7174        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
7175            View rootView = getRootView();
7176            if (rootView == null) {
7177                rootView = this;
7178            }
7179            View next = rootView.findViewInsideOutShouldExist(this,
7180                    mAccessibilityTraversalBeforeId);
7181            if (next != null && next.includeForAccessibility()) {
7182                info.setTraversalBefore(next);
7183            }
7184        }
7185
7186        if (mAccessibilityTraversalAfterId != View.NO_ID) {
7187            View rootView = getRootView();
7188            if (rootView == null) {
7189                rootView = this;
7190            }
7191            View next = rootView.findViewInsideOutShouldExist(this,
7192                    mAccessibilityTraversalAfterId);
7193            if (next != null && next.includeForAccessibility()) {
7194                info.setTraversalAfter(next);
7195            }
7196        }
7197
7198        info.setVisibleToUser(isVisibleToUser());
7199
7200        info.setImportantForAccessibility(isImportantForAccessibility());
7201        info.setPackageName(mContext.getPackageName());
7202        info.setClassName(getAccessibilityClassName());
7203        info.setContentDescription(getContentDescription());
7204
7205        info.setEnabled(isEnabled());
7206        info.setClickable(isClickable());
7207        info.setFocusable(isFocusable());
7208        info.setFocused(isFocused());
7209        info.setAccessibilityFocused(isAccessibilityFocused());
7210        info.setSelected(isSelected());
7211        info.setLongClickable(isLongClickable());
7212        info.setContextClickable(isContextClickable());
7213        info.setLiveRegion(getAccessibilityLiveRegion());
7214
7215        // TODO: These make sense only if we are in an AdapterView but all
7216        // views can be selected. Maybe from accessibility perspective
7217        // we should report as selectable view in an AdapterView.
7218        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
7219        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
7220
7221        if (isFocusable()) {
7222            if (isFocused()) {
7223                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
7224            } else {
7225                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
7226            }
7227        }
7228
7229        if (!isAccessibilityFocused()) {
7230            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
7231        } else {
7232            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
7233        }
7234
7235        if (isClickable() && isEnabled()) {
7236            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
7237        }
7238
7239        if (isLongClickable() && isEnabled()) {
7240            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
7241        }
7242
7243        if (isContextClickable() && isEnabled()) {
7244            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
7245        }
7246
7247        CharSequence text = getIterableTextForAccessibility();
7248        if (text != null && text.length() > 0) {
7249            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
7250
7251            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
7252            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
7253            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
7254            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
7255                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
7256                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
7257        }
7258
7259        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
7260        populateAccessibilityNodeInfoDrawingOrderInParent(info);
7261    }
7262
7263    /**
7264     * Determine the order in which this view will be drawn relative to its siblings for a11y
7265     *
7266     * @param info The info whose drawing order should be populated
7267     */
7268    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7269        /*
7270         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7271         * drawing order may not be well-defined, and some Views with custom drawing order may
7272         * not be initialized sufficiently to respond properly getChildDrawingOrder.
7273         */
7274        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7275            info.setDrawingOrder(0);
7276            return;
7277        }
7278        int drawingOrderInParent = 1;
7279        // Iterate up the hierarchy if parents are not important for a11y
7280        View viewAtDrawingLevel = this;
7281        final ViewParent parent = getParentForAccessibility();
7282        while (viewAtDrawingLevel != parent) {
7283            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7284            if (!(currentParent instanceof ViewGroup)) {
7285                // Should only happen for the Decor
7286                drawingOrderInParent = 0;
7287                break;
7288            } else {
7289                final ViewGroup parentGroup = (ViewGroup) currentParent;
7290                final int childCount = parentGroup.getChildCount();
7291                if (childCount > 1) {
7292                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7293                    if (preorderedList != null) {
7294                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7295                        for (int i = 0; i < childDrawIndex; i++) {
7296                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7297                        }
7298                    } else {
7299                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7300                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7301                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7302                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7303                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7304                        if (childDrawIndex != 0) {
7305                            for (int i = 0; i < numChildrenToIterate; i++) {
7306                                final int otherDrawIndex = (customOrder ?
7307                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7308                                if (otherDrawIndex < childDrawIndex) {
7309                                    drawingOrderInParent +=
7310                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7311                                }
7312                            }
7313                        }
7314                    }
7315                }
7316            }
7317            viewAtDrawingLevel = (View) currentParent;
7318        }
7319        info.setDrawingOrder(drawingOrderInParent);
7320    }
7321
7322    private static int numViewsForAccessibility(View view) {
7323        if (view != null) {
7324            if (view.includeForAccessibility()) {
7325                return 1;
7326            } else if (view instanceof ViewGroup) {
7327                return ((ViewGroup) view).getNumChildrenForAccessibility();
7328            }
7329        }
7330        return 0;
7331    }
7332
7333    private View findLabelForView(View view, int labeledId) {
7334        if (mMatchLabelForPredicate == null) {
7335            mMatchLabelForPredicate = new MatchLabelForPredicate();
7336        }
7337        mMatchLabelForPredicate.mLabeledId = labeledId;
7338        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7339    }
7340
7341    /**
7342     * Computes whether this view is visible to the user. Such a view is
7343     * attached, visible, all its predecessors are visible, it is not clipped
7344     * entirely by its predecessors, and has an alpha greater than zero.
7345     *
7346     * @return Whether the view is visible on the screen.
7347     *
7348     * @hide
7349     */
7350    protected boolean isVisibleToUser() {
7351        return isVisibleToUser(null);
7352    }
7353
7354    /**
7355     * Computes whether the given portion of this view is visible to the user.
7356     * Such a view is attached, visible, all its predecessors are visible,
7357     * has an alpha greater than zero, and the specified portion is not
7358     * clipped entirely by its predecessors.
7359     *
7360     * @param boundInView the portion of the view to test; coordinates should be relative; may be
7361     *                    <code>null</code>, and the entire view will be tested in this case.
7362     *                    When <code>true</code> is returned by the function, the actual visible
7363     *                    region will be stored in this parameter; that is, if boundInView is fully
7364     *                    contained within the view, no modification will be made, otherwise regions
7365     *                    outside of the visible area of the view will be clipped.
7366     *
7367     * @return Whether the specified portion of the view is visible on the screen.
7368     *
7369     * @hide
7370     */
7371    protected boolean isVisibleToUser(Rect boundInView) {
7372        if (mAttachInfo != null) {
7373            // Attached to invisible window means this view is not visible.
7374            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
7375                return false;
7376            }
7377            // An invisible predecessor or one with alpha zero means
7378            // that this view is not visible to the user.
7379            Object current = this;
7380            while (current instanceof View) {
7381                View view = (View) current;
7382                // We have attach info so this view is attached and there is no
7383                // need to check whether we reach to ViewRootImpl on the way up.
7384                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
7385                        view.getVisibility() != VISIBLE) {
7386                    return false;
7387                }
7388                current = view.mParent;
7389            }
7390            // Check if the view is entirely covered by its predecessors.
7391            Rect visibleRect = mAttachInfo.mTmpInvalRect;
7392            Point offset = mAttachInfo.mPoint;
7393            if (!getGlobalVisibleRect(visibleRect, offset)) {
7394                return false;
7395            }
7396            // Check if the visible portion intersects the rectangle of interest.
7397            if (boundInView != null) {
7398                visibleRect.offset(-offset.x, -offset.y);
7399                return boundInView.intersect(visibleRect);
7400            }
7401            return true;
7402        }
7403        return false;
7404    }
7405
7406    /**
7407     * Returns the delegate for implementing accessibility support via
7408     * composition. For more details see {@link AccessibilityDelegate}.
7409     *
7410     * @return The delegate, or null if none set.
7411     *
7412     * @hide
7413     */
7414    public AccessibilityDelegate getAccessibilityDelegate() {
7415        return mAccessibilityDelegate;
7416    }
7417
7418    /**
7419     * Sets a delegate for implementing accessibility support via composition
7420     * (as opposed to inheritance). For more details, see
7421     * {@link AccessibilityDelegate}.
7422     * <p>
7423     * <strong>Note:</strong> On platform versions prior to
7424     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
7425     * views in the {@code android.widget.*} package are called <i>before</i>
7426     * host methods. This prevents certain properties such as class name from
7427     * being modified by overriding
7428     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
7429     * as any changes will be overwritten by the host class.
7430     * <p>
7431     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
7432     * methods are called <i>after</i> host methods, which all properties to be
7433     * modified without being overwritten by the host class.
7434     *
7435     * @param delegate the object to which accessibility method calls should be
7436     *                 delegated
7437     * @see AccessibilityDelegate
7438     */
7439    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
7440        mAccessibilityDelegate = delegate;
7441    }
7442
7443    /**
7444     * Gets the provider for managing a virtual view hierarchy rooted at this View
7445     * and reported to {@link android.accessibilityservice.AccessibilityService}s
7446     * that explore the window content.
7447     * <p>
7448     * If this method returns an instance, this instance is responsible for managing
7449     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
7450     * View including the one representing the View itself. Similarly the returned
7451     * instance is responsible for performing accessibility actions on any virtual
7452     * view or the root view itself.
7453     * </p>
7454     * <p>
7455     * If an {@link AccessibilityDelegate} has been specified via calling
7456     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7457     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
7458     * is responsible for handling this call.
7459     * </p>
7460     *
7461     * @return The provider.
7462     *
7463     * @see AccessibilityNodeProvider
7464     */
7465    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
7466        if (mAccessibilityDelegate != null) {
7467            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
7468        } else {
7469            return null;
7470        }
7471    }
7472
7473    /**
7474     * Gets the unique identifier of this view on the screen for accessibility purposes.
7475     *
7476     * @return The view accessibility id.
7477     *
7478     * @hide
7479     */
7480    public int getAccessibilityViewId() {
7481        if (mAccessibilityViewId == NO_ID) {
7482            mAccessibilityViewId = sNextAccessibilityViewId++;
7483        }
7484        return mAccessibilityViewId;
7485    }
7486
7487    /**
7488     * Gets the unique identifier of the window in which this View reseides.
7489     *
7490     * @return The window accessibility id.
7491     *
7492     * @hide
7493     */
7494    public int getAccessibilityWindowId() {
7495        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
7496                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
7497    }
7498
7499    /**
7500     * Returns the {@link View}'s content description.
7501     * <p>
7502     * <strong>Note:</strong> Do not override this method, as it will have no
7503     * effect on the content description presented to accessibility services.
7504     * You must call {@link #setContentDescription(CharSequence)} to modify the
7505     * content description.
7506     *
7507     * @return the content description
7508     * @see #setContentDescription(CharSequence)
7509     * @attr ref android.R.styleable#View_contentDescription
7510     */
7511    @ViewDebug.ExportedProperty(category = "accessibility")
7512    public CharSequence getContentDescription() {
7513        return mContentDescription;
7514    }
7515
7516    /**
7517     * Sets the {@link View}'s content description.
7518     * <p>
7519     * A content description briefly describes the view and is primarily used
7520     * for accessibility support to determine how a view should be presented to
7521     * the user. In the case of a view with no textual representation, such as
7522     * {@link android.widget.ImageButton}, a useful content description
7523     * explains what the view does. For example, an image button with a phone
7524     * icon that is used to place a call may use "Call" as its content
7525     * description. An image of a floppy disk that is used to save a file may
7526     * use "Save".
7527     *
7528     * @param contentDescription The content description.
7529     * @see #getContentDescription()
7530     * @attr ref android.R.styleable#View_contentDescription
7531     */
7532    @RemotableViewMethod
7533    public void setContentDescription(CharSequence contentDescription) {
7534        if (mContentDescription == null) {
7535            if (contentDescription == null) {
7536                return;
7537            }
7538        } else if (mContentDescription.equals(contentDescription)) {
7539            return;
7540        }
7541        mContentDescription = contentDescription;
7542        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
7543        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
7544            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
7545            notifySubtreeAccessibilityStateChangedIfNeeded();
7546        } else {
7547            notifyViewAccessibilityStateChangedIfNeeded(
7548                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
7549        }
7550    }
7551
7552    /**
7553     * Sets the id of a view before which this one is visited in accessibility traversal.
7554     * A screen-reader must visit the content of this view before the content of the one
7555     * it precedes. For example, if view B is set to be before view A, then a screen-reader
7556     * will traverse the entire content of B before traversing the entire content of A,
7557     * regardles of what traversal strategy it is using.
7558     * <p>
7559     * Views that do not have specified before/after relationships are traversed in order
7560     * determined by the screen-reader.
7561     * </p>
7562     * <p>
7563     * Setting that this view is before a view that is not important for accessibility
7564     * or if this view is not important for accessibility will have no effect as the
7565     * screen-reader is not aware of unimportant views.
7566     * </p>
7567     *
7568     * @param beforeId The id of a view this one precedes in accessibility traversal.
7569     *
7570     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
7571     *
7572     * @see #setImportantForAccessibility(int)
7573     */
7574    @RemotableViewMethod
7575    public void setAccessibilityTraversalBefore(int beforeId) {
7576        if (mAccessibilityTraversalBeforeId == beforeId) {
7577            return;
7578        }
7579        mAccessibilityTraversalBeforeId = beforeId;
7580        notifyViewAccessibilityStateChangedIfNeeded(
7581                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7582    }
7583
7584    /**
7585     * Gets the id of a view before which this one is visited in accessibility traversal.
7586     *
7587     * @return The id of a view this one precedes in accessibility traversal if
7588     *         specified, otherwise {@link #NO_ID}.
7589     *
7590     * @see #setAccessibilityTraversalBefore(int)
7591     */
7592    public int getAccessibilityTraversalBefore() {
7593        return mAccessibilityTraversalBeforeId;
7594    }
7595
7596    /**
7597     * Sets the id of a view after which this one is visited in accessibility traversal.
7598     * A screen-reader must visit the content of the other view before the content of this
7599     * one. For example, if view B is set to be after view A, then a screen-reader
7600     * will traverse the entire content of A before traversing the entire content of B,
7601     * regardles of what traversal strategy it is using.
7602     * <p>
7603     * Views that do not have specified before/after relationships are traversed in order
7604     * determined by the screen-reader.
7605     * </p>
7606     * <p>
7607     * Setting that this view is after a view that is not important for accessibility
7608     * or if this view is not important for accessibility will have no effect as the
7609     * screen-reader is not aware of unimportant views.
7610     * </p>
7611     *
7612     * @param afterId The id of a view this one succedees in accessibility traversal.
7613     *
7614     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
7615     *
7616     * @see #setImportantForAccessibility(int)
7617     */
7618    @RemotableViewMethod
7619    public void setAccessibilityTraversalAfter(int afterId) {
7620        if (mAccessibilityTraversalAfterId == afterId) {
7621            return;
7622        }
7623        mAccessibilityTraversalAfterId = afterId;
7624        notifyViewAccessibilityStateChangedIfNeeded(
7625                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7626    }
7627
7628    /**
7629     * Gets the id of a view after which this one is visited in accessibility traversal.
7630     *
7631     * @return The id of a view this one succeedes in accessibility traversal if
7632     *         specified, otherwise {@link #NO_ID}.
7633     *
7634     * @see #setAccessibilityTraversalAfter(int)
7635     */
7636    public int getAccessibilityTraversalAfter() {
7637        return mAccessibilityTraversalAfterId;
7638    }
7639
7640    /**
7641     * Gets the id of a view for which this view serves as a label for
7642     * accessibility purposes.
7643     *
7644     * @return The labeled view id.
7645     */
7646    @ViewDebug.ExportedProperty(category = "accessibility")
7647    public int getLabelFor() {
7648        return mLabelForId;
7649    }
7650
7651    /**
7652     * Sets the id of a view for which this view serves as a label for
7653     * accessibility purposes.
7654     *
7655     * @param id The labeled view id.
7656     */
7657    @RemotableViewMethod
7658    public void setLabelFor(@IdRes int id) {
7659        if (mLabelForId == id) {
7660            return;
7661        }
7662        mLabelForId = id;
7663        if (mLabelForId != View.NO_ID
7664                && mID == View.NO_ID) {
7665            mID = generateViewId();
7666        }
7667        notifyViewAccessibilityStateChangedIfNeeded(
7668                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7669    }
7670
7671    /**
7672     * Invoked whenever this view loses focus, either by losing window focus or by losing
7673     * focus within its window. This method can be used to clear any state tied to the
7674     * focus. For instance, if a button is held pressed with the trackball and the window
7675     * loses focus, this method can be used to cancel the press.
7676     *
7677     * Subclasses of View overriding this method should always call super.onFocusLost().
7678     *
7679     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7680     * @see #onWindowFocusChanged(boolean)
7681     *
7682     * @hide pending API council approval
7683     */
7684    @CallSuper
7685    protected void onFocusLost() {
7686        resetPressedState();
7687    }
7688
7689    private void resetPressedState() {
7690        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7691            return;
7692        }
7693
7694        if (isPressed()) {
7695            setPressed(false);
7696
7697            if (!mHasPerformedLongPress) {
7698                removeLongPressCallback();
7699            }
7700        }
7701    }
7702
7703    /**
7704     * Returns true if this view has focus
7705     *
7706     * @return True if this view has focus, false otherwise.
7707     */
7708    @ViewDebug.ExportedProperty(category = "focus")
7709    public boolean isFocused() {
7710        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7711    }
7712
7713    /**
7714     * Find the view in the hierarchy rooted at this view that currently has
7715     * focus.
7716     *
7717     * @return The view that currently has focus, or null if no focused view can
7718     *         be found.
7719     */
7720    public View findFocus() {
7721        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7722    }
7723
7724    /**
7725     * Indicates whether this view is one of the set of scrollable containers in
7726     * its window.
7727     *
7728     * @return whether this view is one of the set of scrollable containers in
7729     * its window
7730     *
7731     * @attr ref android.R.styleable#View_isScrollContainer
7732     */
7733    public boolean isScrollContainer() {
7734        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7735    }
7736
7737    /**
7738     * Change whether this view is one of the set of scrollable containers in
7739     * its window.  This will be used to determine whether the window can
7740     * resize or must pan when a soft input area is open -- scrollable
7741     * containers allow the window to use resize mode since the container
7742     * will appropriately shrink.
7743     *
7744     * @attr ref android.R.styleable#View_isScrollContainer
7745     */
7746    public void setScrollContainer(boolean isScrollContainer) {
7747        if (isScrollContainer) {
7748            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7749                mAttachInfo.mScrollContainers.add(this);
7750                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7751            }
7752            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7753        } else {
7754            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7755                mAttachInfo.mScrollContainers.remove(this);
7756            }
7757            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7758        }
7759    }
7760
7761    /**
7762     * Returns the quality of the drawing cache.
7763     *
7764     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7765     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7766     *
7767     * @see #setDrawingCacheQuality(int)
7768     * @see #setDrawingCacheEnabled(boolean)
7769     * @see #isDrawingCacheEnabled()
7770     *
7771     * @attr ref android.R.styleable#View_drawingCacheQuality
7772     */
7773    @DrawingCacheQuality
7774    public int getDrawingCacheQuality() {
7775        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7776    }
7777
7778    /**
7779     * Set the drawing cache quality of this view. This value is used only when the
7780     * drawing cache is enabled
7781     *
7782     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7783     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7784     *
7785     * @see #getDrawingCacheQuality()
7786     * @see #setDrawingCacheEnabled(boolean)
7787     * @see #isDrawingCacheEnabled()
7788     *
7789     * @attr ref android.R.styleable#View_drawingCacheQuality
7790     */
7791    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7792        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7793    }
7794
7795    /**
7796     * Returns whether the screen should remain on, corresponding to the current
7797     * value of {@link #KEEP_SCREEN_ON}.
7798     *
7799     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7800     *
7801     * @see #setKeepScreenOn(boolean)
7802     *
7803     * @attr ref android.R.styleable#View_keepScreenOn
7804     */
7805    public boolean getKeepScreenOn() {
7806        return (mViewFlags & KEEP_SCREEN_ON) != 0;
7807    }
7808
7809    /**
7810     * Controls whether the screen should remain on, modifying the
7811     * value of {@link #KEEP_SCREEN_ON}.
7812     *
7813     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7814     *
7815     * @see #getKeepScreenOn()
7816     *
7817     * @attr ref android.R.styleable#View_keepScreenOn
7818     */
7819    public void setKeepScreenOn(boolean keepScreenOn) {
7820        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7821    }
7822
7823    /**
7824     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7825     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7826     *
7827     * @attr ref android.R.styleable#View_nextFocusLeft
7828     */
7829    public int getNextFocusLeftId() {
7830        return mNextFocusLeftId;
7831    }
7832
7833    /**
7834     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7835     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7836     * decide automatically.
7837     *
7838     * @attr ref android.R.styleable#View_nextFocusLeft
7839     */
7840    public void setNextFocusLeftId(int nextFocusLeftId) {
7841        mNextFocusLeftId = nextFocusLeftId;
7842    }
7843
7844    /**
7845     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7846     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7847     *
7848     * @attr ref android.R.styleable#View_nextFocusRight
7849     */
7850    public int getNextFocusRightId() {
7851        return mNextFocusRightId;
7852    }
7853
7854    /**
7855     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7856     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7857     * decide automatically.
7858     *
7859     * @attr ref android.R.styleable#View_nextFocusRight
7860     */
7861    public void setNextFocusRightId(int nextFocusRightId) {
7862        mNextFocusRightId = nextFocusRightId;
7863    }
7864
7865    /**
7866     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7867     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7868     *
7869     * @attr ref android.R.styleable#View_nextFocusUp
7870     */
7871    public int getNextFocusUpId() {
7872        return mNextFocusUpId;
7873    }
7874
7875    /**
7876     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7877     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7878     * decide automatically.
7879     *
7880     * @attr ref android.R.styleable#View_nextFocusUp
7881     */
7882    public void setNextFocusUpId(int nextFocusUpId) {
7883        mNextFocusUpId = nextFocusUpId;
7884    }
7885
7886    /**
7887     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7888     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7889     *
7890     * @attr ref android.R.styleable#View_nextFocusDown
7891     */
7892    public int getNextFocusDownId() {
7893        return mNextFocusDownId;
7894    }
7895
7896    /**
7897     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7898     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7899     * decide automatically.
7900     *
7901     * @attr ref android.R.styleable#View_nextFocusDown
7902     */
7903    public void setNextFocusDownId(int nextFocusDownId) {
7904        mNextFocusDownId = nextFocusDownId;
7905    }
7906
7907    /**
7908     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7909     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7910     *
7911     * @attr ref android.R.styleable#View_nextFocusForward
7912     */
7913    public int getNextFocusForwardId() {
7914        return mNextFocusForwardId;
7915    }
7916
7917    /**
7918     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7919     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7920     * decide automatically.
7921     *
7922     * @attr ref android.R.styleable#View_nextFocusForward
7923     */
7924    public void setNextFocusForwardId(int nextFocusForwardId) {
7925        mNextFocusForwardId = nextFocusForwardId;
7926    }
7927
7928    /**
7929     * Gets the id of the root of the next keyboard navigation cluster.
7930     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
7931     * decide automatically.
7932     *
7933     * @attr ref android.R.styleable#View_nextClusterForward
7934     */
7935    public int getNextClusterForwardId() {
7936        return mNextClusterForwardId;
7937    }
7938
7939    /**
7940     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
7941     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
7942     * decide automatically.
7943     *
7944     * @attr ref android.R.styleable#View_nextClusterForward
7945     */
7946    public void setNextClusterForwardId(int nextClusterForwardId) {
7947        mNextClusterForwardId = nextClusterForwardId;
7948    }
7949
7950    /**
7951     * Gets the id of the root of the next keyboard navigation section.
7952     * @return The next keyboard navigation section ID, or {@link #NO_ID} if the framework should
7953     * decide automatically.
7954     *
7955     * @attr ref android.R.styleable#View_nextSectionForward
7956     */
7957    public int getNextSectionForwardId() {
7958        return mNextSectionForwardId;
7959    }
7960
7961    /**
7962     * Sets the id of the view to use as the root of the next keyboard navigation section.
7963     * @param nextSectionForwardId The next section ID, or {@link #NO_ID} if the framework should
7964     * decide automatically.
7965     *
7966     * @attr ref android.R.styleable#View_nextSectionForward
7967     */
7968    public void setNextSectionForwardId(int nextSectionForwardId) {
7969        mNextSectionForwardId = nextSectionForwardId;
7970    }
7971
7972    /**
7973     * Returns the visibility of this view and all of its ancestors
7974     *
7975     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7976     */
7977    public boolean isShown() {
7978        View current = this;
7979        //noinspection ConstantConditions
7980        do {
7981            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7982                return false;
7983            }
7984            ViewParent parent = current.mParent;
7985            if (parent == null) {
7986                return false; // We are not attached to the view root
7987            }
7988            if (!(parent instanceof View)) {
7989                return true;
7990            }
7991            current = (View) parent;
7992        } while (current != null);
7993
7994        return false;
7995    }
7996
7997    /**
7998     * Called by the view hierarchy when the content insets for a window have
7999     * changed, to allow it to adjust its content to fit within those windows.
8000     * The content insets tell you the space that the status bar, input method,
8001     * and other system windows infringe on the application's window.
8002     *
8003     * <p>You do not normally need to deal with this function, since the default
8004     * window decoration given to applications takes care of applying it to the
8005     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
8006     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
8007     * and your content can be placed under those system elements.  You can then
8008     * use this method within your view hierarchy if you have parts of your UI
8009     * which you would like to ensure are not being covered.
8010     *
8011     * <p>The default implementation of this method simply applies the content
8012     * insets to the view's padding, consuming that content (modifying the
8013     * insets to be 0), and returning true.  This behavior is off by default, but can
8014     * be enabled through {@link #setFitsSystemWindows(boolean)}.
8015     *
8016     * <p>This function's traversal down the hierarchy is depth-first.  The same content
8017     * insets object is propagated down the hierarchy, so any changes made to it will
8018     * be seen by all following views (including potentially ones above in
8019     * the hierarchy since this is a depth-first traversal).  The first view
8020     * that returns true will abort the entire traversal.
8021     *
8022     * <p>The default implementation works well for a situation where it is
8023     * used with a container that covers the entire window, allowing it to
8024     * apply the appropriate insets to its content on all edges.  If you need
8025     * a more complicated layout (such as two different views fitting system
8026     * windows, one on the top of the window, and one on the bottom),
8027     * you can override the method and handle the insets however you would like.
8028     * Note that the insets provided by the framework are always relative to the
8029     * far edges of the window, not accounting for the location of the called view
8030     * within that window.  (In fact when this method is called you do not yet know
8031     * where the layout will place the view, as it is done before layout happens.)
8032     *
8033     * <p>Note: unlike many View methods, there is no dispatch phase to this
8034     * call.  If you are overriding it in a ViewGroup and want to allow the
8035     * call to continue to your children, you must be sure to call the super
8036     * implementation.
8037     *
8038     * <p>Here is a sample layout that makes use of fitting system windows
8039     * to have controls for a video view placed inside of the window decorations
8040     * that it hides and shows.  This can be used with code like the second
8041     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
8042     *
8043     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
8044     *
8045     * @param insets Current content insets of the window.  Prior to
8046     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
8047     * the insets or else you and Android will be unhappy.
8048     *
8049     * @return {@code true} if this view applied the insets and it should not
8050     * continue propagating further down the hierarchy, {@code false} otherwise.
8051     * @see #getFitsSystemWindows()
8052     * @see #setFitsSystemWindows(boolean)
8053     * @see #setSystemUiVisibility(int)
8054     *
8055     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
8056     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
8057     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
8058     * to implement handling their own insets.
8059     */
8060    @Deprecated
8061    protected boolean fitSystemWindows(Rect insets) {
8062        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
8063            if (insets == null) {
8064                // Null insets by definition have already been consumed.
8065                // This call cannot apply insets since there are none to apply,
8066                // so return false.
8067                return false;
8068            }
8069            // If we're not in the process of dispatching the newer apply insets call,
8070            // that means we're not in the compatibility path. Dispatch into the newer
8071            // apply insets path and take things from there.
8072            try {
8073                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
8074                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
8075            } finally {
8076                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
8077            }
8078        } else {
8079            // We're being called from the newer apply insets path.
8080            // Perform the standard fallback behavior.
8081            return fitSystemWindowsInt(insets);
8082        }
8083    }
8084
8085    private boolean fitSystemWindowsInt(Rect insets) {
8086        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
8087            mUserPaddingStart = UNDEFINED_PADDING;
8088            mUserPaddingEnd = UNDEFINED_PADDING;
8089            Rect localInsets = sThreadLocal.get();
8090            if (localInsets == null) {
8091                localInsets = new Rect();
8092                sThreadLocal.set(localInsets);
8093            }
8094            boolean res = computeFitSystemWindows(insets, localInsets);
8095            mUserPaddingLeftInitial = localInsets.left;
8096            mUserPaddingRightInitial = localInsets.right;
8097            internalSetPadding(localInsets.left, localInsets.top,
8098                    localInsets.right, localInsets.bottom);
8099            return res;
8100        }
8101        return false;
8102    }
8103
8104    /**
8105     * Called when the view should apply {@link WindowInsets} according to its internal policy.
8106     *
8107     * <p>This method should be overridden by views that wish to apply a policy different from or
8108     * in addition to the default behavior. Clients that wish to force a view subtree
8109     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
8110     *
8111     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
8112     * it will be called during dispatch instead of this method. The listener may optionally
8113     * call this method from its own implementation if it wishes to apply the view's default
8114     * insets policy in addition to its own.</p>
8115     *
8116     * <p>Implementations of this method should either return the insets parameter unchanged
8117     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
8118     * that this view applied itself. This allows new inset types added in future platform
8119     * versions to pass through existing implementations unchanged without being erroneously
8120     * consumed.</p>
8121     *
8122     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
8123     * property is set then the view will consume the system window insets and apply them
8124     * as padding for the view.</p>
8125     *
8126     * @param insets Insets to apply
8127     * @return The supplied insets with any applied insets consumed
8128     */
8129    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
8130        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
8131            // We weren't called from within a direct call to fitSystemWindows,
8132            // call into it as a fallback in case we're in a class that overrides it
8133            // and has logic to perform.
8134            if (fitSystemWindows(insets.getSystemWindowInsets())) {
8135                return insets.consumeSystemWindowInsets();
8136            }
8137        } else {
8138            // We were called from within a direct call to fitSystemWindows.
8139            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
8140                return insets.consumeSystemWindowInsets();
8141            }
8142        }
8143        return insets;
8144    }
8145
8146    /**
8147     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
8148     * window insets to this view. The listener's
8149     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
8150     * method will be called instead of the view's
8151     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
8152     *
8153     * @param listener Listener to set
8154     *
8155     * @see #onApplyWindowInsets(WindowInsets)
8156     */
8157    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
8158        getListenerInfo().mOnApplyWindowInsetsListener = listener;
8159    }
8160
8161    /**
8162     * Request to apply the given window insets to this view or another view in its subtree.
8163     *
8164     * <p>This method should be called by clients wishing to apply insets corresponding to areas
8165     * obscured by window decorations or overlays. This can include the status and navigation bars,
8166     * action bars, input methods and more. New inset categories may be added in the future.
8167     * The method returns the insets provided minus any that were applied by this view or its
8168     * children.</p>
8169     *
8170     * <p>Clients wishing to provide custom behavior should override the
8171     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
8172     * {@link OnApplyWindowInsetsListener} via the
8173     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
8174     * method.</p>
8175     *
8176     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
8177     * </p>
8178     *
8179     * @param insets Insets to apply
8180     * @return The provided insets minus the insets that were consumed
8181     */
8182    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
8183        try {
8184            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
8185            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
8186                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
8187            } else {
8188                return onApplyWindowInsets(insets);
8189            }
8190        } finally {
8191            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
8192        }
8193    }
8194
8195    /**
8196     * Compute the view's coordinate within the surface.
8197     *
8198     * <p>Computes the coordinates of this view in its surface. The argument
8199     * must be an array of two integers. After the method returns, the array
8200     * contains the x and y location in that order.</p>
8201     * @hide
8202     * @param location an array of two integers in which to hold the coordinates
8203     */
8204    public void getLocationInSurface(@Size(2) int[] location) {
8205        getLocationInWindow(location);
8206        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
8207            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
8208            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
8209        }
8210    }
8211
8212    /**
8213     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
8214     * only available if the view is attached.
8215     *
8216     * @return WindowInsets from the top of the view hierarchy or null if View is detached
8217     */
8218    public WindowInsets getRootWindowInsets() {
8219        if (mAttachInfo != null) {
8220            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
8221        }
8222        return null;
8223    }
8224
8225    /**
8226     * @hide Compute the insets that should be consumed by this view and the ones
8227     * that should propagate to those under it.
8228     */
8229    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
8230        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8231                || mAttachInfo == null
8232                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
8233                        && !mAttachInfo.mOverscanRequested)) {
8234            outLocalInsets.set(inoutInsets);
8235            inoutInsets.set(0, 0, 0, 0);
8236            return true;
8237        } else {
8238            // The application wants to take care of fitting system window for
8239            // the content...  however we still need to take care of any overscan here.
8240            final Rect overscan = mAttachInfo.mOverscanInsets;
8241            outLocalInsets.set(overscan);
8242            inoutInsets.left -= overscan.left;
8243            inoutInsets.top -= overscan.top;
8244            inoutInsets.right -= overscan.right;
8245            inoutInsets.bottom -= overscan.bottom;
8246            return false;
8247        }
8248    }
8249
8250    /**
8251     * Compute insets that should be consumed by this view and the ones that should propagate
8252     * to those under it.
8253     *
8254     * @param in Insets currently being processed by this View, likely received as a parameter
8255     *           to {@link #onApplyWindowInsets(WindowInsets)}.
8256     * @param outLocalInsets A Rect that will receive the insets that should be consumed
8257     *                       by this view
8258     * @return Insets that should be passed along to views under this one
8259     */
8260    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
8261        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8262                || mAttachInfo == null
8263                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
8264            outLocalInsets.set(in.getSystemWindowInsets());
8265            return in.consumeSystemWindowInsets();
8266        } else {
8267            outLocalInsets.set(0, 0, 0, 0);
8268            return in;
8269        }
8270    }
8271
8272    /**
8273     * Sets whether or not this view should account for system screen decorations
8274     * such as the status bar and inset its content; that is, controlling whether
8275     * the default implementation of {@link #fitSystemWindows(Rect)} will be
8276     * executed.  See that method for more details.
8277     *
8278     * <p>Note that if you are providing your own implementation of
8279     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
8280     * flag to true -- your implementation will be overriding the default
8281     * implementation that checks this flag.
8282     *
8283     * @param fitSystemWindows If true, then the default implementation of
8284     * {@link #fitSystemWindows(Rect)} will be executed.
8285     *
8286     * @attr ref android.R.styleable#View_fitsSystemWindows
8287     * @see #getFitsSystemWindows()
8288     * @see #fitSystemWindows(Rect)
8289     * @see #setSystemUiVisibility(int)
8290     */
8291    public void setFitsSystemWindows(boolean fitSystemWindows) {
8292        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
8293    }
8294
8295    /**
8296     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
8297     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
8298     * will be executed.
8299     *
8300     * @return {@code true} if the default implementation of
8301     * {@link #fitSystemWindows(Rect)} will be executed.
8302     *
8303     * @attr ref android.R.styleable#View_fitsSystemWindows
8304     * @see #setFitsSystemWindows(boolean)
8305     * @see #fitSystemWindows(Rect)
8306     * @see #setSystemUiVisibility(int)
8307     */
8308    @ViewDebug.ExportedProperty
8309    public boolean getFitsSystemWindows() {
8310        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8311    }
8312
8313    /** @hide */
8314    public boolean fitsSystemWindows() {
8315        return getFitsSystemWindows();
8316    }
8317
8318    /**
8319     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8320     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8321     */
8322    @Deprecated
8323    public void requestFitSystemWindows() {
8324        if (mParent != null) {
8325            mParent.requestFitSystemWindows();
8326        }
8327    }
8328
8329    /**
8330     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8331     */
8332    public void requestApplyInsets() {
8333        requestFitSystemWindows();
8334    }
8335
8336    /**
8337     * For use by PhoneWindow to make its own system window fitting optional.
8338     * @hide
8339     */
8340    public void makeOptionalFitsSystemWindows() {
8341        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8342    }
8343
8344    /**
8345     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8346     * treat them as such.
8347     * @hide
8348     */
8349    public void getOutsets(Rect outOutsetRect) {
8350        if (mAttachInfo != null) {
8351            outOutsetRect.set(mAttachInfo.mOutsets);
8352        } else {
8353            outOutsetRect.setEmpty();
8354        }
8355    }
8356
8357    /**
8358     * Returns the visibility status for this view.
8359     *
8360     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8361     * @attr ref android.R.styleable#View_visibility
8362     */
8363    @ViewDebug.ExportedProperty(mapping = {
8364        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8365        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8366        @ViewDebug.IntToString(from = GONE,      to = "GONE")
8367    })
8368    @Visibility
8369    public int getVisibility() {
8370        return mViewFlags & VISIBILITY_MASK;
8371    }
8372
8373    /**
8374     * Set the visibility state of this view.
8375     *
8376     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8377     * @attr ref android.R.styleable#View_visibility
8378     */
8379    @RemotableViewMethod
8380    public void setVisibility(@Visibility int visibility) {
8381        setFlags(visibility, VISIBILITY_MASK);
8382    }
8383
8384    /**
8385     * Returns the enabled status for this view. The interpretation of the
8386     * enabled state varies by subclass.
8387     *
8388     * @return True if this view is enabled, false otherwise.
8389     */
8390    @ViewDebug.ExportedProperty
8391    public boolean isEnabled() {
8392        return (mViewFlags & ENABLED_MASK) == ENABLED;
8393    }
8394
8395    /**
8396     * Set the enabled state of this view. The interpretation of the enabled
8397     * state varies by subclass.
8398     *
8399     * @param enabled True if this view is enabled, false otherwise.
8400     */
8401    @RemotableViewMethod
8402    public void setEnabled(boolean enabled) {
8403        if (enabled == isEnabled()) return;
8404
8405        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
8406
8407        /*
8408         * The View most likely has to change its appearance, so refresh
8409         * the drawable state.
8410         */
8411        refreshDrawableState();
8412
8413        // Invalidate too, since the default behavior for views is to be
8414        // be drawn at 50% alpha rather than to change the drawable.
8415        invalidate(true);
8416
8417        if (!enabled) {
8418            cancelPendingInputEvents();
8419        }
8420    }
8421
8422    /**
8423     * Set whether this view can receive the focus.
8424     *
8425     * Setting this to false will also ensure that this view is not focusable
8426     * in touch mode.
8427     *
8428     * @param focusable If true, this view can receive the focus.
8429     *
8430     * @see #setFocusableInTouchMode(boolean)
8431     * @attr ref android.R.styleable#View_focusable
8432     */
8433    public void setFocusable(boolean focusable) {
8434        if (!focusable) {
8435            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
8436        }
8437        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
8438    }
8439
8440    /**
8441     * Set whether this view can receive focus while in touch mode.
8442     *
8443     * Setting this to true will also ensure that this view is focusable.
8444     *
8445     * @param focusableInTouchMode If true, this view can receive the focus while
8446     *   in touch mode.
8447     *
8448     * @see #setFocusable(boolean)
8449     * @attr ref android.R.styleable#View_focusableInTouchMode
8450     */
8451    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
8452        // Focusable in touch mode should always be set before the focusable flag
8453        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
8454        // which, in touch mode, will not successfully request focus on this view
8455        // because the focusable in touch mode flag is not set
8456        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
8457        if (focusableInTouchMode) {
8458            setFlags(FOCUSABLE, FOCUSABLE_MASK);
8459        }
8460    }
8461
8462    /**
8463     * Set whether this view should have sound effects enabled for events such as
8464     * clicking and touching.
8465     *
8466     * <p>You may wish to disable sound effects for a view if you already play sounds,
8467     * for instance, a dial key that plays dtmf tones.
8468     *
8469     * @param soundEffectsEnabled whether sound effects are enabled for this view.
8470     * @see #isSoundEffectsEnabled()
8471     * @see #playSoundEffect(int)
8472     * @attr ref android.R.styleable#View_soundEffectsEnabled
8473     */
8474    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
8475        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
8476    }
8477
8478    /**
8479     * @return whether this view should have sound effects enabled for events such as
8480     *     clicking and touching.
8481     *
8482     * @see #setSoundEffectsEnabled(boolean)
8483     * @see #playSoundEffect(int)
8484     * @attr ref android.R.styleable#View_soundEffectsEnabled
8485     */
8486    @ViewDebug.ExportedProperty
8487    public boolean isSoundEffectsEnabled() {
8488        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
8489    }
8490
8491    /**
8492     * Set whether this view should have haptic feedback for events such as
8493     * long presses.
8494     *
8495     * <p>You may wish to disable haptic feedback if your view already controls
8496     * its own haptic feedback.
8497     *
8498     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
8499     * @see #isHapticFeedbackEnabled()
8500     * @see #performHapticFeedback(int)
8501     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8502     */
8503    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
8504        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
8505    }
8506
8507    /**
8508     * @return whether this view should have haptic feedback enabled for events
8509     * long presses.
8510     *
8511     * @see #setHapticFeedbackEnabled(boolean)
8512     * @see #performHapticFeedback(int)
8513     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8514     */
8515    @ViewDebug.ExportedProperty
8516    public boolean isHapticFeedbackEnabled() {
8517        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
8518    }
8519
8520    /**
8521     * Returns the layout direction for this view.
8522     *
8523     * @return One of {@link #LAYOUT_DIRECTION_LTR},
8524     *   {@link #LAYOUT_DIRECTION_RTL},
8525     *   {@link #LAYOUT_DIRECTION_INHERIT} or
8526     *   {@link #LAYOUT_DIRECTION_LOCALE}.
8527     *
8528     * @attr ref android.R.styleable#View_layoutDirection
8529     *
8530     * @hide
8531     */
8532    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8533        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
8534        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
8535        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
8536        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
8537    })
8538    @LayoutDir
8539    public int getRawLayoutDirection() {
8540        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
8541    }
8542
8543    /**
8544     * Set the layout direction for this view. This will propagate a reset of layout direction
8545     * resolution to the view's children and resolve layout direction for this view.
8546     *
8547     * @param layoutDirection the layout direction to set. Should be one of:
8548     *
8549     * {@link #LAYOUT_DIRECTION_LTR},
8550     * {@link #LAYOUT_DIRECTION_RTL},
8551     * {@link #LAYOUT_DIRECTION_INHERIT},
8552     * {@link #LAYOUT_DIRECTION_LOCALE}.
8553     *
8554     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
8555     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
8556     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
8557     *
8558     * @attr ref android.R.styleable#View_layoutDirection
8559     */
8560    @RemotableViewMethod
8561    public void setLayoutDirection(@LayoutDir int layoutDirection) {
8562        if (getRawLayoutDirection() != layoutDirection) {
8563            // Reset the current layout direction and the resolved one
8564            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
8565            resetRtlProperties();
8566            // Set the new layout direction (filtered)
8567            mPrivateFlags2 |=
8568                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
8569            // We need to resolve all RTL properties as they all depend on layout direction
8570            resolveRtlPropertiesIfNeeded();
8571            requestLayout();
8572            invalidate(true);
8573        }
8574    }
8575
8576    /**
8577     * Returns the resolved layout direction for this view.
8578     *
8579     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
8580     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
8581     *
8582     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
8583     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
8584     *
8585     * @attr ref android.R.styleable#View_layoutDirection
8586     */
8587    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8588        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
8589        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
8590    })
8591    @ResolvedLayoutDir
8592    public int getLayoutDirection() {
8593        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
8594        if (targetSdkVersion < JELLY_BEAN_MR1) {
8595            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
8596            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
8597        }
8598        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
8599                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
8600    }
8601
8602    /**
8603     * Indicates whether or not this view's layout is right-to-left. This is resolved from
8604     * layout attribute and/or the inherited value from the parent
8605     *
8606     * @return true if the layout is right-to-left.
8607     *
8608     * @hide
8609     */
8610    @ViewDebug.ExportedProperty(category = "layout")
8611    public boolean isLayoutRtl() {
8612        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
8613    }
8614
8615    /**
8616     * Indicates whether the view is currently tracking transient state that the
8617     * app should not need to concern itself with saving and restoring, but that
8618     * the framework should take special note to preserve when possible.
8619     *
8620     * <p>A view with transient state cannot be trivially rebound from an external
8621     * data source, such as an adapter binding item views in a list. This may be
8622     * because the view is performing an animation, tracking user selection
8623     * of content, or similar.</p>
8624     *
8625     * @return true if the view has transient state
8626     */
8627    @ViewDebug.ExportedProperty(category = "layout")
8628    public boolean hasTransientState() {
8629        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
8630    }
8631
8632    /**
8633     * Set whether this view is currently tracking transient state that the
8634     * framework should attempt to preserve when possible. This flag is reference counted,
8635     * so every call to setHasTransientState(true) should be paired with a later call
8636     * to setHasTransientState(false).
8637     *
8638     * <p>A view with transient state cannot be trivially rebound from an external
8639     * data source, such as an adapter binding item views in a list. This may be
8640     * because the view is performing an animation, tracking user selection
8641     * of content, or similar.</p>
8642     *
8643     * @param hasTransientState true if this view has transient state
8644     */
8645    public void setHasTransientState(boolean hasTransientState) {
8646        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
8647                mTransientStateCount - 1;
8648        if (mTransientStateCount < 0) {
8649            mTransientStateCount = 0;
8650            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
8651                    "unmatched pair of setHasTransientState calls");
8652        } else if ((hasTransientState && mTransientStateCount == 1) ||
8653                (!hasTransientState && mTransientStateCount == 0)) {
8654            // update flag if we've just incremented up from 0 or decremented down to 0
8655            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
8656                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
8657            if (mParent != null) {
8658                try {
8659                    mParent.childHasTransientStateChanged(this, hasTransientState);
8660                } catch (AbstractMethodError e) {
8661                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8662                            " does not fully implement ViewParent", e);
8663                }
8664            }
8665        }
8666    }
8667
8668    /**
8669     * Returns true if this view is currently attached to a window.
8670     */
8671    public boolean isAttachedToWindow() {
8672        return mAttachInfo != null;
8673    }
8674
8675    /**
8676     * Returns true if this view has been through at least one layout since it
8677     * was last attached to or detached from a window.
8678     */
8679    public boolean isLaidOut() {
8680        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
8681    }
8682
8683    /**
8684     * If this view doesn't do any drawing on its own, set this flag to
8685     * allow further optimizations. By default, this flag is not set on
8686     * View, but could be set on some View subclasses such as ViewGroup.
8687     *
8688     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8689     * you should clear this flag.
8690     *
8691     * @param willNotDraw whether or not this View draw on its own
8692     */
8693    public void setWillNotDraw(boolean willNotDraw) {
8694        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8695    }
8696
8697    /**
8698     * Returns whether or not this View draws on its own.
8699     *
8700     * @return true if this view has nothing to draw, false otherwise
8701     */
8702    @ViewDebug.ExportedProperty(category = "drawing")
8703    public boolean willNotDraw() {
8704        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8705    }
8706
8707    /**
8708     * When a View's drawing cache is enabled, drawing is redirected to an
8709     * offscreen bitmap. Some views, like an ImageView, must be able to
8710     * bypass this mechanism if they already draw a single bitmap, to avoid
8711     * unnecessary usage of the memory.
8712     *
8713     * @param willNotCacheDrawing true if this view does not cache its
8714     *        drawing, false otherwise
8715     */
8716    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8717        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8718    }
8719
8720    /**
8721     * Returns whether or not this View can cache its drawing or not.
8722     *
8723     * @return true if this view does not cache its drawing, false otherwise
8724     */
8725    @ViewDebug.ExportedProperty(category = "drawing")
8726    public boolean willNotCacheDrawing() {
8727        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8728    }
8729
8730    /**
8731     * Indicates whether this view reacts to click events or not.
8732     *
8733     * @return true if the view is clickable, false otherwise
8734     *
8735     * @see #setClickable(boolean)
8736     * @attr ref android.R.styleable#View_clickable
8737     */
8738    @ViewDebug.ExportedProperty
8739    public boolean isClickable() {
8740        return (mViewFlags & CLICKABLE) == CLICKABLE;
8741    }
8742
8743    /**
8744     * Enables or disables click events for this view. When a view
8745     * is clickable it will change its state to "pressed" on every click.
8746     * Subclasses should set the view clickable to visually react to
8747     * user's clicks.
8748     *
8749     * @param clickable true to make the view clickable, false otherwise
8750     *
8751     * @see #isClickable()
8752     * @attr ref android.R.styleable#View_clickable
8753     */
8754    public void setClickable(boolean clickable) {
8755        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8756    }
8757
8758    /**
8759     * Indicates whether this view reacts to long click events or not.
8760     *
8761     * @return true if the view is long clickable, false otherwise
8762     *
8763     * @see #setLongClickable(boolean)
8764     * @attr ref android.R.styleable#View_longClickable
8765     */
8766    public boolean isLongClickable() {
8767        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8768    }
8769
8770    /**
8771     * Enables or disables long click events for this view. When a view is long
8772     * clickable it reacts to the user holding down the button for a longer
8773     * duration than a tap. This event can either launch the listener or a
8774     * context menu.
8775     *
8776     * @param longClickable true to make the view long clickable, false otherwise
8777     * @see #isLongClickable()
8778     * @attr ref android.R.styleable#View_longClickable
8779     */
8780    public void setLongClickable(boolean longClickable) {
8781        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8782    }
8783
8784    /**
8785     * Indicates whether this view reacts to context clicks or not.
8786     *
8787     * @return true if the view is context clickable, false otherwise
8788     * @see #setContextClickable(boolean)
8789     * @attr ref android.R.styleable#View_contextClickable
8790     */
8791    public boolean isContextClickable() {
8792        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8793    }
8794
8795    /**
8796     * Enables or disables context clicking for this view. This event can launch the listener.
8797     *
8798     * @param contextClickable true to make the view react to a context click, false otherwise
8799     * @see #isContextClickable()
8800     * @attr ref android.R.styleable#View_contextClickable
8801     */
8802    public void setContextClickable(boolean contextClickable) {
8803        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8804    }
8805
8806    /**
8807     * Sets the pressed state for this view and provides a touch coordinate for
8808     * animation hinting.
8809     *
8810     * @param pressed Pass true to set the View's internal state to "pressed",
8811     *            or false to reverts the View's internal state from a
8812     *            previously set "pressed" state.
8813     * @param x The x coordinate of the touch that caused the press
8814     * @param y The y coordinate of the touch that caused the press
8815     */
8816    private void setPressed(boolean pressed, float x, float y) {
8817        if (pressed) {
8818            drawableHotspotChanged(x, y);
8819        }
8820
8821        setPressed(pressed);
8822    }
8823
8824    /**
8825     * Sets the pressed state for this view.
8826     *
8827     * @see #isClickable()
8828     * @see #setClickable(boolean)
8829     *
8830     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8831     *        the View's internal state from a previously set "pressed" state.
8832     */
8833    public void setPressed(boolean pressed) {
8834        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8835
8836        if (pressed) {
8837            mPrivateFlags |= PFLAG_PRESSED;
8838        } else {
8839            mPrivateFlags &= ~PFLAG_PRESSED;
8840        }
8841
8842        if (needsRefresh) {
8843            refreshDrawableState();
8844        }
8845        dispatchSetPressed(pressed);
8846    }
8847
8848    /**
8849     * Dispatch setPressed to all of this View's children.
8850     *
8851     * @see #setPressed(boolean)
8852     *
8853     * @param pressed The new pressed state
8854     */
8855    protected void dispatchSetPressed(boolean pressed) {
8856    }
8857
8858    /**
8859     * Indicates whether the view is currently in pressed state. Unless
8860     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8861     * the pressed state.
8862     *
8863     * @see #setPressed(boolean)
8864     * @see #isClickable()
8865     * @see #setClickable(boolean)
8866     *
8867     * @return true if the view is currently pressed, false otherwise
8868     */
8869    @ViewDebug.ExportedProperty
8870    public boolean isPressed() {
8871        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8872    }
8873
8874    /**
8875     * @hide
8876     * Indicates whether this view will participate in data collection through
8877     * {@link ViewStructure}.  If true, it will not provide any data
8878     * for itself or its children.  If false, the normal data collection will be allowed.
8879     *
8880     * @return Returns false if assist data collection is not blocked, else true.
8881     *
8882     * @see #setAssistBlocked(boolean)
8883     * @attr ref android.R.styleable#View_assistBlocked
8884     */
8885    public boolean isAssistBlocked() {
8886        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8887    }
8888
8889    /**
8890     * @hide
8891     * Indicates whether this view will participate in data collection through
8892     * {@link ViewStructure} for auto-fill purposes.
8893     *
8894     * <p>If {@code true}, it will not provide any data for itself or its children.
8895     * <p>If {@code false}, the normal data collection will be allowed.
8896     *
8897     * @return Returns {@code false} if assist data collection for auto-fill is not blocked,
8898     * else {@code true}.
8899     *
8900     * TODO(b/33197203): update / remove javadoc tags below
8901     * @see #setAssistBlocked(boolean)
8902     * @attr ref android.R.styleable#View_assistBlocked
8903     */
8904    public boolean isAutoFillBlocked() {
8905        return false; // TODO(b/33197203): properly implement it
8906    }
8907
8908    /**
8909     * @hide
8910     * Controls whether assist data collection from this view and its children is enabled
8911     * (that is, whether {@link #onProvideStructure} and
8912     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8913     * allowing normal assist collection.  Setting this to false will disable assist collection.
8914     *
8915     * @param enabled Set to true to <em>disable</em> assist data collection, or false
8916     * (the default) to allow it.
8917     *
8918     * @see #isAssistBlocked()
8919     * @see #onProvideStructure
8920     * @see #onProvideVirtualStructure
8921     * @attr ref android.R.styleable#View_assistBlocked
8922     */
8923    public void setAssistBlocked(boolean enabled) {
8924        if (enabled) {
8925            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8926        } else {
8927            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8928        }
8929    }
8930
8931    /**
8932     * Indicates whether this view will save its state (that is,
8933     * whether its {@link #onSaveInstanceState} method will be called).
8934     *
8935     * @return Returns true if the view state saving is enabled, else false.
8936     *
8937     * @see #setSaveEnabled(boolean)
8938     * @attr ref android.R.styleable#View_saveEnabled
8939     */
8940    public boolean isSaveEnabled() {
8941        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8942    }
8943
8944    /**
8945     * Controls whether the saving of this view's state is
8946     * enabled (that is, whether its {@link #onSaveInstanceState} method
8947     * will be called).  Note that even if freezing is enabled, the
8948     * view still must have an id assigned to it (via {@link #setId(int)})
8949     * for its state to be saved.  This flag can only disable the
8950     * saving of this view; any child views may still have their state saved.
8951     *
8952     * @param enabled Set to false to <em>disable</em> state saving, or true
8953     * (the default) to allow it.
8954     *
8955     * @see #isSaveEnabled()
8956     * @see #setId(int)
8957     * @see #onSaveInstanceState()
8958     * @attr ref android.R.styleable#View_saveEnabled
8959     */
8960    public void setSaveEnabled(boolean enabled) {
8961        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8962    }
8963
8964    /**
8965     * Gets whether the framework should discard touches when the view's
8966     * window is obscured by another visible window.
8967     * Refer to the {@link View} security documentation for more details.
8968     *
8969     * @return True if touch filtering is enabled.
8970     *
8971     * @see #setFilterTouchesWhenObscured(boolean)
8972     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8973     */
8974    @ViewDebug.ExportedProperty
8975    public boolean getFilterTouchesWhenObscured() {
8976        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8977    }
8978
8979    /**
8980     * Sets whether the framework should discard touches when the view's
8981     * window is obscured by another visible window.
8982     * Refer to the {@link View} security documentation for more details.
8983     *
8984     * @param enabled True if touch filtering should be enabled.
8985     *
8986     * @see #getFilterTouchesWhenObscured
8987     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8988     */
8989    public void setFilterTouchesWhenObscured(boolean enabled) {
8990        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8991                FILTER_TOUCHES_WHEN_OBSCURED);
8992    }
8993
8994    /**
8995     * Indicates whether the entire hierarchy under this view will save its
8996     * state when a state saving traversal occurs from its parent.  The default
8997     * is true; if false, these views will not be saved unless
8998     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8999     *
9000     * @return Returns true if the view state saving from parent is enabled, else false.
9001     *
9002     * @see #setSaveFromParentEnabled(boolean)
9003     */
9004    public boolean isSaveFromParentEnabled() {
9005        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
9006    }
9007
9008    /**
9009     * Controls whether the entire hierarchy under this view will save its
9010     * state when a state saving traversal occurs from its parent.  The default
9011     * is true; if false, these views will not be saved unless
9012     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9013     *
9014     * @param enabled Set to false to <em>disable</em> state saving, or true
9015     * (the default) to allow it.
9016     *
9017     * @see #isSaveFromParentEnabled()
9018     * @see #setId(int)
9019     * @see #onSaveInstanceState()
9020     */
9021    public void setSaveFromParentEnabled(boolean enabled) {
9022        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
9023    }
9024
9025
9026    /**
9027     * Returns whether this View is able to take focus.
9028     *
9029     * @return True if this view can take focus, or false otherwise.
9030     * @attr ref android.R.styleable#View_focusable
9031     */
9032    @ViewDebug.ExportedProperty(category = "focus")
9033    public final boolean isFocusable() {
9034        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
9035    }
9036
9037    /**
9038     * When a view is focusable, it may not want to take focus when in touch mode.
9039     * For example, a button would like focus when the user is navigating via a D-pad
9040     * so that the user can click on it, but once the user starts touching the screen,
9041     * the button shouldn't take focus
9042     * @return Whether the view is focusable in touch mode.
9043     * @attr ref android.R.styleable#View_focusableInTouchMode
9044     */
9045    @ViewDebug.ExportedProperty
9046    public final boolean isFocusableInTouchMode() {
9047        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
9048    }
9049
9050    /**
9051     * Find the nearest view in the specified direction that can take focus.
9052     * This does not actually give focus to that view.
9053     *
9054     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9055     *
9056     * @return The nearest focusable in the specified direction, or null if none
9057     *         can be found.
9058     */
9059    public View focusSearch(@FocusRealDirection int direction) {
9060        if (mParent != null) {
9061            return mParent.focusSearch(this, direction);
9062        } else {
9063            return null;
9064        }
9065    }
9066
9067    /**
9068     * Returns whether this View is a root of a keyboard navigation cluster.
9069     *
9070     * @return True if this view is a root of a cluster, or false otherwise.
9071     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9072     */
9073    @ViewDebug.ExportedProperty(category = "keyboardNavigationCluster")
9074    public final boolean isKeyboardNavigationCluster() {
9075        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
9076    }
9077
9078    /**
9079     * Set whether this view is a root of a keyboard navigation cluster.
9080     *
9081     * @param isCluster If true, this view is a root of a cluster.
9082     *
9083     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9084     */
9085    public void setKeyboardNavigationCluster(boolean isCluster) {
9086        if (isCluster) {
9087            mPrivateFlags3 |= PFLAG3_CLUSTER;
9088        } else {
9089            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
9090        }
9091    }
9092
9093    /**
9094     * Returns whether this View is a root of a keyboard navigation section.
9095     *
9096     * @return True if this view is a root of a section, or false otherwise.
9097     * @attr ref android.R.styleable#View_keyboardNavigationSection
9098     */
9099    @ViewDebug.ExportedProperty(category = "keyboardNavigationSection")
9100    public final boolean isKeyboardNavigationSection() {
9101        return (mPrivateFlags3 & PFLAG3_SECTION) != 0;
9102    }
9103
9104    /**
9105     * Set whether this view is a root of a keyboard navigation section.
9106     *
9107     * @param isSection If true, this view is a root of a section.
9108     *
9109     * @attr ref android.R.styleable#View_keyboardNavigationSection
9110     */
9111    public void setKeyboardNavigationSection(boolean isSection) {
9112        if (isSection) {
9113            mPrivateFlags3 |= PFLAG3_SECTION;
9114        } else {
9115            mPrivateFlags3 &= ~PFLAG3_SECTION;
9116        }
9117    }
9118
9119    final boolean isKeyboardNavigationGroupOfType(@KeyboardNavigationGroupType int groupType) {
9120        switch (groupType) {
9121            case KEYBOARD_NAVIGATION_GROUP_CLUSTER:
9122                return isKeyboardNavigationCluster();
9123            case KEYBOARD_NAVIGATION_GROUP_SECTION:
9124                return isKeyboardNavigationSection();
9125            default:
9126                throw new IllegalArgumentException(
9127                        "Unknown keyboard navigation group type: " + groupType);
9128        }
9129    }
9130
9131    /**
9132     * Find the nearest keyboard navigation group in the specified direction. The group type can be
9133     * either a cluster or a section.
9134     * This does not actually give focus to that group.
9135     *
9136     * @param groupType Type of the keyboard navigation group
9137     * @param currentGroup The starting point of the search. Null means the current group is not
9138     *                     found yet
9139     * @param direction Direction to look
9140     *
9141     * @return The nearest keyboard navigation group in the specified direction, or null if none
9142     *         can be found
9143     */
9144    public View keyboardNavigationGroupSearch(
9145            @KeyboardNavigationGroupType int groupType, View currentGroup, int direction) {
9146        if (isKeyboardNavigationGroupOfType(groupType)) {
9147            currentGroup = this;
9148        }
9149        if (isRootNamespace()
9150                || (groupType == KEYBOARD_NAVIGATION_GROUP_SECTION
9151                && isKeyboardNavigationCluster())) {
9152            // Root namespace means we should consider ourselves the top of the
9153            // tree for group searching; otherwise we could be group searching
9154            // into other tabs.  see LocalActivityManager and TabHost for more info.
9155            // In addition, a cluster node works as a root for section searches.
9156            return FocusFinder.getInstance().findNextKeyboardNavigationGroup(
9157                    groupType, this, currentGroup, direction);
9158        } else if (mParent != null) {
9159            return mParent.keyboardNavigationGroupSearch(
9160                    groupType, currentGroup, direction);
9161        }
9162        return null;
9163    }
9164
9165    /**
9166     * This method is the last chance for the focused view and its ancestors to
9167     * respond to an arrow key. This is called when the focused view did not
9168     * consume the key internally, nor could the view system find a new view in
9169     * the requested direction to give focus to.
9170     *
9171     * @param focused The currently focused view.
9172     * @param direction The direction focus wants to move. One of FOCUS_UP,
9173     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
9174     * @return True if the this view consumed this unhandled move.
9175     */
9176    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
9177        return false;
9178    }
9179
9180    /**
9181     * If a user manually specified the next view id for a particular direction,
9182     * use the root to look up the view.
9183     * @param root The root view of the hierarchy containing this view.
9184     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
9185     * or FOCUS_BACKWARD.
9186     * @return The user specified next view, or null if there is none.
9187     */
9188    View findUserSetNextFocus(View root, @FocusDirection int direction) {
9189        switch (direction) {
9190            case FOCUS_LEFT:
9191                if (mNextFocusLeftId == View.NO_ID) return null;
9192                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
9193            case FOCUS_RIGHT:
9194                if (mNextFocusRightId == View.NO_ID) return null;
9195                return findViewInsideOutShouldExist(root, mNextFocusRightId);
9196            case FOCUS_UP:
9197                if (mNextFocusUpId == View.NO_ID) return null;
9198                return findViewInsideOutShouldExist(root, mNextFocusUpId);
9199            case FOCUS_DOWN:
9200                if (mNextFocusDownId == View.NO_ID) return null;
9201                return findViewInsideOutShouldExist(root, mNextFocusDownId);
9202            case FOCUS_FORWARD:
9203                if (mNextFocusForwardId == View.NO_ID) return null;
9204                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
9205            case FOCUS_BACKWARD: {
9206                if (mID == View.NO_ID) return null;
9207                final int id = mID;
9208                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
9209                    @Override
9210                    public boolean apply(View t) {
9211                        return t.mNextFocusForwardId == id;
9212                    }
9213                });
9214            }
9215        }
9216        return null;
9217    }
9218
9219    private View findViewInsideOutShouldExist(View root, int id) {
9220        if (mMatchIdPredicate == null) {
9221            mMatchIdPredicate = new MatchIdPredicate();
9222        }
9223        mMatchIdPredicate.mId = id;
9224        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
9225        if (result == null) {
9226            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
9227        }
9228        return result;
9229    }
9230
9231    /**
9232     * Find and return all focusable views that are descendants of this view,
9233     * possibly including this view if it is focusable itself.
9234     *
9235     * @param direction The direction of the focus
9236     * @return A list of focusable views
9237     */
9238    public ArrayList<View> getFocusables(@FocusDirection int direction) {
9239        ArrayList<View> result = new ArrayList<View>(24);
9240        addFocusables(result, direction);
9241        return result;
9242    }
9243
9244    /**
9245     * Add any focusable views that are descendants of this view (possibly
9246     * including this view if it is focusable itself) to views.  If we are in touch mode,
9247     * only add views that are also focusable in touch mode.
9248     *
9249     * @param views Focusable views found so far
9250     * @param direction The direction of the focus
9251     */
9252    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
9253        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
9254    }
9255
9256    /**
9257     * Adds any focusable views that are descendants of this view (possibly
9258     * including this view if it is focusable itself) to views. This method
9259     * adds all focusable views regardless if we are in touch mode or
9260     * only views focusable in touch mode if we are in touch mode or
9261     * only views that can take accessibility focus if accessibility is enabled
9262     * depending on the focusable mode parameter.
9263     *
9264     * @param views Focusable views found so far or null if all we are interested is
9265     *        the number of focusables.
9266     * @param direction The direction of the focus.
9267     * @param focusableMode The type of focusables to be added.
9268     *
9269     * @see #FOCUSABLES_ALL
9270     * @see #FOCUSABLES_TOUCH_MODE
9271     */
9272    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
9273            @FocusableMode int focusableMode) {
9274        if (views == null) {
9275            return;
9276        }
9277        if (!isFocusable()) {
9278            return;
9279        }
9280        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
9281                && !isFocusableInTouchMode()) {
9282            return;
9283        }
9284        views.add(this);
9285    }
9286
9287    /**
9288     * Adds any keyboard navigation group roots that are descendants of this view (possibly
9289     * including this view if it is a group root itself) to views. The group type can be either a
9290     * cluster or a section.
9291     *
9292     * @param groupType Type of the keyboard navigation group
9293     * @param views Keyboard navigation group roots found so far
9294     * @param direction Direction to look
9295     */
9296    public void addKeyboardNavigationGroups(
9297            @KeyboardNavigationGroupType int groupType,
9298            @NonNull Collection<View> views,
9299            int direction) {
9300        if (!(isKeyboardNavigationGroupOfType(groupType))) {
9301            return;
9302        }
9303        views.add(this);
9304    }
9305
9306    /**
9307     * Finds the Views that contain given text. The containment is case insensitive.
9308     * The search is performed by either the text that the View renders or the content
9309     * description that describes the view for accessibility purposes and the view does
9310     * not render or both. Clients can specify how the search is to be performed via
9311     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
9312     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
9313     *
9314     * @param outViews The output list of matching Views.
9315     * @param searched The text to match against.
9316     *
9317     * @see #FIND_VIEWS_WITH_TEXT
9318     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
9319     * @see #setContentDescription(CharSequence)
9320     */
9321    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
9322            @FindViewFlags int flags) {
9323        if (getAccessibilityNodeProvider() != null) {
9324            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
9325                outViews.add(this);
9326            }
9327        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
9328                && (searched != null && searched.length() > 0)
9329                && (mContentDescription != null && mContentDescription.length() > 0)) {
9330            String searchedLowerCase = searched.toString().toLowerCase();
9331            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
9332            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
9333                outViews.add(this);
9334            }
9335        }
9336    }
9337
9338    /**
9339     * Find and return all touchable views that are descendants of this view,
9340     * possibly including this view if it is touchable itself.
9341     *
9342     * @return A list of touchable views
9343     */
9344    public ArrayList<View> getTouchables() {
9345        ArrayList<View> result = new ArrayList<View>();
9346        addTouchables(result);
9347        return result;
9348    }
9349
9350    /**
9351     * Add any touchable views that are descendants of this view (possibly
9352     * including this view if it is touchable itself) to views.
9353     *
9354     * @param views Touchable views found so far
9355     */
9356    public void addTouchables(ArrayList<View> views) {
9357        final int viewFlags = mViewFlags;
9358
9359        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
9360                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
9361                && (viewFlags & ENABLED_MASK) == ENABLED) {
9362            views.add(this);
9363        }
9364    }
9365
9366    /**
9367     * Returns whether this View is accessibility focused.
9368     *
9369     * @return True if this View is accessibility focused.
9370     */
9371    public boolean isAccessibilityFocused() {
9372        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
9373    }
9374
9375    /**
9376     * Call this to try to give accessibility focus to this view.
9377     *
9378     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
9379     * returns false or the view is no visible or the view already has accessibility
9380     * focus.
9381     *
9382     * See also {@link #focusSearch(int)}, which is what you call to say that you
9383     * have focus, and you want your parent to look for the next one.
9384     *
9385     * @return Whether this view actually took accessibility focus.
9386     *
9387     * @hide
9388     */
9389    public boolean requestAccessibilityFocus() {
9390        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
9391        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
9392            return false;
9393        }
9394        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9395            return false;
9396        }
9397        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
9398            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
9399            ViewRootImpl viewRootImpl = getViewRootImpl();
9400            if (viewRootImpl != null) {
9401                viewRootImpl.setAccessibilityFocus(this, null);
9402            }
9403            invalidate();
9404            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
9405            return true;
9406        }
9407        return false;
9408    }
9409
9410    /**
9411     * Call this to try to clear accessibility focus of this view.
9412     *
9413     * See also {@link #focusSearch(int)}, which is what you call to say that you
9414     * have focus, and you want your parent to look for the next one.
9415     *
9416     * @hide
9417     */
9418    public void clearAccessibilityFocus() {
9419        clearAccessibilityFocusNoCallbacks(0);
9420
9421        // Clear the global reference of accessibility focus if this view or
9422        // any of its descendants had accessibility focus. This will NOT send
9423        // an event or update internal state if focus is cleared from a
9424        // descendant view, which may leave views in inconsistent states.
9425        final ViewRootImpl viewRootImpl = getViewRootImpl();
9426        if (viewRootImpl != null) {
9427            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
9428            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9429                viewRootImpl.setAccessibilityFocus(null, null);
9430            }
9431        }
9432    }
9433
9434    private void sendAccessibilityHoverEvent(int eventType) {
9435        // Since we are not delivering to a client accessibility events from not
9436        // important views (unless the clinet request that) we need to fire the
9437        // event from the deepest view exposed to the client. As a consequence if
9438        // the user crosses a not exposed view the client will see enter and exit
9439        // of the exposed predecessor followed by and enter and exit of that same
9440        // predecessor when entering and exiting the not exposed descendant. This
9441        // is fine since the client has a clear idea which view is hovered at the
9442        // price of a couple more events being sent. This is a simple and
9443        // working solution.
9444        View source = this;
9445        while (true) {
9446            if (source.includeForAccessibility()) {
9447                source.sendAccessibilityEvent(eventType);
9448                return;
9449            }
9450            ViewParent parent = source.getParent();
9451            if (parent instanceof View) {
9452                source = (View) parent;
9453            } else {
9454                return;
9455            }
9456        }
9457    }
9458
9459    /**
9460     * Clears accessibility focus without calling any callback methods
9461     * normally invoked in {@link #clearAccessibilityFocus()}. This method
9462     * is used separately from that one for clearing accessibility focus when
9463     * giving this focus to another view.
9464     *
9465     * @param action The action, if any, that led to focus being cleared. Set to
9466     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
9467     * the window.
9468     */
9469    void clearAccessibilityFocusNoCallbacks(int action) {
9470        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
9471            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
9472            invalidate();
9473            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9474                AccessibilityEvent event = AccessibilityEvent.obtain(
9475                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
9476                event.setAction(action);
9477                if (mAccessibilityDelegate != null) {
9478                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
9479                } else {
9480                    sendAccessibilityEventUnchecked(event);
9481                }
9482            }
9483        }
9484    }
9485
9486    /**
9487     * Call this to try to give focus to a specific view or to one of its
9488     * descendants.
9489     *
9490     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9491     * false), or if it is focusable and it is not focusable in touch mode
9492     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9493     *
9494     * See also {@link #focusSearch(int)}, which is what you call to say that you
9495     * have focus, and you want your parent to look for the next one.
9496     *
9497     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
9498     * {@link #FOCUS_DOWN} and <code>null</code>.
9499     *
9500     * @return Whether this view or one of its descendants actually took focus.
9501     */
9502    public final boolean requestFocus() {
9503        return requestFocus(View.FOCUS_DOWN);
9504    }
9505
9506    /**
9507     * Gives focus to the last focused view in the view hierarchy that has this view as a root.
9508     * If the last focused view cannot be found, fall back to calling {@link #requestFocus()}.
9509     * Nested keyboard navigation clusters are excluded from the hierarchy considered for saving the
9510     * last focus.
9511     *
9512     * @return Whether this view or one of its descendants actually took focus.
9513     */
9514    public boolean restoreLastFocus() {
9515        return requestFocus();
9516    }
9517
9518    /**
9519     * Call this to try to give focus to a specific view or to one of its
9520     * descendants and give it a hint about what direction focus is heading.
9521     *
9522     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9523     * false), or if it is focusable and it is not focusable in touch mode
9524     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9525     *
9526     * See also {@link #focusSearch(int)}, which is what you call to say that you
9527     * have focus, and you want your parent to look for the next one.
9528     *
9529     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
9530     * <code>null</code> set for the previously focused rectangle.
9531     *
9532     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9533     * @return Whether this view or one of its descendants actually took focus.
9534     */
9535    public final boolean requestFocus(int direction) {
9536        return requestFocus(direction, null);
9537    }
9538
9539    /**
9540     * Call this to try to give focus to a specific view or to one of its descendants
9541     * and give it hints about the direction and a specific rectangle that the focus
9542     * is coming from.  The rectangle can help give larger views a finer grained hint
9543     * about where focus is coming from, and therefore, where to show selection, or
9544     * forward focus change internally.
9545     *
9546     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9547     * false), or if it is focusable and it is not focusable in touch mode
9548     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9549     *
9550     * A View will not take focus if it is not visible.
9551     *
9552     * A View will not take focus if one of its parents has
9553     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
9554     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
9555     *
9556     * See also {@link #focusSearch(int)}, which is what you call to say that you
9557     * have focus, and you want your parent to look for the next one.
9558     *
9559     * You may wish to override this method if your custom {@link View} has an internal
9560     * {@link View} that it wishes to forward the request to.
9561     *
9562     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9563     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
9564     *        to give a finer grained hint about where focus is coming from.  May be null
9565     *        if there is no hint.
9566     * @return Whether this view or one of its descendants actually took focus.
9567     */
9568    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
9569        return requestFocusNoSearch(direction, previouslyFocusedRect);
9570    }
9571
9572    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
9573        // need to be focusable
9574        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
9575                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9576            return false;
9577        }
9578
9579        // need to be focusable in touch mode if in touch mode
9580        if (isInTouchMode() &&
9581            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
9582               return false;
9583        }
9584
9585        // need to not have any parents blocking us
9586        if (hasAncestorThatBlocksDescendantFocus()) {
9587            return false;
9588        }
9589
9590        handleFocusGainInternal(direction, previouslyFocusedRect);
9591        return true;
9592    }
9593
9594    /**
9595     * Call this to try to give focus to a specific view or to one of its descendants. This is a
9596     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
9597     * touch mode to request focus when they are touched.
9598     *
9599     * @return Whether this view or one of its descendants actually took focus.
9600     *
9601     * @see #isInTouchMode()
9602     *
9603     */
9604    public final boolean requestFocusFromTouch() {
9605        // Leave touch mode if we need to
9606        if (isInTouchMode()) {
9607            ViewRootImpl viewRoot = getViewRootImpl();
9608            if (viewRoot != null) {
9609                viewRoot.ensureTouchMode(false);
9610            }
9611        }
9612        return requestFocus(View.FOCUS_DOWN);
9613    }
9614
9615    /**
9616     * @return Whether any ancestor of this view blocks descendant focus.
9617     */
9618    private boolean hasAncestorThatBlocksDescendantFocus() {
9619        final boolean focusableInTouchMode = isFocusableInTouchMode();
9620        ViewParent ancestor = mParent;
9621        while (ancestor instanceof ViewGroup) {
9622            final ViewGroup vgAncestor = (ViewGroup) ancestor;
9623            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
9624                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
9625                return true;
9626            } else {
9627                ancestor = vgAncestor.getParent();
9628            }
9629        }
9630        return false;
9631    }
9632
9633    /**
9634     * Gets the mode for determining whether this View is important for accessibility.
9635     * A view is important for accessibility if it fires accessibility events and if it
9636     * is reported to accessibility services that query the screen.
9637     *
9638     * @return The mode for determining whether a view is important for accessibility, one
9639     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
9640     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
9641     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
9642     *
9643     * @attr ref android.R.styleable#View_importantForAccessibility
9644     *
9645     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9646     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9647     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9648     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9649     */
9650    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
9651            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
9652            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
9653            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
9654            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
9655                    to = "noHideDescendants")
9656        })
9657    public int getImportantForAccessibility() {
9658        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9659                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9660    }
9661
9662    /**
9663     * Sets the live region mode for this view. This indicates to accessibility
9664     * services whether they should automatically notify the user about changes
9665     * to the view's content description or text, or to the content descriptions
9666     * or text of the view's children (where applicable).
9667     * <p>
9668     * For example, in a login screen with a TextView that displays an "incorrect
9669     * password" notification, that view should be marked as a live region with
9670     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9671     * <p>
9672     * To disable change notifications for this view, use
9673     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
9674     * mode for most views.
9675     * <p>
9676     * To indicate that the user should be notified of changes, use
9677     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9678     * <p>
9679     * If the view's changes should interrupt ongoing speech and notify the user
9680     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
9681     *
9682     * @param mode The live region mode for this view, one of:
9683     *        <ul>
9684     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
9685     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
9686     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
9687     *        </ul>
9688     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9689     */
9690    public void setAccessibilityLiveRegion(int mode) {
9691        if (mode != getAccessibilityLiveRegion()) {
9692            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9693            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
9694                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9695            notifyViewAccessibilityStateChangedIfNeeded(
9696                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9697        }
9698    }
9699
9700    /**
9701     * Gets the live region mode for this View.
9702     *
9703     * @return The live region mode for the view.
9704     *
9705     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9706     *
9707     * @see #setAccessibilityLiveRegion(int)
9708     */
9709    public int getAccessibilityLiveRegion() {
9710        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
9711                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
9712    }
9713
9714    /**
9715     * Sets how to determine whether this view is important for accessibility
9716     * which is if it fires accessibility events and if it is reported to
9717     * accessibility services that query the screen.
9718     *
9719     * @param mode How to determine whether this view is important for accessibility.
9720     *
9721     * @attr ref android.R.styleable#View_importantForAccessibility
9722     *
9723     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9724     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9725     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9726     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9727     */
9728    public void setImportantForAccessibility(int mode) {
9729        final int oldMode = getImportantForAccessibility();
9730        if (mode != oldMode) {
9731            final boolean hideDescendants =
9732                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
9733
9734            // If this node or its descendants are no longer important, try to
9735            // clear accessibility focus.
9736            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
9737                final View focusHost = findAccessibilityFocusHost(hideDescendants);
9738                if (focusHost != null) {
9739                    focusHost.clearAccessibilityFocus();
9740                }
9741            }
9742
9743            // If we're moving between AUTO and another state, we might not need
9744            // to send a subtree changed notification. We'll store the computed
9745            // importance, since we'll need to check it later to make sure.
9746            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
9747                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
9748            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
9749            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9750            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
9751                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9752            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
9753                notifySubtreeAccessibilityStateChangedIfNeeded();
9754            } else {
9755                notifyViewAccessibilityStateChangedIfNeeded(
9756                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9757            }
9758        }
9759    }
9760
9761    /**
9762     * Returns the view within this view's hierarchy that is hosting
9763     * accessibility focus.
9764     *
9765     * @param searchDescendants whether to search for focus in descendant views
9766     * @return the view hosting accessibility focus, or {@code null}
9767     */
9768    private View findAccessibilityFocusHost(boolean searchDescendants) {
9769        if (isAccessibilityFocusedViewOrHost()) {
9770            return this;
9771        }
9772
9773        if (searchDescendants) {
9774            final ViewRootImpl viewRoot = getViewRootImpl();
9775            if (viewRoot != null) {
9776                final View focusHost = viewRoot.getAccessibilityFocusedHost();
9777                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9778                    return focusHost;
9779                }
9780            }
9781        }
9782
9783        return null;
9784    }
9785
9786    /**
9787     * Computes whether this view should be exposed for accessibility. In
9788     * general, views that are interactive or provide information are exposed
9789     * while views that serve only as containers are hidden.
9790     * <p>
9791     * If an ancestor of this view has importance
9792     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
9793     * returns <code>false</code>.
9794     * <p>
9795     * Otherwise, the value is computed according to the view's
9796     * {@link #getImportantForAccessibility()} value:
9797     * <ol>
9798     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
9799     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
9800     * </code>
9801     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
9802     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
9803     * view satisfies any of the following:
9804     * <ul>
9805     * <li>Is actionable, e.g. {@link #isClickable()},
9806     * {@link #isLongClickable()}, or {@link #isFocusable()}
9807     * <li>Has an {@link AccessibilityDelegate}
9808     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
9809     * {@link OnKeyListener}, etc.
9810     * <li>Is an accessibility live region, e.g.
9811     * {@link #getAccessibilityLiveRegion()} is not
9812     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
9813     * </ul>
9814     * </ol>
9815     *
9816     * @return Whether the view is exposed for accessibility.
9817     * @see #setImportantForAccessibility(int)
9818     * @see #getImportantForAccessibility()
9819     */
9820    public boolean isImportantForAccessibility() {
9821        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9822                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9823        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
9824                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9825            return false;
9826        }
9827
9828        // Check parent mode to ensure we're not hidden.
9829        ViewParent parent = mParent;
9830        while (parent instanceof View) {
9831            if (((View) parent).getImportantForAccessibility()
9832                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9833                return false;
9834            }
9835            parent = parent.getParent();
9836        }
9837
9838        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
9839                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
9840                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
9841    }
9842
9843    /**
9844     * Gets the parent for accessibility purposes. Note that the parent for
9845     * accessibility is not necessary the immediate parent. It is the first
9846     * predecessor that is important for accessibility.
9847     *
9848     * @return The parent for accessibility purposes.
9849     */
9850    public ViewParent getParentForAccessibility() {
9851        if (mParent instanceof View) {
9852            View parentView = (View) mParent;
9853            if (parentView.includeForAccessibility()) {
9854                return mParent;
9855            } else {
9856                return mParent.getParentForAccessibility();
9857            }
9858        }
9859        return null;
9860    }
9861
9862    /**
9863     * Adds the children of this View relevant for accessibility to the given list
9864     * as output. Since some Views are not important for accessibility the added
9865     * child views are not necessarily direct children of this view, rather they are
9866     * the first level of descendants important for accessibility.
9867     *
9868     * @param outChildren The output list that will receive children for accessibility.
9869     */
9870    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
9871
9872    }
9873
9874    /**
9875     * Whether to regard this view for accessibility. A view is regarded for
9876     * accessibility if it is important for accessibility or the querying
9877     * accessibility service has explicitly requested that view not
9878     * important for accessibility are regarded.
9879     *
9880     * @return Whether to regard the view for accessibility.
9881     *
9882     * @hide
9883     */
9884    public boolean includeForAccessibility() {
9885        if (mAttachInfo != null) {
9886            return (mAttachInfo.mAccessibilityFetchFlags
9887                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
9888                    || isImportantForAccessibility();
9889        }
9890        return false;
9891    }
9892
9893    /**
9894     * Returns whether the View is considered actionable from
9895     * accessibility perspective. Such view are important for
9896     * accessibility.
9897     *
9898     * @return True if the view is actionable for accessibility.
9899     *
9900     * @hide
9901     */
9902    public boolean isActionableForAccessibility() {
9903        return (isClickable() || isLongClickable() || isFocusable());
9904    }
9905
9906    /**
9907     * Returns whether the View has registered callbacks which makes it
9908     * important for accessibility.
9909     *
9910     * @return True if the view is actionable for accessibility.
9911     */
9912    private boolean hasListenersForAccessibility() {
9913        ListenerInfo info = getListenerInfo();
9914        return mTouchDelegate != null || info.mOnKeyListener != null
9915                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
9916                || info.mOnHoverListener != null || info.mOnDragListener != null;
9917    }
9918
9919    /**
9920     * Notifies that the accessibility state of this view changed. The change
9921     * is local to this view and does not represent structural changes such
9922     * as children and parent. For example, the view became focusable. The
9923     * notification is at at most once every
9924     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9925     * to avoid unnecessary load to the system. Also once a view has a pending
9926     * notification this method is a NOP until the notification has been sent.
9927     *
9928     * @hide
9929     */
9930    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
9931        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9932            return;
9933        }
9934        if (mSendViewStateChangedAccessibilityEvent == null) {
9935            mSendViewStateChangedAccessibilityEvent =
9936                    new SendViewStateChangedAccessibilityEvent();
9937        }
9938        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9939    }
9940
9941    /**
9942     * Notifies that the accessibility state of this view changed. The change
9943     * is *not* local to this view and does represent structural changes such
9944     * as children and parent. For example, the view size changed. The
9945     * notification is at at most once every
9946     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9947     * to avoid unnecessary load to the system. Also once a view has a pending
9948     * notification this method is a NOP until the notification has been sent.
9949     *
9950     * @hide
9951     */
9952    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9953        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9954            return;
9955        }
9956        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9957            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9958            if (mParent != null) {
9959                try {
9960                    mParent.notifySubtreeAccessibilityStateChanged(
9961                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9962                } catch (AbstractMethodError e) {
9963                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9964                            " does not fully implement ViewParent", e);
9965                }
9966            }
9967        }
9968    }
9969
9970    /**
9971     * Change the visibility of the View without triggering any other changes. This is
9972     * important for transitions, where visibility changes should not adjust focus or
9973     * trigger a new layout. This is only used when the visibility has already been changed
9974     * and we need a transient value during an animation. When the animation completes,
9975     * the original visibility value is always restored.
9976     *
9977     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9978     * @hide
9979     */
9980    public void setTransitionVisibility(@Visibility int visibility) {
9981        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9982    }
9983
9984    /**
9985     * Reset the flag indicating the accessibility state of the subtree rooted
9986     * at this view changed.
9987     */
9988    void resetSubtreeAccessibilityStateChanged() {
9989        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9990    }
9991
9992    /**
9993     * Report an accessibility action to this view's parents for delegated processing.
9994     *
9995     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9996     * call this method to delegate an accessibility action to a supporting parent. If the parent
9997     * returns true from its
9998     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9999     * method this method will return true to signify that the action was consumed.</p>
10000     *
10001     * <p>This method is useful for implementing nested scrolling child views. If
10002     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
10003     * a custom view implementation may invoke this method to allow a parent to consume the
10004     * scroll first. If this method returns true the custom view should skip its own scrolling
10005     * behavior.</p>
10006     *
10007     * @param action Accessibility action to delegate
10008     * @param arguments Optional action arguments
10009     * @return true if the action was consumed by a parent
10010     */
10011    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
10012        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
10013            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
10014                return true;
10015            }
10016        }
10017        return false;
10018    }
10019
10020    /**
10021     * Performs the specified accessibility action on the view. For
10022     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
10023     * <p>
10024     * If an {@link AccessibilityDelegate} has been specified via calling
10025     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10026     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
10027     * is responsible for handling this call.
10028     * </p>
10029     *
10030     * <p>The default implementation will delegate
10031     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
10032     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
10033     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
10034     *
10035     * @param action The action to perform.
10036     * @param arguments Optional action arguments.
10037     * @return Whether the action was performed.
10038     */
10039    public boolean performAccessibilityAction(int action, Bundle arguments) {
10040      if (mAccessibilityDelegate != null) {
10041          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
10042      } else {
10043          return performAccessibilityActionInternal(action, arguments);
10044      }
10045    }
10046
10047   /**
10048    * @see #performAccessibilityAction(int, Bundle)
10049    *
10050    * Note: Called from the default {@link AccessibilityDelegate}.
10051    *
10052    * @hide
10053    */
10054    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
10055        if (isNestedScrollingEnabled()
10056                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
10057                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
10058                || action == R.id.accessibilityActionScrollUp
10059                || action == R.id.accessibilityActionScrollLeft
10060                || action == R.id.accessibilityActionScrollDown
10061                || action == R.id.accessibilityActionScrollRight)) {
10062            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
10063                return true;
10064            }
10065        }
10066
10067        switch (action) {
10068            case AccessibilityNodeInfo.ACTION_CLICK: {
10069                if (isClickable()) {
10070                    performClick();
10071                    return true;
10072                }
10073            } break;
10074            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
10075                if (isLongClickable()) {
10076                    performLongClick();
10077                    return true;
10078                }
10079            } break;
10080            case AccessibilityNodeInfo.ACTION_FOCUS: {
10081                if (!hasFocus()) {
10082                    // Get out of touch mode since accessibility
10083                    // wants to move focus around.
10084                    getViewRootImpl().ensureTouchMode(false);
10085                    return requestFocus();
10086                }
10087            } break;
10088            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
10089                if (hasFocus()) {
10090                    clearFocus();
10091                    return !isFocused();
10092                }
10093            } break;
10094            case AccessibilityNodeInfo.ACTION_SELECT: {
10095                if (!isSelected()) {
10096                    setSelected(true);
10097                    return isSelected();
10098                }
10099            } break;
10100            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
10101                if (isSelected()) {
10102                    setSelected(false);
10103                    return !isSelected();
10104                }
10105            } break;
10106            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
10107                if (!isAccessibilityFocused()) {
10108                    return requestAccessibilityFocus();
10109                }
10110            } break;
10111            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
10112                if (isAccessibilityFocused()) {
10113                    clearAccessibilityFocus();
10114                    return true;
10115                }
10116            } break;
10117            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
10118                if (arguments != null) {
10119                    final int granularity = arguments.getInt(
10120                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10121                    final boolean extendSelection = arguments.getBoolean(
10122                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10123                    return traverseAtGranularity(granularity, true, extendSelection);
10124                }
10125            } break;
10126            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
10127                if (arguments != null) {
10128                    final int granularity = arguments.getInt(
10129                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10130                    final boolean extendSelection = arguments.getBoolean(
10131                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10132                    return traverseAtGranularity(granularity, false, extendSelection);
10133                }
10134            } break;
10135            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
10136                CharSequence text = getIterableTextForAccessibility();
10137                if (text == null) {
10138                    return false;
10139                }
10140                final int start = (arguments != null) ? arguments.getInt(
10141                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
10142                final int end = (arguments != null) ? arguments.getInt(
10143                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
10144                // Only cursor position can be specified (selection length == 0)
10145                if ((getAccessibilitySelectionStart() != start
10146                        || getAccessibilitySelectionEnd() != end)
10147                        && (start == end)) {
10148                    setAccessibilitySelection(start, end);
10149                    notifyViewAccessibilityStateChangedIfNeeded(
10150                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10151                    return true;
10152                }
10153            } break;
10154            case R.id.accessibilityActionShowOnScreen: {
10155                if (mAttachInfo != null) {
10156                    final Rect r = mAttachInfo.mTmpInvalRect;
10157                    getDrawingRect(r);
10158                    return requestRectangleOnScreen(r, true);
10159                }
10160            } break;
10161            case R.id.accessibilityActionContextClick: {
10162                if (isContextClickable()) {
10163                    performContextClick();
10164                    return true;
10165                }
10166            } break;
10167        }
10168        return false;
10169    }
10170
10171    private boolean traverseAtGranularity(int granularity, boolean forward,
10172            boolean extendSelection) {
10173        CharSequence text = getIterableTextForAccessibility();
10174        if (text == null || text.length() == 0) {
10175            return false;
10176        }
10177        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
10178        if (iterator == null) {
10179            return false;
10180        }
10181        int current = getAccessibilitySelectionEnd();
10182        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
10183            current = forward ? 0 : text.length();
10184        }
10185        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
10186        if (range == null) {
10187            return false;
10188        }
10189        final int segmentStart = range[0];
10190        final int segmentEnd = range[1];
10191        int selectionStart;
10192        int selectionEnd;
10193        if (extendSelection && isAccessibilitySelectionExtendable()) {
10194            selectionStart = getAccessibilitySelectionStart();
10195            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
10196                selectionStart = forward ? segmentStart : segmentEnd;
10197            }
10198            selectionEnd = forward ? segmentEnd : segmentStart;
10199        } else {
10200            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
10201        }
10202        setAccessibilitySelection(selectionStart, selectionEnd);
10203        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
10204                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
10205        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
10206        return true;
10207    }
10208
10209    /**
10210     * Gets the text reported for accessibility purposes.
10211     *
10212     * @return The accessibility text.
10213     *
10214     * @hide
10215     */
10216    public CharSequence getIterableTextForAccessibility() {
10217        return getContentDescription();
10218    }
10219
10220    /**
10221     * Gets whether accessibility selection can be extended.
10222     *
10223     * @return If selection is extensible.
10224     *
10225     * @hide
10226     */
10227    public boolean isAccessibilitySelectionExtendable() {
10228        return false;
10229    }
10230
10231    /**
10232     * @hide
10233     */
10234    public int getAccessibilitySelectionStart() {
10235        return mAccessibilityCursorPosition;
10236    }
10237
10238    /**
10239     * @hide
10240     */
10241    public int getAccessibilitySelectionEnd() {
10242        return getAccessibilitySelectionStart();
10243    }
10244
10245    /**
10246     * @hide
10247     */
10248    public void setAccessibilitySelection(int start, int end) {
10249        if (start ==  end && end == mAccessibilityCursorPosition) {
10250            return;
10251        }
10252        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
10253            mAccessibilityCursorPosition = start;
10254        } else {
10255            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
10256        }
10257        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
10258    }
10259
10260    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
10261            int fromIndex, int toIndex) {
10262        if (mParent == null) {
10263            return;
10264        }
10265        AccessibilityEvent event = AccessibilityEvent.obtain(
10266                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
10267        onInitializeAccessibilityEvent(event);
10268        onPopulateAccessibilityEvent(event);
10269        event.setFromIndex(fromIndex);
10270        event.setToIndex(toIndex);
10271        event.setAction(action);
10272        event.setMovementGranularity(granularity);
10273        mParent.requestSendAccessibilityEvent(this, event);
10274    }
10275
10276    /**
10277     * @hide
10278     */
10279    public TextSegmentIterator getIteratorForGranularity(int granularity) {
10280        switch (granularity) {
10281            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
10282                CharSequence text = getIterableTextForAccessibility();
10283                if (text != null && text.length() > 0) {
10284                    CharacterTextSegmentIterator iterator =
10285                        CharacterTextSegmentIterator.getInstance(
10286                                mContext.getResources().getConfiguration().locale);
10287                    iterator.initialize(text.toString());
10288                    return iterator;
10289                }
10290            } break;
10291            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
10292                CharSequence text = getIterableTextForAccessibility();
10293                if (text != null && text.length() > 0) {
10294                    WordTextSegmentIterator iterator =
10295                        WordTextSegmentIterator.getInstance(
10296                                mContext.getResources().getConfiguration().locale);
10297                    iterator.initialize(text.toString());
10298                    return iterator;
10299                }
10300            } break;
10301            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
10302                CharSequence text = getIterableTextForAccessibility();
10303                if (text != null && text.length() > 0) {
10304                    ParagraphTextSegmentIterator iterator =
10305                        ParagraphTextSegmentIterator.getInstance();
10306                    iterator.initialize(text.toString());
10307                    return iterator;
10308                }
10309            } break;
10310        }
10311        return null;
10312    }
10313
10314    /**
10315     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
10316     * and {@link #onFinishTemporaryDetach()}.
10317     *
10318     * <p>This method always returns {@code true} when called directly or indirectly from
10319     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
10320     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
10321     * <ul>
10322     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
10323     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
10324     * </ul>
10325     * </p>
10326     *
10327     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
10328     * and {@link #onFinishTemporaryDetach()}.
10329     */
10330    public final boolean isTemporarilyDetached() {
10331        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
10332    }
10333
10334    /**
10335     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
10336     * a container View.
10337     */
10338    @CallSuper
10339    public void dispatchStartTemporaryDetach() {
10340        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
10341        onStartTemporaryDetach();
10342    }
10343
10344    /**
10345     * This is called when a container is going to temporarily detach a child, with
10346     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
10347     * It will either be followed by {@link #onFinishTemporaryDetach()} or
10348     * {@link #onDetachedFromWindow()} when the container is done.
10349     */
10350    public void onStartTemporaryDetach() {
10351        removeUnsetPressCallback();
10352        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
10353    }
10354
10355    /**
10356     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
10357     * a container View.
10358     */
10359    @CallSuper
10360    public void dispatchFinishTemporaryDetach() {
10361        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
10362        onFinishTemporaryDetach();
10363        if (hasWindowFocus() && hasFocus()) {
10364            InputMethodManager.getInstance().focusIn(this);
10365        }
10366    }
10367
10368    /**
10369     * Called after {@link #onStartTemporaryDetach} when the container is done
10370     * changing the view.
10371     */
10372    public void onFinishTemporaryDetach() {
10373    }
10374
10375    /**
10376     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
10377     * for this view's window.  Returns null if the view is not currently attached
10378     * to the window.  Normally you will not need to use this directly, but
10379     * just use the standard high-level event callbacks like
10380     * {@link #onKeyDown(int, KeyEvent)}.
10381     */
10382    public KeyEvent.DispatcherState getKeyDispatcherState() {
10383        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
10384    }
10385
10386    /**
10387     * Dispatch a key event before it is processed by any input method
10388     * associated with the view hierarchy.  This can be used to intercept
10389     * key events in special situations before the IME consumes them; a
10390     * typical example would be handling the BACK key to update the application's
10391     * UI instead of allowing the IME to see it and close itself.
10392     *
10393     * @param event The key event to be dispatched.
10394     * @return True if the event was handled, false otherwise.
10395     */
10396    public boolean dispatchKeyEventPreIme(KeyEvent event) {
10397        return onKeyPreIme(event.getKeyCode(), event);
10398    }
10399
10400    /**
10401     * Dispatch a key event to the next view on the focus path. This path runs
10402     * from the top of the view tree down to the currently focused view. If this
10403     * view has focus, it will dispatch to itself. Otherwise it will dispatch
10404     * the next node down the focus path. This method also fires any key
10405     * listeners.
10406     *
10407     * @param event The key event to be dispatched.
10408     * @return True if the event was handled, false otherwise.
10409     */
10410    public boolean dispatchKeyEvent(KeyEvent event) {
10411        if (mInputEventConsistencyVerifier != null) {
10412            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
10413        }
10414
10415        // Give any attached key listener a first crack at the event.
10416        //noinspection SimplifiableIfStatement
10417        ListenerInfo li = mListenerInfo;
10418        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
10419                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
10420            return true;
10421        }
10422
10423        if (event.dispatch(this, mAttachInfo != null
10424                ? mAttachInfo.mKeyDispatchState : null, this)) {
10425            return true;
10426        }
10427
10428        if (mInputEventConsistencyVerifier != null) {
10429            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10430        }
10431        return false;
10432    }
10433
10434    /**
10435     * Dispatches a key shortcut event.
10436     *
10437     * @param event The key event to be dispatched.
10438     * @return True if the event was handled by the view, false otherwise.
10439     */
10440    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
10441        return onKeyShortcut(event.getKeyCode(), event);
10442    }
10443
10444    /**
10445     * Pass the touch screen motion event down to the target view, or this
10446     * view if it is the target.
10447     *
10448     * @param event The motion event to be dispatched.
10449     * @return True if the event was handled by the view, false otherwise.
10450     */
10451    public boolean dispatchTouchEvent(MotionEvent event) {
10452        // If the event should be handled by accessibility focus first.
10453        if (event.isTargetAccessibilityFocus()) {
10454            // We don't have focus or no virtual descendant has it, do not handle the event.
10455            if (!isAccessibilityFocusedViewOrHost()) {
10456                return false;
10457            }
10458            // We have focus and got the event, then use normal event dispatch.
10459            event.setTargetAccessibilityFocus(false);
10460        }
10461
10462        boolean result = false;
10463
10464        if (mInputEventConsistencyVerifier != null) {
10465            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
10466        }
10467
10468        final int actionMasked = event.getActionMasked();
10469        if (actionMasked == MotionEvent.ACTION_DOWN) {
10470            // Defensive cleanup for new gesture
10471            stopNestedScroll();
10472        }
10473
10474        if (onFilterTouchEventForSecurity(event)) {
10475            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
10476                result = true;
10477            }
10478            //noinspection SimplifiableIfStatement
10479            ListenerInfo li = mListenerInfo;
10480            if (li != null && li.mOnTouchListener != null
10481                    && (mViewFlags & ENABLED_MASK) == ENABLED
10482                    && li.mOnTouchListener.onTouch(this, event)) {
10483                result = true;
10484            }
10485
10486            if (!result && onTouchEvent(event)) {
10487                result = true;
10488            }
10489        }
10490
10491        if (!result && mInputEventConsistencyVerifier != null) {
10492            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10493        }
10494
10495        // Clean up after nested scrolls if this is the end of a gesture;
10496        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
10497        // of the gesture.
10498        if (actionMasked == MotionEvent.ACTION_UP ||
10499                actionMasked == MotionEvent.ACTION_CANCEL ||
10500                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
10501            stopNestedScroll();
10502        }
10503
10504        return result;
10505    }
10506
10507    boolean isAccessibilityFocusedViewOrHost() {
10508        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
10509                .getAccessibilityFocusedHost() == this);
10510    }
10511
10512    /**
10513     * Filter the touch event to apply security policies.
10514     *
10515     * @param event The motion event to be filtered.
10516     * @return True if the event should be dispatched, false if the event should be dropped.
10517     *
10518     * @see #getFilterTouchesWhenObscured
10519     */
10520    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
10521        //noinspection RedundantIfStatement
10522        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
10523                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
10524            // Window is obscured, drop this touch.
10525            return false;
10526        }
10527        return true;
10528    }
10529
10530    /**
10531     * Pass a trackball motion event down to the focused view.
10532     *
10533     * @param event The motion event to be dispatched.
10534     * @return True if the event was handled by the view, false otherwise.
10535     */
10536    public boolean dispatchTrackballEvent(MotionEvent event) {
10537        if (mInputEventConsistencyVerifier != null) {
10538            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
10539        }
10540
10541        return onTrackballEvent(event);
10542    }
10543
10544    /**
10545     * Dispatch a generic motion event.
10546     * <p>
10547     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10548     * are delivered to the view under the pointer.  All other generic motion events are
10549     * delivered to the focused view.  Hover events are handled specially and are delivered
10550     * to {@link #onHoverEvent(MotionEvent)}.
10551     * </p>
10552     *
10553     * @param event The motion event to be dispatched.
10554     * @return True if the event was handled by the view, false otherwise.
10555     */
10556    public boolean dispatchGenericMotionEvent(MotionEvent event) {
10557        if (mInputEventConsistencyVerifier != null) {
10558            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
10559        }
10560
10561        final int source = event.getSource();
10562        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
10563            final int action = event.getAction();
10564            if (action == MotionEvent.ACTION_HOVER_ENTER
10565                    || action == MotionEvent.ACTION_HOVER_MOVE
10566                    || action == MotionEvent.ACTION_HOVER_EXIT) {
10567                if (dispatchHoverEvent(event)) {
10568                    return true;
10569                }
10570            } else if (dispatchGenericPointerEvent(event)) {
10571                return true;
10572            }
10573        } else if (dispatchGenericFocusedEvent(event)) {
10574            return true;
10575        }
10576
10577        if (dispatchGenericMotionEventInternal(event)) {
10578            return true;
10579        }
10580
10581        if (mInputEventConsistencyVerifier != null) {
10582            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10583        }
10584        return false;
10585    }
10586
10587    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
10588        //noinspection SimplifiableIfStatement
10589        ListenerInfo li = mListenerInfo;
10590        if (li != null && li.mOnGenericMotionListener != null
10591                && (mViewFlags & ENABLED_MASK) == ENABLED
10592                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
10593            return true;
10594        }
10595
10596        if (onGenericMotionEvent(event)) {
10597            return true;
10598        }
10599
10600        final int actionButton = event.getActionButton();
10601        switch (event.getActionMasked()) {
10602            case MotionEvent.ACTION_BUTTON_PRESS:
10603                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
10604                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10605                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10606                    if (performContextClick(event.getX(), event.getY())) {
10607                        mInContextButtonPress = true;
10608                        setPressed(true, event.getX(), event.getY());
10609                        removeTapCallback();
10610                        removeLongPressCallback();
10611                        return true;
10612                    }
10613                }
10614                break;
10615
10616            case MotionEvent.ACTION_BUTTON_RELEASE:
10617                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10618                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10619                    mInContextButtonPress = false;
10620                    mIgnoreNextUpEvent = true;
10621                }
10622                break;
10623        }
10624
10625        if (mInputEventConsistencyVerifier != null) {
10626            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10627        }
10628        return false;
10629    }
10630
10631    /**
10632     * Dispatch a hover event.
10633     * <p>
10634     * Do not call this method directly.
10635     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10636     * </p>
10637     *
10638     * @param event The motion event to be dispatched.
10639     * @return True if the event was handled by the view, false otherwise.
10640     */
10641    protected boolean dispatchHoverEvent(MotionEvent event) {
10642        ListenerInfo li = mListenerInfo;
10643        //noinspection SimplifiableIfStatement
10644        if (li != null && li.mOnHoverListener != null
10645                && (mViewFlags & ENABLED_MASK) == ENABLED
10646                && li.mOnHoverListener.onHover(this, event)) {
10647            return true;
10648        }
10649
10650        return onHoverEvent(event);
10651    }
10652
10653    /**
10654     * Returns true if the view has a child to which it has recently sent
10655     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
10656     * it does not have a hovered child, then it must be the innermost hovered view.
10657     * @hide
10658     */
10659    protected boolean hasHoveredChild() {
10660        return false;
10661    }
10662
10663    /**
10664     * Dispatch a generic motion event to the view under the first pointer.
10665     * <p>
10666     * Do not call this method directly.
10667     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10668     * </p>
10669     *
10670     * @param event The motion event to be dispatched.
10671     * @return True if the event was handled by the view, false otherwise.
10672     */
10673    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
10674        return false;
10675    }
10676
10677    /**
10678     * Dispatch a generic motion event to the currently focused view.
10679     * <p>
10680     * Do not call this method directly.
10681     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10682     * </p>
10683     *
10684     * @param event The motion event to be dispatched.
10685     * @return True if the event was handled by the view, false otherwise.
10686     */
10687    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
10688        return false;
10689    }
10690
10691    /**
10692     * Dispatch a pointer event.
10693     * <p>
10694     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
10695     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
10696     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
10697     * and should not be expected to handle other pointing device features.
10698     * </p>
10699     *
10700     * @param event The motion event to be dispatched.
10701     * @return True if the event was handled by the view, false otherwise.
10702     * @hide
10703     */
10704    public final boolean dispatchPointerEvent(MotionEvent event) {
10705        if (event.isTouchEvent()) {
10706            return dispatchTouchEvent(event);
10707        } else {
10708            return dispatchGenericMotionEvent(event);
10709        }
10710    }
10711
10712    /**
10713     * Called when the window containing this view gains or loses window focus.
10714     * ViewGroups should override to route to their children.
10715     *
10716     * @param hasFocus True if the window containing this view now has focus,
10717     *        false otherwise.
10718     */
10719    public void dispatchWindowFocusChanged(boolean hasFocus) {
10720        onWindowFocusChanged(hasFocus);
10721    }
10722
10723    /**
10724     * Called when the window containing this view gains or loses focus.  Note
10725     * that this is separate from view focus: to receive key events, both
10726     * your view and its window must have focus.  If a window is displayed
10727     * on top of yours that takes input focus, then your own window will lose
10728     * focus but the view focus will remain unchanged.
10729     *
10730     * @param hasWindowFocus True if the window containing this view now has
10731     *        focus, false otherwise.
10732     */
10733    public void onWindowFocusChanged(boolean hasWindowFocus) {
10734        InputMethodManager imm = InputMethodManager.peekInstance();
10735        if (!hasWindowFocus) {
10736            if (isPressed()) {
10737                setPressed(false);
10738            }
10739            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
10740            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10741                imm.focusOut(this);
10742            }
10743            removeLongPressCallback();
10744            removeTapCallback();
10745            onFocusLost();
10746        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10747            imm.focusIn(this);
10748        }
10749        refreshDrawableState();
10750    }
10751
10752    /**
10753     * Returns true if this view is in a window that currently has window focus.
10754     * Note that this is not the same as the view itself having focus.
10755     *
10756     * @return True if this view is in a window that currently has window focus.
10757     */
10758    public boolean hasWindowFocus() {
10759        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
10760    }
10761
10762    /**
10763     * Dispatch a view visibility change down the view hierarchy.
10764     * ViewGroups should override to route to their children.
10765     * @param changedView The view whose visibility changed. Could be 'this' or
10766     * an ancestor view.
10767     * @param visibility The new visibility of changedView: {@link #VISIBLE},
10768     * {@link #INVISIBLE} or {@link #GONE}.
10769     */
10770    protected void dispatchVisibilityChanged(@NonNull View changedView,
10771            @Visibility int visibility) {
10772        onVisibilityChanged(changedView, visibility);
10773    }
10774
10775    /**
10776     * Called when the visibility of the view or an ancestor of the view has
10777     * changed.
10778     *
10779     * @param changedView The view whose visibility changed. May be
10780     *                    {@code this} or an ancestor view.
10781     * @param visibility The new visibility, one of {@link #VISIBLE},
10782     *                   {@link #INVISIBLE} or {@link #GONE}.
10783     */
10784    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
10785    }
10786
10787    /**
10788     * Dispatch a hint about whether this view is displayed. For instance, when
10789     * a View moves out of the screen, it might receives a display hint indicating
10790     * the view is not displayed. Applications should not <em>rely</em> on this hint
10791     * as there is no guarantee that they will receive one.
10792     *
10793     * @param hint A hint about whether or not this view is displayed:
10794     * {@link #VISIBLE} or {@link #INVISIBLE}.
10795     */
10796    public void dispatchDisplayHint(@Visibility int hint) {
10797        onDisplayHint(hint);
10798    }
10799
10800    /**
10801     * Gives this view a hint about whether is displayed or not. For instance, when
10802     * a View moves out of the screen, it might receives a display hint indicating
10803     * the view is not displayed. Applications should not <em>rely</em> on this hint
10804     * as there is no guarantee that they will receive one.
10805     *
10806     * @param hint A hint about whether or not this view is displayed:
10807     * {@link #VISIBLE} or {@link #INVISIBLE}.
10808     */
10809    protected void onDisplayHint(@Visibility int hint) {
10810    }
10811
10812    /**
10813     * Dispatch a window visibility change down the view hierarchy.
10814     * ViewGroups should override to route to their children.
10815     *
10816     * @param visibility The new visibility of the window.
10817     *
10818     * @see #onWindowVisibilityChanged(int)
10819     */
10820    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
10821        onWindowVisibilityChanged(visibility);
10822    }
10823
10824    /**
10825     * Called when the window containing has change its visibility
10826     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
10827     * that this tells you whether or not your window is being made visible
10828     * to the window manager; this does <em>not</em> tell you whether or not
10829     * your window is obscured by other windows on the screen, even if it
10830     * is itself visible.
10831     *
10832     * @param visibility The new visibility of the window.
10833     */
10834    protected void onWindowVisibilityChanged(@Visibility int visibility) {
10835        if (visibility == VISIBLE) {
10836            initialAwakenScrollBars();
10837        }
10838    }
10839
10840    /**
10841     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
10842     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
10843     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
10844     *
10845     * @param isVisible true if this view's visibility to the user is uninterrupted by its
10846     *                  ancestors or by window visibility
10847     * @return true if this view is visible to the user, not counting clipping or overlapping
10848     */
10849    boolean dispatchVisibilityAggregated(boolean isVisible) {
10850        final boolean thisVisible = getVisibility() == VISIBLE;
10851        // If we're not visible but something is telling us we are, ignore it.
10852        if (thisVisible || !isVisible) {
10853            onVisibilityAggregated(isVisible);
10854        }
10855        return thisVisible && isVisible;
10856    }
10857
10858    /**
10859     * Called when the user-visibility of this View is potentially affected by a change
10860     * to this view itself, an ancestor view or the window this view is attached to.
10861     *
10862     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
10863     *                  and this view's window is also visible
10864     */
10865    @CallSuper
10866    public void onVisibilityAggregated(boolean isVisible) {
10867        if (isVisible && mAttachInfo != null) {
10868            initialAwakenScrollBars();
10869        }
10870
10871        final Drawable dr = mBackground;
10872        if (dr != null && isVisible != dr.isVisible()) {
10873            dr.setVisible(isVisible, false);
10874        }
10875        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
10876        if (fg != null && isVisible != fg.isVisible()) {
10877            fg.setVisible(isVisible, false);
10878        }
10879    }
10880
10881    /**
10882     * Returns the current visibility of the window this view is attached to
10883     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
10884     *
10885     * @return Returns the current visibility of the view's window.
10886     */
10887    @Visibility
10888    public int getWindowVisibility() {
10889        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
10890    }
10891
10892    /**
10893     * Retrieve the overall visible display size in which the window this view is
10894     * attached to has been positioned in.  This takes into account screen
10895     * decorations above the window, for both cases where the window itself
10896     * is being position inside of them or the window is being placed under
10897     * then and covered insets are used for the window to position its content
10898     * inside.  In effect, this tells you the available area where content can
10899     * be placed and remain visible to users.
10900     *
10901     * <p>This function requires an IPC back to the window manager to retrieve
10902     * the requested information, so should not be used in performance critical
10903     * code like drawing.
10904     *
10905     * @param outRect Filled in with the visible display frame.  If the view
10906     * is not attached to a window, this is simply the raw display size.
10907     */
10908    public void getWindowVisibleDisplayFrame(Rect outRect) {
10909        if (mAttachInfo != null) {
10910            try {
10911                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10912            } catch (RemoteException e) {
10913                return;
10914            }
10915            // XXX This is really broken, and probably all needs to be done
10916            // in the window manager, and we need to know more about whether
10917            // we want the area behind or in front of the IME.
10918            final Rect insets = mAttachInfo.mVisibleInsets;
10919            outRect.left += insets.left;
10920            outRect.top += insets.top;
10921            outRect.right -= insets.right;
10922            outRect.bottom -= insets.bottom;
10923            return;
10924        }
10925        // The view is not attached to a display so we don't have a context.
10926        // Make a best guess about the display size.
10927        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10928        d.getRectSize(outRect);
10929    }
10930
10931    /**
10932     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
10933     * is currently in without any insets.
10934     *
10935     * @hide
10936     */
10937    public void getWindowDisplayFrame(Rect outRect) {
10938        if (mAttachInfo != null) {
10939            try {
10940                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10941            } catch (RemoteException e) {
10942                return;
10943            }
10944            return;
10945        }
10946        // The view is not attached to a display so we don't have a context.
10947        // Make a best guess about the display size.
10948        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10949        d.getRectSize(outRect);
10950    }
10951
10952    /**
10953     * Dispatch a notification about a resource configuration change down
10954     * the view hierarchy.
10955     * ViewGroups should override to route to their children.
10956     *
10957     * @param newConfig The new resource configuration.
10958     *
10959     * @see #onConfigurationChanged(android.content.res.Configuration)
10960     */
10961    public void dispatchConfigurationChanged(Configuration newConfig) {
10962        onConfigurationChanged(newConfig);
10963    }
10964
10965    /**
10966     * Called when the current configuration of the resources being used
10967     * by the application have changed.  You can use this to decide when
10968     * to reload resources that can changed based on orientation and other
10969     * configuration characteristics.  You only need to use this if you are
10970     * not relying on the normal {@link android.app.Activity} mechanism of
10971     * recreating the activity instance upon a configuration change.
10972     *
10973     * @param newConfig The new resource configuration.
10974     */
10975    protected void onConfigurationChanged(Configuration newConfig) {
10976    }
10977
10978    /**
10979     * Private function to aggregate all per-view attributes in to the view
10980     * root.
10981     */
10982    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10983        performCollectViewAttributes(attachInfo, visibility);
10984    }
10985
10986    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10987        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
10988            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
10989                attachInfo.mKeepScreenOn = true;
10990            }
10991            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
10992            ListenerInfo li = mListenerInfo;
10993            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
10994                attachInfo.mHasSystemUiListeners = true;
10995            }
10996        }
10997    }
10998
10999    void needGlobalAttributesUpdate(boolean force) {
11000        final AttachInfo ai = mAttachInfo;
11001        if (ai != null && !ai.mRecomputeGlobalAttributes) {
11002            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
11003                    || ai.mHasSystemUiListeners) {
11004                ai.mRecomputeGlobalAttributes = true;
11005            }
11006        }
11007    }
11008
11009    /**
11010     * Returns whether the device is currently in touch mode.  Touch mode is entered
11011     * once the user begins interacting with the device by touch, and affects various
11012     * things like whether focus is always visible to the user.
11013     *
11014     * @return Whether the device is in touch mode.
11015     */
11016    @ViewDebug.ExportedProperty
11017    public boolean isInTouchMode() {
11018        if (mAttachInfo != null) {
11019            return mAttachInfo.mInTouchMode;
11020        } else {
11021            return ViewRootImpl.isInTouchMode();
11022        }
11023    }
11024
11025    /**
11026     * Returns the context the view is running in, through which it can
11027     * access the current theme, resources, etc.
11028     *
11029     * @return The view's Context.
11030     */
11031    @ViewDebug.CapturedViewProperty
11032    public final Context getContext() {
11033        return mContext;
11034    }
11035
11036    /**
11037     * Handle a key event before it is processed by any input method
11038     * associated with the view hierarchy.  This can be used to intercept
11039     * key events in special situations before the IME consumes them; a
11040     * typical example would be handling the BACK key to update the application's
11041     * UI instead of allowing the IME to see it and close itself.
11042     *
11043     * @param keyCode The value in event.getKeyCode().
11044     * @param event Description of the key event.
11045     * @return If you handled the event, return true. If you want to allow the
11046     *         event to be handled by the next receiver, return false.
11047     */
11048    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
11049        return false;
11050    }
11051
11052    /**
11053     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
11054     * KeyEvent.Callback.onKeyDown()}: perform press of the view
11055     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
11056     * is released, if the view is enabled and clickable.
11057     * <p>
11058     * Key presses in software keyboards will generally NOT trigger this
11059     * listener, although some may elect to do so in some situations. Do not
11060     * rely on this to catch software key presses.
11061     *
11062     * @param keyCode a key code that represents the button pressed, from
11063     *                {@link android.view.KeyEvent}
11064     * @param event the KeyEvent object that defines the button action
11065     */
11066    public boolean onKeyDown(int keyCode, KeyEvent event) {
11067        if (KeyEvent.isConfirmKey(keyCode)) {
11068            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11069                return true;
11070            }
11071
11072            if (event.getRepeatCount() == 0) {
11073                // Long clickable items don't necessarily have to be clickable.
11074                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
11075                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
11076                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
11077                    // For the purposes of menu anchoring and drawable hotspots,
11078                    // key events are considered to be at the center of the view.
11079                    final float x = getWidth() / 2f;
11080                    final float y = getHeight() / 2f;
11081                    if (clickable) {
11082                        setPressed(true, x, y);
11083                    }
11084                    checkForLongClick(0, x, y);
11085                    return true;
11086                }
11087            }
11088        }
11089
11090        return false;
11091    }
11092
11093    /**
11094     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
11095     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
11096     * the event).
11097     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11098     * although some may elect to do so in some situations. Do not rely on this to
11099     * catch software key presses.
11100     */
11101    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
11102        return false;
11103    }
11104
11105    /**
11106     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
11107     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
11108     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
11109     * or {@link KeyEvent#KEYCODE_SPACE} is released.
11110     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11111     * although some may elect to do so in some situations. Do not rely on this to
11112     * catch software key presses.
11113     *
11114     * @param keyCode A key code that represents the button pressed, from
11115     *                {@link android.view.KeyEvent}.
11116     * @param event   The KeyEvent object that defines the button action.
11117     */
11118    public boolean onKeyUp(int keyCode, KeyEvent event) {
11119        if (KeyEvent.isConfirmKey(keyCode)) {
11120            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11121                return true;
11122            }
11123            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
11124                setPressed(false);
11125
11126                if (!mHasPerformedLongPress) {
11127                    // This is a tap, so remove the longpress check
11128                    removeLongPressCallback();
11129                    return performClick();
11130                }
11131            }
11132        }
11133        return false;
11134    }
11135
11136    /**
11137     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
11138     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
11139     * the event).
11140     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11141     * although some may elect to do so in some situations. Do not rely on this to
11142     * catch software key presses.
11143     *
11144     * @param keyCode     A key code that represents the button pressed, from
11145     *                    {@link android.view.KeyEvent}.
11146     * @param repeatCount The number of times the action was made.
11147     * @param event       The KeyEvent object that defines the button action.
11148     */
11149    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
11150        return false;
11151    }
11152
11153    /**
11154     * Called on the focused view when a key shortcut event is not handled.
11155     * Override this method to implement local key shortcuts for the View.
11156     * Key shortcuts can also be implemented by setting the
11157     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
11158     *
11159     * @param keyCode The value in event.getKeyCode().
11160     * @param event Description of the key event.
11161     * @return If you handled the event, return true. If you want to allow the
11162     *         event to be handled by the next receiver, return false.
11163     */
11164    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
11165        return false;
11166    }
11167
11168    /**
11169     * Check whether the called view is a text editor, in which case it
11170     * would make sense to automatically display a soft input window for
11171     * it.  Subclasses should override this if they implement
11172     * {@link #onCreateInputConnection(EditorInfo)} to return true if
11173     * a call on that method would return a non-null InputConnection, and
11174     * they are really a first-class editor that the user would normally
11175     * start typing on when the go into a window containing your view.
11176     *
11177     * <p>The default implementation always returns false.  This does
11178     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
11179     * will not be called or the user can not otherwise perform edits on your
11180     * view; it is just a hint to the system that this is not the primary
11181     * purpose of this view.
11182     *
11183     * @return Returns true if this view is a text editor, else false.
11184     */
11185    public boolean onCheckIsTextEditor() {
11186        return false;
11187    }
11188
11189    /**
11190     * Create a new InputConnection for an InputMethod to interact
11191     * with the view.  The default implementation returns null, since it doesn't
11192     * support input methods.  You can override this to implement such support.
11193     * This is only needed for views that take focus and text input.
11194     *
11195     * <p>When implementing this, you probably also want to implement
11196     * {@link #onCheckIsTextEditor()} to indicate you will return a
11197     * non-null InputConnection.</p>
11198     *
11199     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
11200     * object correctly and in its entirety, so that the connected IME can rely
11201     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
11202     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
11203     * must be filled in with the correct cursor position for IMEs to work correctly
11204     * with your application.</p>
11205     *
11206     * @param outAttrs Fill in with attribute information about the connection.
11207     */
11208    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
11209        return null;
11210    }
11211
11212    /**
11213     * Called by the {@link android.view.inputmethod.InputMethodManager}
11214     * when a view who is not the current
11215     * input connection target is trying to make a call on the manager.  The
11216     * default implementation returns false; you can override this to return
11217     * true for certain views if you are performing InputConnection proxying
11218     * to them.
11219     * @param view The View that is making the InputMethodManager call.
11220     * @return Return true to allow the call, false to reject.
11221     */
11222    public boolean checkInputConnectionProxy(View view) {
11223        return false;
11224    }
11225
11226    /**
11227     * Show the context menu for this view. It is not safe to hold on to the
11228     * menu after returning from this method.
11229     *
11230     * You should normally not overload this method. Overload
11231     * {@link #onCreateContextMenu(ContextMenu)} or define an
11232     * {@link OnCreateContextMenuListener} to add items to the context menu.
11233     *
11234     * @param menu The context menu to populate
11235     */
11236    public void createContextMenu(ContextMenu menu) {
11237        ContextMenuInfo menuInfo = getContextMenuInfo();
11238
11239        // Sets the current menu info so all items added to menu will have
11240        // my extra info set.
11241        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
11242
11243        onCreateContextMenu(menu);
11244        ListenerInfo li = mListenerInfo;
11245        if (li != null && li.mOnCreateContextMenuListener != null) {
11246            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
11247        }
11248
11249        // Clear the extra information so subsequent items that aren't mine don't
11250        // have my extra info.
11251        ((MenuBuilder)menu).setCurrentMenuInfo(null);
11252
11253        if (mParent != null) {
11254            mParent.createContextMenu(menu);
11255        }
11256    }
11257
11258    /**
11259     * Views should implement this if they have extra information to associate
11260     * with the context menu. The return result is supplied as a parameter to
11261     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
11262     * callback.
11263     *
11264     * @return Extra information about the item for which the context menu
11265     *         should be shown. This information will vary across different
11266     *         subclasses of View.
11267     */
11268    protected ContextMenuInfo getContextMenuInfo() {
11269        return null;
11270    }
11271
11272    /**
11273     * Views should implement this if the view itself is going to add items to
11274     * the context menu.
11275     *
11276     * @param menu the context menu to populate
11277     */
11278    protected void onCreateContextMenu(ContextMenu menu) {
11279    }
11280
11281    /**
11282     * Implement this method to handle trackball motion events.  The
11283     * <em>relative</em> movement of the trackball since the last event
11284     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
11285     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
11286     * that a movement of 1 corresponds to the user pressing one DPAD key (so
11287     * they will often be fractional values, representing the more fine-grained
11288     * movement information available from a trackball).
11289     *
11290     * @param event The motion event.
11291     * @return True if the event was handled, false otherwise.
11292     */
11293    public boolean onTrackballEvent(MotionEvent event) {
11294        return false;
11295    }
11296
11297    /**
11298     * Implement this method to handle generic motion events.
11299     * <p>
11300     * Generic motion events describe joystick movements, mouse hovers, track pad
11301     * touches, scroll wheel movements and other input events.  The
11302     * {@link MotionEvent#getSource() source} of the motion event specifies
11303     * the class of input that was received.  Implementations of this method
11304     * must examine the bits in the source before processing the event.
11305     * The following code example shows how this is done.
11306     * </p><p>
11307     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11308     * are delivered to the view under the pointer.  All other generic motion events are
11309     * delivered to the focused view.
11310     * </p>
11311     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
11312     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
11313     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
11314     *             // process the joystick movement...
11315     *             return true;
11316     *         }
11317     *     }
11318     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
11319     *         switch (event.getAction()) {
11320     *             case MotionEvent.ACTION_HOVER_MOVE:
11321     *                 // process the mouse hover movement...
11322     *                 return true;
11323     *             case MotionEvent.ACTION_SCROLL:
11324     *                 // process the scroll wheel movement...
11325     *                 return true;
11326     *         }
11327     *     }
11328     *     return super.onGenericMotionEvent(event);
11329     * }</pre>
11330     *
11331     * @param event The generic motion event being processed.
11332     * @return True if the event was handled, false otherwise.
11333     */
11334    public boolean onGenericMotionEvent(MotionEvent event) {
11335        return false;
11336    }
11337
11338    /**
11339     * Implement this method to handle hover events.
11340     * <p>
11341     * This method is called whenever a pointer is hovering into, over, or out of the
11342     * bounds of a view and the view is not currently being touched.
11343     * Hover events are represented as pointer events with action
11344     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
11345     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
11346     * </p>
11347     * <ul>
11348     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
11349     * when the pointer enters the bounds of the view.</li>
11350     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
11351     * when the pointer has already entered the bounds of the view and has moved.</li>
11352     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
11353     * when the pointer has exited the bounds of the view or when the pointer is
11354     * about to go down due to a button click, tap, or similar user action that
11355     * causes the view to be touched.</li>
11356     * </ul>
11357     * <p>
11358     * The view should implement this method to return true to indicate that it is
11359     * handling the hover event, such as by changing its drawable state.
11360     * </p><p>
11361     * The default implementation calls {@link #setHovered} to update the hovered state
11362     * of the view when a hover enter or hover exit event is received, if the view
11363     * is enabled and is clickable.  The default implementation also sends hover
11364     * accessibility events.
11365     * </p>
11366     *
11367     * @param event The motion event that describes the hover.
11368     * @return True if the view handled the hover event.
11369     *
11370     * @see #isHovered
11371     * @see #setHovered
11372     * @see #onHoverChanged
11373     */
11374    public boolean onHoverEvent(MotionEvent event) {
11375        // The root view may receive hover (or touch) events that are outside the bounds of
11376        // the window.  This code ensures that we only send accessibility events for
11377        // hovers that are actually within the bounds of the root view.
11378        final int action = event.getActionMasked();
11379        if (!mSendingHoverAccessibilityEvents) {
11380            if ((action == MotionEvent.ACTION_HOVER_ENTER
11381                    || action == MotionEvent.ACTION_HOVER_MOVE)
11382                    && !hasHoveredChild()
11383                    && pointInView(event.getX(), event.getY())) {
11384                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
11385                mSendingHoverAccessibilityEvents = true;
11386            }
11387        } else {
11388            if (action == MotionEvent.ACTION_HOVER_EXIT
11389                    || (action == MotionEvent.ACTION_MOVE
11390                            && !pointInView(event.getX(), event.getY()))) {
11391                mSendingHoverAccessibilityEvents = false;
11392                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
11393            }
11394        }
11395
11396        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
11397                && event.isFromSource(InputDevice.SOURCE_MOUSE)
11398                && isOnScrollbar(event.getX(), event.getY())) {
11399            awakenScrollBars();
11400        }
11401        if (isHoverable()) {
11402            switch (action) {
11403                case MotionEvent.ACTION_HOVER_ENTER:
11404                    setHovered(true);
11405                    break;
11406                case MotionEvent.ACTION_HOVER_EXIT:
11407                    setHovered(false);
11408                    break;
11409            }
11410
11411            // Dispatch the event to onGenericMotionEvent before returning true.
11412            // This is to provide compatibility with existing applications that
11413            // handled HOVER_MOVE events in onGenericMotionEvent and that would
11414            // break because of the new default handling for hoverable views
11415            // in onHoverEvent.
11416            // Note that onGenericMotionEvent will be called by default when
11417            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
11418            dispatchGenericMotionEventInternal(event);
11419            // The event was already handled by calling setHovered(), so always
11420            // return true.
11421            return true;
11422        }
11423
11424        return false;
11425    }
11426
11427    /**
11428     * Returns true if the view should handle {@link #onHoverEvent}
11429     * by calling {@link #setHovered} to change its hovered state.
11430     *
11431     * @return True if the view is hoverable.
11432     */
11433    private boolean isHoverable() {
11434        final int viewFlags = mViewFlags;
11435        if ((viewFlags & ENABLED_MASK) == DISABLED) {
11436            return false;
11437        }
11438
11439        return (viewFlags & CLICKABLE) == CLICKABLE
11440                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
11441                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
11442    }
11443
11444    /**
11445     * Returns true if the view is currently hovered.
11446     *
11447     * @return True if the view is currently hovered.
11448     *
11449     * @see #setHovered
11450     * @see #onHoverChanged
11451     */
11452    @ViewDebug.ExportedProperty
11453    public boolean isHovered() {
11454        return (mPrivateFlags & PFLAG_HOVERED) != 0;
11455    }
11456
11457    /**
11458     * Sets whether the view is currently hovered.
11459     * <p>
11460     * Calling this method also changes the drawable state of the view.  This
11461     * enables the view to react to hover by using different drawable resources
11462     * to change its appearance.
11463     * </p><p>
11464     * The {@link #onHoverChanged} method is called when the hovered state changes.
11465     * </p>
11466     *
11467     * @param hovered True if the view is hovered.
11468     *
11469     * @see #isHovered
11470     * @see #onHoverChanged
11471     */
11472    public void setHovered(boolean hovered) {
11473        if (hovered) {
11474            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
11475                mPrivateFlags |= PFLAG_HOVERED;
11476                refreshDrawableState();
11477                onHoverChanged(true);
11478            }
11479        } else {
11480            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
11481                mPrivateFlags &= ~PFLAG_HOVERED;
11482                refreshDrawableState();
11483                onHoverChanged(false);
11484            }
11485        }
11486    }
11487
11488    /**
11489     * Implement this method to handle hover state changes.
11490     * <p>
11491     * This method is called whenever the hover state changes as a result of a
11492     * call to {@link #setHovered}.
11493     * </p>
11494     *
11495     * @param hovered The current hover state, as returned by {@link #isHovered}.
11496     *
11497     * @see #isHovered
11498     * @see #setHovered
11499     */
11500    public void onHoverChanged(boolean hovered) {
11501    }
11502
11503    /**
11504     * Handles scroll bar dragging by mouse input.
11505     *
11506     * @hide
11507     * @param event The motion event.
11508     *
11509     * @return true if the event was handled as a scroll bar dragging, false otherwise.
11510     */
11511    protected boolean handleScrollBarDragging(MotionEvent event) {
11512        if (mScrollCache == null) {
11513            return false;
11514        }
11515        final float x = event.getX();
11516        final float y = event.getY();
11517        final int action = event.getAction();
11518        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
11519                && action != MotionEvent.ACTION_DOWN)
11520                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
11521                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
11522            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11523            return false;
11524        }
11525
11526        switch (action) {
11527            case MotionEvent.ACTION_MOVE:
11528                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
11529                    return false;
11530                }
11531                if (mScrollCache.mScrollBarDraggingState
11532                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
11533                    final Rect bounds = mScrollCache.mScrollBarBounds;
11534                    getVerticalScrollBarBounds(bounds);
11535                    final int range = computeVerticalScrollRange();
11536                    final int offset = computeVerticalScrollOffset();
11537                    final int extent = computeVerticalScrollExtent();
11538
11539                    final int thumbLength = ScrollBarUtils.getThumbLength(
11540                            bounds.height(), bounds.width(), extent, range);
11541                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11542                            bounds.height(), thumbLength, extent, range, offset);
11543
11544                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
11545                    final float maxThumbOffset = bounds.height() - thumbLength;
11546                    final float newThumbOffset =
11547                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11548                    final int height = getHeight();
11549                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11550                            && height > 0 && extent > 0) {
11551                        final int newY = Math.round((range - extent)
11552                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
11553                        if (newY != getScrollY()) {
11554                            mScrollCache.mScrollBarDraggingPos = y;
11555                            setScrollY(newY);
11556                        }
11557                    }
11558                    return true;
11559                }
11560                if (mScrollCache.mScrollBarDraggingState
11561                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
11562                    final Rect bounds = mScrollCache.mScrollBarBounds;
11563                    getHorizontalScrollBarBounds(bounds);
11564                    final int range = computeHorizontalScrollRange();
11565                    final int offset = computeHorizontalScrollOffset();
11566                    final int extent = computeHorizontalScrollExtent();
11567
11568                    final int thumbLength = ScrollBarUtils.getThumbLength(
11569                            bounds.width(), bounds.height(), extent, range);
11570                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11571                            bounds.width(), thumbLength, extent, range, offset);
11572
11573                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
11574                    final float maxThumbOffset = bounds.width() - thumbLength;
11575                    final float newThumbOffset =
11576                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11577                    final int width = getWidth();
11578                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11579                            && width > 0 && extent > 0) {
11580                        final int newX = Math.round((range - extent)
11581                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
11582                        if (newX != getScrollX()) {
11583                            mScrollCache.mScrollBarDraggingPos = x;
11584                            setScrollX(newX);
11585                        }
11586                    }
11587                    return true;
11588                }
11589            case MotionEvent.ACTION_DOWN:
11590                if (mScrollCache.state == ScrollabilityCache.OFF) {
11591                    return false;
11592                }
11593                if (isOnVerticalScrollbarThumb(x, y)) {
11594                    mScrollCache.mScrollBarDraggingState =
11595                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
11596                    mScrollCache.mScrollBarDraggingPos = y;
11597                    return true;
11598                }
11599                if (isOnHorizontalScrollbarThumb(x, y)) {
11600                    mScrollCache.mScrollBarDraggingState =
11601                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
11602                    mScrollCache.mScrollBarDraggingPos = x;
11603                    return true;
11604                }
11605        }
11606        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11607        return false;
11608    }
11609
11610    /**
11611     * Implement this method to handle touch screen motion events.
11612     * <p>
11613     * If this method is used to detect click actions, it is recommended that
11614     * the actions be performed by implementing and calling
11615     * {@link #performClick()}. This will ensure consistent system behavior,
11616     * including:
11617     * <ul>
11618     * <li>obeying click sound preferences
11619     * <li>dispatching OnClickListener calls
11620     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
11621     * accessibility features are enabled
11622     * </ul>
11623     *
11624     * @param event The motion event.
11625     * @return True if the event was handled, false otherwise.
11626     */
11627    public boolean onTouchEvent(MotionEvent event) {
11628        final float x = event.getX();
11629        final float y = event.getY();
11630        final int viewFlags = mViewFlags;
11631        final int action = event.getAction();
11632
11633        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
11634                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
11635                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
11636
11637        if ((viewFlags & ENABLED_MASK) == DISABLED) {
11638            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
11639                setPressed(false);
11640            }
11641            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11642            // A disabled view that is clickable still consumes the touch
11643            // events, it just doesn't respond to them.
11644            return clickable;
11645        }
11646        if (mTouchDelegate != null) {
11647            if (mTouchDelegate.onTouchEvent(event)) {
11648                return true;
11649            }
11650        }
11651
11652        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
11653            switch (action) {
11654                case MotionEvent.ACTION_UP:
11655                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11656                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
11657                        handleTooltipUp();
11658                    }
11659                    if (!clickable) {
11660                        removeTapCallback();
11661                        removeLongPressCallback();
11662                        mInContextButtonPress = false;
11663                        mHasPerformedLongPress = false;
11664                        mIgnoreNextUpEvent = false;
11665                        break;
11666                    }
11667                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
11668                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
11669                        // take focus if we don't have it already and we should in
11670                        // touch mode.
11671                        boolean focusTaken = false;
11672                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
11673                            focusTaken = requestFocus();
11674                        }
11675
11676                        if (prepressed) {
11677                            // The button is being released before we actually
11678                            // showed it as pressed.  Make it show the pressed
11679                            // state now (before scheduling the click) to ensure
11680                            // the user sees it.
11681                            setPressed(true, x, y);
11682                        }
11683
11684                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
11685                            // This is a tap, so remove the longpress check
11686                            removeLongPressCallback();
11687
11688                            // Only perform take click actions if we were in the pressed state
11689                            if (!focusTaken) {
11690                                // Use a Runnable and post this rather than calling
11691                                // performClick directly. This lets other visual state
11692                                // of the view update before click actions start.
11693                                if (mPerformClick == null) {
11694                                    mPerformClick = new PerformClick();
11695                                }
11696                                if (!post(mPerformClick)) {
11697                                    performClick();
11698                                }
11699                            }
11700                        }
11701
11702                        if (mUnsetPressedState == null) {
11703                            mUnsetPressedState = new UnsetPressedState();
11704                        }
11705
11706                        if (prepressed) {
11707                            postDelayed(mUnsetPressedState,
11708                                    ViewConfiguration.getPressedStateDuration());
11709                        } else if (!post(mUnsetPressedState)) {
11710                            // If the post failed, unpress right now
11711                            mUnsetPressedState.run();
11712                        }
11713
11714                        removeTapCallback();
11715                    }
11716                    mIgnoreNextUpEvent = false;
11717                    break;
11718
11719                case MotionEvent.ACTION_DOWN:
11720                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
11721                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
11722                    }
11723                    mHasPerformedLongPress = false;
11724
11725                    if (!clickable) {
11726                        checkForLongClick(0, x, y);
11727                        break;
11728                    }
11729
11730                    if (performButtonActionOnTouchDown(event)) {
11731                        break;
11732                    }
11733
11734                    // Walk up the hierarchy to determine if we're inside a scrolling container.
11735                    boolean isInScrollingContainer = isInScrollingContainer();
11736
11737                    // For views inside a scrolling container, delay the pressed feedback for
11738                    // a short period in case this is a scroll.
11739                    if (isInScrollingContainer) {
11740                        mPrivateFlags |= PFLAG_PREPRESSED;
11741                        if (mPendingCheckForTap == null) {
11742                            mPendingCheckForTap = new CheckForTap();
11743                        }
11744                        mPendingCheckForTap.x = event.getX();
11745                        mPendingCheckForTap.y = event.getY();
11746                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
11747                    } else {
11748                        // Not inside a scrolling container, so show the feedback right away
11749                        setPressed(true, x, y);
11750                        checkForLongClick(0, x, y);
11751                    }
11752                    break;
11753
11754                case MotionEvent.ACTION_CANCEL:
11755                    if (clickable) {
11756                        setPressed(false);
11757                    }
11758                    removeTapCallback();
11759                    removeLongPressCallback();
11760                    mInContextButtonPress = false;
11761                    mHasPerformedLongPress = false;
11762                    mIgnoreNextUpEvent = false;
11763                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11764                    break;
11765
11766                case MotionEvent.ACTION_MOVE:
11767                    if (clickable) {
11768                        drawableHotspotChanged(x, y);
11769                    }
11770
11771                    // Be lenient about moving outside of buttons
11772                    if (!pointInView(x, y, mTouchSlop)) {
11773                        // Outside button
11774                        // Remove any future long press/tap checks
11775                        removeTapCallback();
11776                        removeLongPressCallback();
11777                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
11778                            setPressed(false);
11779                        }
11780                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11781                    }
11782                    break;
11783            }
11784
11785            return true;
11786        }
11787
11788        return false;
11789    }
11790
11791    /**
11792     * @hide
11793     */
11794    public boolean isInScrollingContainer() {
11795        ViewParent p = getParent();
11796        while (p != null && p instanceof ViewGroup) {
11797            if (((ViewGroup) p).shouldDelayChildPressedState()) {
11798                return true;
11799            }
11800            p = p.getParent();
11801        }
11802        return false;
11803    }
11804
11805    /**
11806     * Remove the longpress detection timer.
11807     */
11808    private void removeLongPressCallback() {
11809        if (mPendingCheckForLongPress != null) {
11810            removeCallbacks(mPendingCheckForLongPress);
11811        }
11812    }
11813
11814    /**
11815     * Remove the pending click action
11816     */
11817    private void removePerformClickCallback() {
11818        if (mPerformClick != null) {
11819            removeCallbacks(mPerformClick);
11820        }
11821    }
11822
11823    /**
11824     * Remove the prepress detection timer.
11825     */
11826    private void removeUnsetPressCallback() {
11827        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
11828            setPressed(false);
11829            removeCallbacks(mUnsetPressedState);
11830        }
11831    }
11832
11833    /**
11834     * Remove the tap detection timer.
11835     */
11836    private void removeTapCallback() {
11837        if (mPendingCheckForTap != null) {
11838            mPrivateFlags &= ~PFLAG_PREPRESSED;
11839            removeCallbacks(mPendingCheckForTap);
11840        }
11841    }
11842
11843    /**
11844     * Cancels a pending long press.  Your subclass can use this if you
11845     * want the context menu to come up if the user presses and holds
11846     * at the same place, but you don't want it to come up if they press
11847     * and then move around enough to cause scrolling.
11848     */
11849    public void cancelLongPress() {
11850        removeLongPressCallback();
11851
11852        /*
11853         * The prepressed state handled by the tap callback is a display
11854         * construct, but the tap callback will post a long press callback
11855         * less its own timeout. Remove it here.
11856         */
11857        removeTapCallback();
11858    }
11859
11860    /**
11861     * Remove the pending callback for sending a
11862     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
11863     */
11864    private void removeSendViewScrolledAccessibilityEventCallback() {
11865        if (mSendViewScrolledAccessibilityEvent != null) {
11866            removeCallbacks(mSendViewScrolledAccessibilityEvent);
11867            mSendViewScrolledAccessibilityEvent.mIsPending = false;
11868        }
11869    }
11870
11871    /**
11872     * Sets the TouchDelegate for this View.
11873     */
11874    public void setTouchDelegate(TouchDelegate delegate) {
11875        mTouchDelegate = delegate;
11876    }
11877
11878    /**
11879     * Gets the TouchDelegate for this View.
11880     */
11881    public TouchDelegate getTouchDelegate() {
11882        return mTouchDelegate;
11883    }
11884
11885    /**
11886     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
11887     *
11888     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
11889     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
11890     * available. This method should only be called for touch events.
11891     *
11892     * <p class="note">This api is not intended for most applications. Buffered dispatch
11893     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
11894     * streams will not improve your input latency. Side effects include: increased latency,
11895     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
11896     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
11897     * you.</p>
11898     */
11899    public final void requestUnbufferedDispatch(MotionEvent event) {
11900        final int action = event.getAction();
11901        if (mAttachInfo == null
11902                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
11903                || !event.isTouchEvent()) {
11904            return;
11905        }
11906        mAttachInfo.mUnbufferedDispatchRequested = true;
11907    }
11908
11909    /**
11910     * Set flags controlling behavior of this view.
11911     *
11912     * @param flags Constant indicating the value which should be set
11913     * @param mask Constant indicating the bit range that should be changed
11914     */
11915    void setFlags(int flags, int mask) {
11916        final boolean accessibilityEnabled =
11917                AccessibilityManager.getInstance(mContext).isEnabled();
11918        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
11919
11920        int old = mViewFlags;
11921        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
11922
11923        int changed = mViewFlags ^ old;
11924        if (changed == 0) {
11925            return;
11926        }
11927        int privateFlags = mPrivateFlags;
11928
11929        /* Check if the FOCUSABLE bit has changed */
11930        if (((changed & FOCUSABLE_MASK) != 0) &&
11931                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
11932            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
11933                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
11934                /* Give up focus if we are no longer focusable */
11935                clearFocus();
11936            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
11937                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
11938                /*
11939                 * Tell the view system that we are now available to take focus
11940                 * if no one else already has it.
11941                 */
11942                if (mParent != null) mParent.focusableViewAvailable(this);
11943            }
11944        }
11945
11946        final int newVisibility = flags & VISIBILITY_MASK;
11947        if (newVisibility == VISIBLE) {
11948            if ((changed & VISIBILITY_MASK) != 0) {
11949                /*
11950                 * If this view is becoming visible, invalidate it in case it changed while
11951                 * it was not visible. Marking it drawn ensures that the invalidation will
11952                 * go through.
11953                 */
11954                mPrivateFlags |= PFLAG_DRAWN;
11955                invalidate(true);
11956
11957                needGlobalAttributesUpdate(true);
11958
11959                // a view becoming visible is worth notifying the parent
11960                // about in case nothing has focus.  even if this specific view
11961                // isn't focusable, it may contain something that is, so let
11962                // the root view try to give this focus if nothing else does.
11963                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
11964                    mParent.focusableViewAvailable(this);
11965                }
11966            }
11967        }
11968
11969        /* Check if the GONE bit has changed */
11970        if ((changed & GONE) != 0) {
11971            needGlobalAttributesUpdate(false);
11972            requestLayout();
11973
11974            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
11975                if (hasFocus()) clearFocus();
11976                clearAccessibilityFocus();
11977                destroyDrawingCache();
11978                if (mParent instanceof View) {
11979                    // GONE views noop invalidation, so invalidate the parent
11980                    ((View) mParent).invalidate(true);
11981                }
11982                // Mark the view drawn to ensure that it gets invalidated properly the next
11983                // time it is visible and gets invalidated
11984                mPrivateFlags |= PFLAG_DRAWN;
11985            }
11986            if (mAttachInfo != null) {
11987                mAttachInfo.mViewVisibilityChanged = true;
11988            }
11989        }
11990
11991        /* Check if the VISIBLE bit has changed */
11992        if ((changed & INVISIBLE) != 0) {
11993            needGlobalAttributesUpdate(false);
11994            /*
11995             * If this view is becoming invisible, set the DRAWN flag so that
11996             * the next invalidate() will not be skipped.
11997             */
11998            mPrivateFlags |= PFLAG_DRAWN;
11999
12000            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
12001                // root view becoming invisible shouldn't clear focus and accessibility focus
12002                if (getRootView() != this) {
12003                    if (hasFocus()) clearFocus();
12004                    clearAccessibilityFocus();
12005                }
12006            }
12007            if (mAttachInfo != null) {
12008                mAttachInfo.mViewVisibilityChanged = true;
12009            }
12010        }
12011
12012        if ((changed & VISIBILITY_MASK) != 0) {
12013            // If the view is invisible, cleanup its display list to free up resources
12014            if (newVisibility != VISIBLE && mAttachInfo != null) {
12015                cleanupDraw();
12016            }
12017
12018            if (mParent instanceof ViewGroup) {
12019                ((ViewGroup) mParent).onChildVisibilityChanged(this,
12020                        (changed & VISIBILITY_MASK), newVisibility);
12021                ((View) mParent).invalidate(true);
12022            } else if (mParent != null) {
12023                mParent.invalidateChild(this, null);
12024            }
12025
12026            if (mAttachInfo != null) {
12027                dispatchVisibilityChanged(this, newVisibility);
12028
12029                // Aggregated visibility changes are dispatched to attached views
12030                // in visible windows where the parent is currently shown/drawn
12031                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
12032                // discounting clipping or overlapping. This makes it a good place
12033                // to change animation states.
12034                if (mParent != null && getWindowVisibility() == VISIBLE &&
12035                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
12036                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
12037                }
12038                notifySubtreeAccessibilityStateChangedIfNeeded();
12039            }
12040        }
12041
12042        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
12043            destroyDrawingCache();
12044        }
12045
12046        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
12047            destroyDrawingCache();
12048            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12049            invalidateParentCaches();
12050        }
12051
12052        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
12053            destroyDrawingCache();
12054            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12055        }
12056
12057        if ((changed & DRAW_MASK) != 0) {
12058            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
12059                if (mBackground != null
12060                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
12061                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12062                } else {
12063                    mPrivateFlags |= PFLAG_SKIP_DRAW;
12064                }
12065            } else {
12066                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12067            }
12068            requestLayout();
12069            invalidate(true);
12070        }
12071
12072        if ((changed & KEEP_SCREEN_ON) != 0) {
12073            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
12074                mParent.recomputeViewAttributes(this);
12075            }
12076        }
12077
12078        if (accessibilityEnabled) {
12079            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
12080                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
12081                    || (changed & CONTEXT_CLICKABLE) != 0) {
12082                if (oldIncludeForAccessibility != includeForAccessibility()) {
12083                    notifySubtreeAccessibilityStateChangedIfNeeded();
12084                } else {
12085                    notifyViewAccessibilityStateChangedIfNeeded(
12086                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12087                }
12088            } else if ((changed & ENABLED_MASK) != 0) {
12089                notifyViewAccessibilityStateChangedIfNeeded(
12090                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12091            }
12092        }
12093    }
12094
12095    /**
12096     * Change the view's z order in the tree, so it's on top of other sibling
12097     * views. This ordering change may affect layout, if the parent container
12098     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
12099     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
12100     * method should be followed by calls to {@link #requestLayout()} and
12101     * {@link View#invalidate()} on the view's parent to force the parent to redraw
12102     * with the new child ordering.
12103     *
12104     * @see ViewGroup#bringChildToFront(View)
12105     */
12106    public void bringToFront() {
12107        if (mParent != null) {
12108            mParent.bringChildToFront(this);
12109        }
12110    }
12111
12112    /**
12113     * This is called in response to an internal scroll in this view (i.e., the
12114     * view scrolled its own contents). This is typically as a result of
12115     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
12116     * called.
12117     *
12118     * @param l Current horizontal scroll origin.
12119     * @param t Current vertical scroll origin.
12120     * @param oldl Previous horizontal scroll origin.
12121     * @param oldt Previous vertical scroll origin.
12122     */
12123    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
12124        notifySubtreeAccessibilityStateChangedIfNeeded();
12125
12126        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
12127            postSendViewScrolledAccessibilityEventCallback();
12128        }
12129
12130        mBackgroundSizeChanged = true;
12131        if (mForegroundInfo != null) {
12132            mForegroundInfo.mBoundsChanged = true;
12133        }
12134
12135        final AttachInfo ai = mAttachInfo;
12136        if (ai != null) {
12137            ai.mViewScrollChanged = true;
12138        }
12139
12140        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
12141            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
12142        }
12143    }
12144
12145    /**
12146     * Interface definition for a callback to be invoked when the scroll
12147     * X or Y positions of a view change.
12148     * <p>
12149     * <b>Note:</b> Some views handle scrolling independently from View and may
12150     * have their own separate listeners for scroll-type events. For example,
12151     * {@link android.widget.ListView ListView} allows clients to register an
12152     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
12153     * to listen for changes in list scroll position.
12154     *
12155     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
12156     */
12157    public interface OnScrollChangeListener {
12158        /**
12159         * Called when the scroll position of a view changes.
12160         *
12161         * @param v The view whose scroll position has changed.
12162         * @param scrollX Current horizontal scroll origin.
12163         * @param scrollY Current vertical scroll origin.
12164         * @param oldScrollX Previous horizontal scroll origin.
12165         * @param oldScrollY Previous vertical scroll origin.
12166         */
12167        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
12168    }
12169
12170    /**
12171     * Interface definition for a callback to be invoked when the layout bounds of a view
12172     * changes due to layout processing.
12173     */
12174    public interface OnLayoutChangeListener {
12175        /**
12176         * Called when the layout bounds of a view changes due to layout processing.
12177         *
12178         * @param v The view whose bounds have changed.
12179         * @param left The new value of the view's left property.
12180         * @param top The new value of the view's top property.
12181         * @param right The new value of the view's right property.
12182         * @param bottom The new value of the view's bottom property.
12183         * @param oldLeft The previous value of the view's left property.
12184         * @param oldTop The previous value of the view's top property.
12185         * @param oldRight The previous value of the view's right property.
12186         * @param oldBottom The previous value of the view's bottom property.
12187         */
12188        void onLayoutChange(View v, int left, int top, int right, int bottom,
12189            int oldLeft, int oldTop, int oldRight, int oldBottom);
12190    }
12191
12192    /**
12193     * This is called during layout when the size of this view has changed. If
12194     * you were just added to the view hierarchy, you're called with the old
12195     * values of 0.
12196     *
12197     * @param w Current width of this view.
12198     * @param h Current height of this view.
12199     * @param oldw Old width of this view.
12200     * @param oldh Old height of this view.
12201     */
12202    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
12203    }
12204
12205    /**
12206     * Called by draw to draw the child views. This may be overridden
12207     * by derived classes to gain control just before its children are drawn
12208     * (but after its own view has been drawn).
12209     * @param canvas the canvas on which to draw the view
12210     */
12211    protected void dispatchDraw(Canvas canvas) {
12212
12213    }
12214
12215    /**
12216     * Gets the parent of this view. Note that the parent is a
12217     * ViewParent and not necessarily a View.
12218     *
12219     * @return Parent of this view.
12220     */
12221    public final ViewParent getParent() {
12222        return mParent;
12223    }
12224
12225    /**
12226     * Set the horizontal scrolled position of your view. This will cause a call to
12227     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12228     * invalidated.
12229     * @param value the x position to scroll to
12230     */
12231    public void setScrollX(int value) {
12232        scrollTo(value, mScrollY);
12233    }
12234
12235    /**
12236     * Set the vertical scrolled position of your view. This will cause a call to
12237     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12238     * invalidated.
12239     * @param value the y position to scroll to
12240     */
12241    public void setScrollY(int value) {
12242        scrollTo(mScrollX, value);
12243    }
12244
12245    /**
12246     * Return the scrolled left position of this view. This is the left edge of
12247     * the displayed part of your view. You do not need to draw any pixels
12248     * farther left, since those are outside of the frame of your view on
12249     * screen.
12250     *
12251     * @return The left edge of the displayed part of your view, in pixels.
12252     */
12253    public final int getScrollX() {
12254        return mScrollX;
12255    }
12256
12257    /**
12258     * Return the scrolled top position of this view. This is the top edge of
12259     * the displayed part of your view. You do not need to draw any pixels above
12260     * it, since those are outside of the frame of your view on screen.
12261     *
12262     * @return The top edge of the displayed part of your view, in pixels.
12263     */
12264    public final int getScrollY() {
12265        return mScrollY;
12266    }
12267
12268    /**
12269     * Return the width of the your view.
12270     *
12271     * @return The width of your view, in pixels.
12272     */
12273    @ViewDebug.ExportedProperty(category = "layout")
12274    public final int getWidth() {
12275        return mRight - mLeft;
12276    }
12277
12278    /**
12279     * Return the height of your view.
12280     *
12281     * @return The height of your view, in pixels.
12282     */
12283    @ViewDebug.ExportedProperty(category = "layout")
12284    public final int getHeight() {
12285        return mBottom - mTop;
12286    }
12287
12288    /**
12289     * Return the visible drawing bounds of your view. Fills in the output
12290     * rectangle with the values from getScrollX(), getScrollY(),
12291     * getWidth(), and getHeight(). These bounds do not account for any
12292     * transformation properties currently set on the view, such as
12293     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
12294     *
12295     * @param outRect The (scrolled) drawing bounds of the view.
12296     */
12297    public void getDrawingRect(Rect outRect) {
12298        outRect.left = mScrollX;
12299        outRect.top = mScrollY;
12300        outRect.right = mScrollX + (mRight - mLeft);
12301        outRect.bottom = mScrollY + (mBottom - mTop);
12302    }
12303
12304    /**
12305     * Like {@link #getMeasuredWidthAndState()}, but only returns the
12306     * raw width component (that is the result is masked by
12307     * {@link #MEASURED_SIZE_MASK}).
12308     *
12309     * @return The raw measured width of this view.
12310     */
12311    public final int getMeasuredWidth() {
12312        return mMeasuredWidth & MEASURED_SIZE_MASK;
12313    }
12314
12315    /**
12316     * Return the full width measurement information for this view as computed
12317     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
12318     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
12319     * This should be used during measurement and layout calculations only. Use
12320     * {@link #getWidth()} to see how wide a view is after layout.
12321     *
12322     * @return The measured width of this view as a bit mask.
12323     */
12324    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
12325            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
12326                    name = "MEASURED_STATE_TOO_SMALL"),
12327    })
12328    public final int getMeasuredWidthAndState() {
12329        return mMeasuredWidth;
12330    }
12331
12332    /**
12333     * Like {@link #getMeasuredHeightAndState()}, but only returns the
12334     * raw height component (that is the result is masked by
12335     * {@link #MEASURED_SIZE_MASK}).
12336     *
12337     * @return The raw measured height of this view.
12338     */
12339    public final int getMeasuredHeight() {
12340        return mMeasuredHeight & MEASURED_SIZE_MASK;
12341    }
12342
12343    /**
12344     * Return the full height measurement information for this view as computed
12345     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
12346     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
12347     * This should be used during measurement and layout calculations only. Use
12348     * {@link #getHeight()} to see how wide a view is after layout.
12349     *
12350     * @return The measured height of this view as a bit mask.
12351     */
12352    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
12353            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
12354                    name = "MEASURED_STATE_TOO_SMALL"),
12355    })
12356    public final int getMeasuredHeightAndState() {
12357        return mMeasuredHeight;
12358    }
12359
12360    /**
12361     * Return only the state bits of {@link #getMeasuredWidthAndState()}
12362     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
12363     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
12364     * and the height component is at the shifted bits
12365     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
12366     */
12367    public final int getMeasuredState() {
12368        return (mMeasuredWidth&MEASURED_STATE_MASK)
12369                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
12370                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
12371    }
12372
12373    /**
12374     * The transform matrix of this view, which is calculated based on the current
12375     * rotation, scale, and pivot properties.
12376     *
12377     * @see #getRotation()
12378     * @see #getScaleX()
12379     * @see #getScaleY()
12380     * @see #getPivotX()
12381     * @see #getPivotY()
12382     * @return The current transform matrix for the view
12383     */
12384    public Matrix getMatrix() {
12385        ensureTransformationInfo();
12386        final Matrix matrix = mTransformationInfo.mMatrix;
12387        mRenderNode.getMatrix(matrix);
12388        return matrix;
12389    }
12390
12391    /**
12392     * Returns true if the transform matrix is the identity matrix.
12393     * Recomputes the matrix if necessary.
12394     *
12395     * @return True if the transform matrix is the identity matrix, false otherwise.
12396     */
12397    final boolean hasIdentityMatrix() {
12398        return mRenderNode.hasIdentityMatrix();
12399    }
12400
12401    void ensureTransformationInfo() {
12402        if (mTransformationInfo == null) {
12403            mTransformationInfo = new TransformationInfo();
12404        }
12405    }
12406
12407    /**
12408     * Utility method to retrieve the inverse of the current mMatrix property.
12409     * We cache the matrix to avoid recalculating it when transform properties
12410     * have not changed.
12411     *
12412     * @return The inverse of the current matrix of this view.
12413     * @hide
12414     */
12415    public final Matrix getInverseMatrix() {
12416        ensureTransformationInfo();
12417        if (mTransformationInfo.mInverseMatrix == null) {
12418            mTransformationInfo.mInverseMatrix = new Matrix();
12419        }
12420        final Matrix matrix = mTransformationInfo.mInverseMatrix;
12421        mRenderNode.getInverseMatrix(matrix);
12422        return matrix;
12423    }
12424
12425    /**
12426     * Gets the distance along the Z axis from the camera to this view.
12427     *
12428     * @see #setCameraDistance(float)
12429     *
12430     * @return The distance along the Z axis.
12431     */
12432    public float getCameraDistance() {
12433        final float dpi = mResources.getDisplayMetrics().densityDpi;
12434        return -(mRenderNode.getCameraDistance() * dpi);
12435    }
12436
12437    /**
12438     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
12439     * views are drawn) from the camera to this view. The camera's distance
12440     * affects 3D transformations, for instance rotations around the X and Y
12441     * axis. If the rotationX or rotationY properties are changed and this view is
12442     * large (more than half the size of the screen), it is recommended to always
12443     * use a camera distance that's greater than the height (X axis rotation) or
12444     * the width (Y axis rotation) of this view.</p>
12445     *
12446     * <p>The distance of the camera from the view plane can have an affect on the
12447     * perspective distortion of the view when it is rotated around the x or y axis.
12448     * For example, a large distance will result in a large viewing angle, and there
12449     * will not be much perspective distortion of the view as it rotates. A short
12450     * distance may cause much more perspective distortion upon rotation, and can
12451     * also result in some drawing artifacts if the rotated view ends up partially
12452     * behind the camera (which is why the recommendation is to use a distance at
12453     * least as far as the size of the view, if the view is to be rotated.)</p>
12454     *
12455     * <p>The distance is expressed in "depth pixels." The default distance depends
12456     * on the screen density. For instance, on a medium density display, the
12457     * default distance is 1280. On a high density display, the default distance
12458     * is 1920.</p>
12459     *
12460     * <p>If you want to specify a distance that leads to visually consistent
12461     * results across various densities, use the following formula:</p>
12462     * <pre>
12463     * float scale = context.getResources().getDisplayMetrics().density;
12464     * view.setCameraDistance(distance * scale);
12465     * </pre>
12466     *
12467     * <p>The density scale factor of a high density display is 1.5,
12468     * and 1920 = 1280 * 1.5.</p>
12469     *
12470     * @param distance The distance in "depth pixels", if negative the opposite
12471     *        value is used
12472     *
12473     * @see #setRotationX(float)
12474     * @see #setRotationY(float)
12475     */
12476    public void setCameraDistance(float distance) {
12477        final float dpi = mResources.getDisplayMetrics().densityDpi;
12478
12479        invalidateViewProperty(true, false);
12480        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
12481        invalidateViewProperty(false, false);
12482
12483        invalidateParentIfNeededAndWasQuickRejected();
12484    }
12485
12486    /**
12487     * The degrees that the view is rotated around the pivot point.
12488     *
12489     * @see #setRotation(float)
12490     * @see #getPivotX()
12491     * @see #getPivotY()
12492     *
12493     * @return The degrees of rotation.
12494     */
12495    @ViewDebug.ExportedProperty(category = "drawing")
12496    public float getRotation() {
12497        return mRenderNode.getRotation();
12498    }
12499
12500    /**
12501     * Sets the degrees that the view is rotated around the pivot point. Increasing values
12502     * result in clockwise rotation.
12503     *
12504     * @param rotation The degrees of rotation.
12505     *
12506     * @see #getRotation()
12507     * @see #getPivotX()
12508     * @see #getPivotY()
12509     * @see #setRotationX(float)
12510     * @see #setRotationY(float)
12511     *
12512     * @attr ref android.R.styleable#View_rotation
12513     */
12514    public void setRotation(float rotation) {
12515        if (rotation != getRotation()) {
12516            // Double-invalidation is necessary to capture view's old and new areas
12517            invalidateViewProperty(true, false);
12518            mRenderNode.setRotation(rotation);
12519            invalidateViewProperty(false, true);
12520
12521            invalidateParentIfNeededAndWasQuickRejected();
12522            notifySubtreeAccessibilityStateChangedIfNeeded();
12523        }
12524    }
12525
12526    /**
12527     * The degrees that the view is rotated around the vertical axis through the pivot point.
12528     *
12529     * @see #getPivotX()
12530     * @see #getPivotY()
12531     * @see #setRotationY(float)
12532     *
12533     * @return The degrees of Y rotation.
12534     */
12535    @ViewDebug.ExportedProperty(category = "drawing")
12536    public float getRotationY() {
12537        return mRenderNode.getRotationY();
12538    }
12539
12540    /**
12541     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
12542     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
12543     * down the y axis.
12544     *
12545     * When rotating large views, it is recommended to adjust the camera distance
12546     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12547     *
12548     * @param rotationY The degrees of Y rotation.
12549     *
12550     * @see #getRotationY()
12551     * @see #getPivotX()
12552     * @see #getPivotY()
12553     * @see #setRotation(float)
12554     * @see #setRotationX(float)
12555     * @see #setCameraDistance(float)
12556     *
12557     * @attr ref android.R.styleable#View_rotationY
12558     */
12559    public void setRotationY(float rotationY) {
12560        if (rotationY != getRotationY()) {
12561            invalidateViewProperty(true, false);
12562            mRenderNode.setRotationY(rotationY);
12563            invalidateViewProperty(false, true);
12564
12565            invalidateParentIfNeededAndWasQuickRejected();
12566            notifySubtreeAccessibilityStateChangedIfNeeded();
12567        }
12568    }
12569
12570    /**
12571     * The degrees that the view is rotated around the horizontal axis through the pivot point.
12572     *
12573     * @see #getPivotX()
12574     * @see #getPivotY()
12575     * @see #setRotationX(float)
12576     *
12577     * @return The degrees of X rotation.
12578     */
12579    @ViewDebug.ExportedProperty(category = "drawing")
12580    public float getRotationX() {
12581        return mRenderNode.getRotationX();
12582    }
12583
12584    /**
12585     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
12586     * Increasing values result in clockwise rotation from the viewpoint of looking down the
12587     * x axis.
12588     *
12589     * When rotating large views, it is recommended to adjust the camera distance
12590     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12591     *
12592     * @param rotationX The degrees of X rotation.
12593     *
12594     * @see #getRotationX()
12595     * @see #getPivotX()
12596     * @see #getPivotY()
12597     * @see #setRotation(float)
12598     * @see #setRotationY(float)
12599     * @see #setCameraDistance(float)
12600     *
12601     * @attr ref android.R.styleable#View_rotationX
12602     */
12603    public void setRotationX(float rotationX) {
12604        if (rotationX != getRotationX()) {
12605            invalidateViewProperty(true, false);
12606            mRenderNode.setRotationX(rotationX);
12607            invalidateViewProperty(false, true);
12608
12609            invalidateParentIfNeededAndWasQuickRejected();
12610            notifySubtreeAccessibilityStateChangedIfNeeded();
12611        }
12612    }
12613
12614    /**
12615     * The amount that the view is scaled in x around the pivot point, as a proportion of
12616     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
12617     *
12618     * <p>By default, this is 1.0f.
12619     *
12620     * @see #getPivotX()
12621     * @see #getPivotY()
12622     * @return The scaling factor.
12623     */
12624    @ViewDebug.ExportedProperty(category = "drawing")
12625    public float getScaleX() {
12626        return mRenderNode.getScaleX();
12627    }
12628
12629    /**
12630     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
12631     * the view's unscaled width. A value of 1 means that no scaling is applied.
12632     *
12633     * @param scaleX The scaling factor.
12634     * @see #getPivotX()
12635     * @see #getPivotY()
12636     *
12637     * @attr ref android.R.styleable#View_scaleX
12638     */
12639    public void setScaleX(float scaleX) {
12640        if (scaleX != getScaleX()) {
12641            invalidateViewProperty(true, false);
12642            mRenderNode.setScaleX(scaleX);
12643            invalidateViewProperty(false, true);
12644
12645            invalidateParentIfNeededAndWasQuickRejected();
12646            notifySubtreeAccessibilityStateChangedIfNeeded();
12647        }
12648    }
12649
12650    /**
12651     * The amount that the view is scaled in y around the pivot point, as a proportion of
12652     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
12653     *
12654     * <p>By default, this is 1.0f.
12655     *
12656     * @see #getPivotX()
12657     * @see #getPivotY()
12658     * @return The scaling factor.
12659     */
12660    @ViewDebug.ExportedProperty(category = "drawing")
12661    public float getScaleY() {
12662        return mRenderNode.getScaleY();
12663    }
12664
12665    /**
12666     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
12667     * the view's unscaled width. A value of 1 means that no scaling is applied.
12668     *
12669     * @param scaleY The scaling factor.
12670     * @see #getPivotX()
12671     * @see #getPivotY()
12672     *
12673     * @attr ref android.R.styleable#View_scaleY
12674     */
12675    public void setScaleY(float scaleY) {
12676        if (scaleY != getScaleY()) {
12677            invalidateViewProperty(true, false);
12678            mRenderNode.setScaleY(scaleY);
12679            invalidateViewProperty(false, true);
12680
12681            invalidateParentIfNeededAndWasQuickRejected();
12682            notifySubtreeAccessibilityStateChangedIfNeeded();
12683        }
12684    }
12685
12686    /**
12687     * The x location of the point around which the view is {@link #setRotation(float) rotated}
12688     * and {@link #setScaleX(float) scaled}.
12689     *
12690     * @see #getRotation()
12691     * @see #getScaleX()
12692     * @see #getScaleY()
12693     * @see #getPivotY()
12694     * @return The x location of the pivot point.
12695     *
12696     * @attr ref android.R.styleable#View_transformPivotX
12697     */
12698    @ViewDebug.ExportedProperty(category = "drawing")
12699    public float getPivotX() {
12700        return mRenderNode.getPivotX();
12701    }
12702
12703    /**
12704     * Sets the x location of the point around which the view is
12705     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
12706     * By default, the pivot point is centered on the object.
12707     * Setting this property disables this behavior and causes the view to use only the
12708     * explicitly set pivotX and pivotY values.
12709     *
12710     * @param pivotX The x location of the pivot point.
12711     * @see #getRotation()
12712     * @see #getScaleX()
12713     * @see #getScaleY()
12714     * @see #getPivotY()
12715     *
12716     * @attr ref android.R.styleable#View_transformPivotX
12717     */
12718    public void setPivotX(float pivotX) {
12719        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
12720            invalidateViewProperty(true, false);
12721            mRenderNode.setPivotX(pivotX);
12722            invalidateViewProperty(false, true);
12723
12724            invalidateParentIfNeededAndWasQuickRejected();
12725        }
12726    }
12727
12728    /**
12729     * The y location of the point around which the view is {@link #setRotation(float) rotated}
12730     * and {@link #setScaleY(float) scaled}.
12731     *
12732     * @see #getRotation()
12733     * @see #getScaleX()
12734     * @see #getScaleY()
12735     * @see #getPivotY()
12736     * @return The y location of the pivot point.
12737     *
12738     * @attr ref android.R.styleable#View_transformPivotY
12739     */
12740    @ViewDebug.ExportedProperty(category = "drawing")
12741    public float getPivotY() {
12742        return mRenderNode.getPivotY();
12743    }
12744
12745    /**
12746     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
12747     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
12748     * Setting this property disables this behavior and causes the view to use only the
12749     * explicitly set pivotX and pivotY values.
12750     *
12751     * @param pivotY The y location of the pivot point.
12752     * @see #getRotation()
12753     * @see #getScaleX()
12754     * @see #getScaleY()
12755     * @see #getPivotY()
12756     *
12757     * @attr ref android.R.styleable#View_transformPivotY
12758     */
12759    public void setPivotY(float pivotY) {
12760        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
12761            invalidateViewProperty(true, false);
12762            mRenderNode.setPivotY(pivotY);
12763            invalidateViewProperty(false, true);
12764
12765            invalidateParentIfNeededAndWasQuickRejected();
12766        }
12767    }
12768
12769    /**
12770     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
12771     * completely transparent and 1 means the view is completely opaque.
12772     *
12773     * <p>By default this is 1.0f.
12774     * @return The opacity of the view.
12775     */
12776    @ViewDebug.ExportedProperty(category = "drawing")
12777    public float getAlpha() {
12778        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
12779    }
12780
12781    /**
12782     * Sets the behavior for overlapping rendering for this view (see {@link
12783     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
12784     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
12785     * providing the value which is then used internally. That is, when {@link
12786     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
12787     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
12788     * instead.
12789     *
12790     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
12791     * instead of that returned by {@link #hasOverlappingRendering()}.
12792     *
12793     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
12794     */
12795    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
12796        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
12797        if (hasOverlappingRendering) {
12798            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12799        } else {
12800            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12801        }
12802    }
12803
12804    /**
12805     * Returns the value for overlapping rendering that is used internally. This is either
12806     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
12807     * the return value of {@link #hasOverlappingRendering()}, otherwise.
12808     *
12809     * @return The value for overlapping rendering being used internally.
12810     */
12811    public final boolean getHasOverlappingRendering() {
12812        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
12813                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
12814                hasOverlappingRendering();
12815    }
12816
12817    /**
12818     * Returns whether this View has content which overlaps.
12819     *
12820     * <p>This function, intended to be overridden by specific View types, is an optimization when
12821     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
12822     * an offscreen buffer and then composited into place, which can be expensive. If the view has
12823     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
12824     * directly. An example of overlapping rendering is a TextView with a background image, such as
12825     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
12826     * ImageView with only the foreground image. The default implementation returns true; subclasses
12827     * should override if they have cases which can be optimized.</p>
12828     *
12829     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
12830     * necessitates that a View return true if it uses the methods internally without passing the
12831     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
12832     *
12833     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
12834     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
12835     *
12836     * @return true if the content in this view might overlap, false otherwise.
12837     */
12838    @ViewDebug.ExportedProperty(category = "drawing")
12839    public boolean hasOverlappingRendering() {
12840        return true;
12841    }
12842
12843    /**
12844     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
12845     * completely transparent and 1 means the view is completely opaque.
12846     *
12847     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
12848     * can have significant performance implications, especially for large views. It is best to use
12849     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
12850     *
12851     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
12852     * strongly recommended for performance reasons to either override
12853     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
12854     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
12855     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
12856     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
12857     * of rendering cost, even for simple or small views. Starting with
12858     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
12859     * applied to the view at the rendering level.</p>
12860     *
12861     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
12862     * responsible for applying the opacity itself.</p>
12863     *
12864     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
12865     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
12866     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
12867     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
12868     *
12869     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
12870     * value will clip a View to its bounds, unless the View returns <code>false</code> from
12871     * {@link #hasOverlappingRendering}.</p>
12872     *
12873     * @param alpha The opacity of the view.
12874     *
12875     * @see #hasOverlappingRendering()
12876     * @see #setLayerType(int, android.graphics.Paint)
12877     *
12878     * @attr ref android.R.styleable#View_alpha
12879     */
12880    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
12881        ensureTransformationInfo();
12882        if (mTransformationInfo.mAlpha != alpha) {
12883            // Report visibility changes, which can affect children, to accessibility
12884            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
12885                notifySubtreeAccessibilityStateChangedIfNeeded();
12886            }
12887            mTransformationInfo.mAlpha = alpha;
12888            if (onSetAlpha((int) (alpha * 255))) {
12889                mPrivateFlags |= PFLAG_ALPHA_SET;
12890                // subclass is handling alpha - don't optimize rendering cache invalidation
12891                invalidateParentCaches();
12892                invalidate(true);
12893            } else {
12894                mPrivateFlags &= ~PFLAG_ALPHA_SET;
12895                invalidateViewProperty(true, false);
12896                mRenderNode.setAlpha(getFinalAlpha());
12897            }
12898        }
12899    }
12900
12901    /**
12902     * Faster version of setAlpha() which performs the same steps except there are
12903     * no calls to invalidate(). The caller of this function should perform proper invalidation
12904     * on the parent and this object. The return value indicates whether the subclass handles
12905     * alpha (the return value for onSetAlpha()).
12906     *
12907     * @param alpha The new value for the alpha property
12908     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
12909     *         the new value for the alpha property is different from the old value
12910     */
12911    boolean setAlphaNoInvalidation(float alpha) {
12912        ensureTransformationInfo();
12913        if (mTransformationInfo.mAlpha != alpha) {
12914            mTransformationInfo.mAlpha = alpha;
12915            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
12916            if (subclassHandlesAlpha) {
12917                mPrivateFlags |= PFLAG_ALPHA_SET;
12918                return true;
12919            } else {
12920                mPrivateFlags &= ~PFLAG_ALPHA_SET;
12921                mRenderNode.setAlpha(getFinalAlpha());
12922            }
12923        }
12924        return false;
12925    }
12926
12927    /**
12928     * This property is hidden and intended only for use by the Fade transition, which
12929     * animates it to produce a visual translucency that does not side-effect (or get
12930     * affected by) the real alpha property. This value is composited with the other
12931     * alpha value (and the AlphaAnimation value, when that is present) to produce
12932     * a final visual translucency result, which is what is passed into the DisplayList.
12933     *
12934     * @hide
12935     */
12936    public void setTransitionAlpha(float alpha) {
12937        ensureTransformationInfo();
12938        if (mTransformationInfo.mTransitionAlpha != alpha) {
12939            mTransformationInfo.mTransitionAlpha = alpha;
12940            mPrivateFlags &= ~PFLAG_ALPHA_SET;
12941            invalidateViewProperty(true, false);
12942            mRenderNode.setAlpha(getFinalAlpha());
12943        }
12944    }
12945
12946    /**
12947     * Calculates the visual alpha of this view, which is a combination of the actual
12948     * alpha value and the transitionAlpha value (if set).
12949     */
12950    private float getFinalAlpha() {
12951        if (mTransformationInfo != null) {
12952            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
12953        }
12954        return 1;
12955    }
12956
12957    /**
12958     * This property is hidden and intended only for use by the Fade transition, which
12959     * animates it to produce a visual translucency that does not side-effect (or get
12960     * affected by) the real alpha property. This value is composited with the other
12961     * alpha value (and the AlphaAnimation value, when that is present) to produce
12962     * a final visual translucency result, which is what is passed into the DisplayList.
12963     *
12964     * @hide
12965     */
12966    @ViewDebug.ExportedProperty(category = "drawing")
12967    public float getTransitionAlpha() {
12968        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
12969    }
12970
12971    /**
12972     * Top position of this view relative to its parent.
12973     *
12974     * @return The top of this view, in pixels.
12975     */
12976    @ViewDebug.CapturedViewProperty
12977    public final int getTop() {
12978        return mTop;
12979    }
12980
12981    /**
12982     * Sets the top position of this view relative to its parent. This method is meant to be called
12983     * by the layout system and should not generally be called otherwise, because the property
12984     * may be changed at any time by the layout.
12985     *
12986     * @param top The top of this view, in pixels.
12987     */
12988    public final void setTop(int top) {
12989        if (top != mTop) {
12990            final boolean matrixIsIdentity = hasIdentityMatrix();
12991            if (matrixIsIdentity) {
12992                if (mAttachInfo != null) {
12993                    int minTop;
12994                    int yLoc;
12995                    if (top < mTop) {
12996                        minTop = top;
12997                        yLoc = top - mTop;
12998                    } else {
12999                        minTop = mTop;
13000                        yLoc = 0;
13001                    }
13002                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
13003                }
13004            } else {
13005                // Double-invalidation is necessary to capture view's old and new areas
13006                invalidate(true);
13007            }
13008
13009            int width = mRight - mLeft;
13010            int oldHeight = mBottom - mTop;
13011
13012            mTop = top;
13013            mRenderNode.setTop(mTop);
13014
13015            sizeChange(width, mBottom - mTop, width, oldHeight);
13016
13017            if (!matrixIsIdentity) {
13018                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13019                invalidate(true);
13020            }
13021            mBackgroundSizeChanged = true;
13022            if (mForegroundInfo != null) {
13023                mForegroundInfo.mBoundsChanged = true;
13024            }
13025            invalidateParentIfNeeded();
13026            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13027                // View was rejected last time it was drawn by its parent; this may have changed
13028                invalidateParentIfNeeded();
13029            }
13030        }
13031    }
13032
13033    /**
13034     * Bottom position of this view relative to its parent.
13035     *
13036     * @return The bottom of this view, in pixels.
13037     */
13038    @ViewDebug.CapturedViewProperty
13039    public final int getBottom() {
13040        return mBottom;
13041    }
13042
13043    /**
13044     * True if this view has changed since the last time being drawn.
13045     *
13046     * @return The dirty state of this view.
13047     */
13048    public boolean isDirty() {
13049        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
13050    }
13051
13052    /**
13053     * Sets the bottom position of this view relative to its parent. This method is meant to be
13054     * called by the layout system and should not generally be called otherwise, because the
13055     * property may be changed at any time by the layout.
13056     *
13057     * @param bottom The bottom of this view, in pixels.
13058     */
13059    public final void setBottom(int bottom) {
13060        if (bottom != mBottom) {
13061            final boolean matrixIsIdentity = hasIdentityMatrix();
13062            if (matrixIsIdentity) {
13063                if (mAttachInfo != null) {
13064                    int maxBottom;
13065                    if (bottom < mBottom) {
13066                        maxBottom = mBottom;
13067                    } else {
13068                        maxBottom = bottom;
13069                    }
13070                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
13071                }
13072            } else {
13073                // Double-invalidation is necessary to capture view's old and new areas
13074                invalidate(true);
13075            }
13076
13077            int width = mRight - mLeft;
13078            int oldHeight = mBottom - mTop;
13079
13080            mBottom = bottom;
13081            mRenderNode.setBottom(mBottom);
13082
13083            sizeChange(width, mBottom - mTop, width, oldHeight);
13084
13085            if (!matrixIsIdentity) {
13086                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13087                invalidate(true);
13088            }
13089            mBackgroundSizeChanged = true;
13090            if (mForegroundInfo != null) {
13091                mForegroundInfo.mBoundsChanged = true;
13092            }
13093            invalidateParentIfNeeded();
13094            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13095                // View was rejected last time it was drawn by its parent; this may have changed
13096                invalidateParentIfNeeded();
13097            }
13098        }
13099    }
13100
13101    /**
13102     * Left position of this view relative to its parent.
13103     *
13104     * @return The left edge of this view, in pixels.
13105     */
13106    @ViewDebug.CapturedViewProperty
13107    public final int getLeft() {
13108        return mLeft;
13109    }
13110
13111    /**
13112     * Sets the left position of this view relative to its parent. This method is meant to be called
13113     * by the layout system and should not generally be called otherwise, because the property
13114     * may be changed at any time by the layout.
13115     *
13116     * @param left The left of this view, in pixels.
13117     */
13118    public final void setLeft(int left) {
13119        if (left != mLeft) {
13120            final boolean matrixIsIdentity = hasIdentityMatrix();
13121            if (matrixIsIdentity) {
13122                if (mAttachInfo != null) {
13123                    int minLeft;
13124                    int xLoc;
13125                    if (left < mLeft) {
13126                        minLeft = left;
13127                        xLoc = left - mLeft;
13128                    } else {
13129                        minLeft = mLeft;
13130                        xLoc = 0;
13131                    }
13132                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
13133                }
13134            } else {
13135                // Double-invalidation is necessary to capture view's old and new areas
13136                invalidate(true);
13137            }
13138
13139            int oldWidth = mRight - mLeft;
13140            int height = mBottom - mTop;
13141
13142            mLeft = left;
13143            mRenderNode.setLeft(left);
13144
13145            sizeChange(mRight - mLeft, height, oldWidth, height);
13146
13147            if (!matrixIsIdentity) {
13148                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13149                invalidate(true);
13150            }
13151            mBackgroundSizeChanged = true;
13152            if (mForegroundInfo != null) {
13153                mForegroundInfo.mBoundsChanged = true;
13154            }
13155            invalidateParentIfNeeded();
13156            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13157                // View was rejected last time it was drawn by its parent; this may have changed
13158                invalidateParentIfNeeded();
13159            }
13160        }
13161    }
13162
13163    /**
13164     * Right position of this view relative to its parent.
13165     *
13166     * @return The right edge of this view, in pixels.
13167     */
13168    @ViewDebug.CapturedViewProperty
13169    public final int getRight() {
13170        return mRight;
13171    }
13172
13173    /**
13174     * Sets the right position of this view relative to its parent. This method is meant to be called
13175     * by the layout system and should not generally be called otherwise, because the property
13176     * may be changed at any time by the layout.
13177     *
13178     * @param right The right of this view, in pixels.
13179     */
13180    public final void setRight(int right) {
13181        if (right != mRight) {
13182            final boolean matrixIsIdentity = hasIdentityMatrix();
13183            if (matrixIsIdentity) {
13184                if (mAttachInfo != null) {
13185                    int maxRight;
13186                    if (right < mRight) {
13187                        maxRight = mRight;
13188                    } else {
13189                        maxRight = right;
13190                    }
13191                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
13192                }
13193            } else {
13194                // Double-invalidation is necessary to capture view's old and new areas
13195                invalidate(true);
13196            }
13197
13198            int oldWidth = mRight - mLeft;
13199            int height = mBottom - mTop;
13200
13201            mRight = right;
13202            mRenderNode.setRight(mRight);
13203
13204            sizeChange(mRight - mLeft, height, oldWidth, height);
13205
13206            if (!matrixIsIdentity) {
13207                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13208                invalidate(true);
13209            }
13210            mBackgroundSizeChanged = true;
13211            if (mForegroundInfo != null) {
13212                mForegroundInfo.mBoundsChanged = true;
13213            }
13214            invalidateParentIfNeeded();
13215            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13216                // View was rejected last time it was drawn by its parent; this may have changed
13217                invalidateParentIfNeeded();
13218            }
13219        }
13220    }
13221
13222    /**
13223     * The visual x position of this view, in pixels. This is equivalent to the
13224     * {@link #setTranslationX(float) translationX} property plus the current
13225     * {@link #getLeft() left} property.
13226     *
13227     * @return The visual x position of this view, in pixels.
13228     */
13229    @ViewDebug.ExportedProperty(category = "drawing")
13230    public float getX() {
13231        return mLeft + getTranslationX();
13232    }
13233
13234    /**
13235     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
13236     * {@link #setTranslationX(float) translationX} property to be the difference between
13237     * the x value passed in and the current {@link #getLeft() left} property.
13238     *
13239     * @param x The visual x position of this view, in pixels.
13240     */
13241    public void setX(float x) {
13242        setTranslationX(x - mLeft);
13243    }
13244
13245    /**
13246     * The visual y position of this view, in pixels. This is equivalent to the
13247     * {@link #setTranslationY(float) translationY} property plus the current
13248     * {@link #getTop() top} property.
13249     *
13250     * @return The visual y position of this view, in pixels.
13251     */
13252    @ViewDebug.ExportedProperty(category = "drawing")
13253    public float getY() {
13254        return mTop + getTranslationY();
13255    }
13256
13257    /**
13258     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
13259     * {@link #setTranslationY(float) translationY} property to be the difference between
13260     * the y value passed in and the current {@link #getTop() top} property.
13261     *
13262     * @param y The visual y position of this view, in pixels.
13263     */
13264    public void setY(float y) {
13265        setTranslationY(y - mTop);
13266    }
13267
13268    /**
13269     * The visual z position of this view, in pixels. This is equivalent to the
13270     * {@link #setTranslationZ(float) translationZ} property plus the current
13271     * {@link #getElevation() elevation} property.
13272     *
13273     * @return The visual z position of this view, in pixels.
13274     */
13275    @ViewDebug.ExportedProperty(category = "drawing")
13276    public float getZ() {
13277        return getElevation() + getTranslationZ();
13278    }
13279
13280    /**
13281     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
13282     * {@link #setTranslationZ(float) translationZ} property to be the difference between
13283     * the x value passed in and the current {@link #getElevation() elevation} property.
13284     *
13285     * @param z The visual z position of this view, in pixels.
13286     */
13287    public void setZ(float z) {
13288        setTranslationZ(z - getElevation());
13289    }
13290
13291    /**
13292     * The base elevation of this view relative to its parent, in pixels.
13293     *
13294     * @return The base depth position of the view, in pixels.
13295     */
13296    @ViewDebug.ExportedProperty(category = "drawing")
13297    public float getElevation() {
13298        return mRenderNode.getElevation();
13299    }
13300
13301    /**
13302     * Sets the base elevation of this view, in pixels.
13303     *
13304     * @attr ref android.R.styleable#View_elevation
13305     */
13306    public void setElevation(float elevation) {
13307        if (elevation != getElevation()) {
13308            invalidateViewProperty(true, false);
13309            mRenderNode.setElevation(elevation);
13310            invalidateViewProperty(false, true);
13311
13312            invalidateParentIfNeededAndWasQuickRejected();
13313        }
13314    }
13315
13316    /**
13317     * The horizontal location of this view relative to its {@link #getLeft() left} position.
13318     * This position is post-layout, in addition to wherever the object's
13319     * layout placed it.
13320     *
13321     * @return The horizontal position of this view relative to its left position, in pixels.
13322     */
13323    @ViewDebug.ExportedProperty(category = "drawing")
13324    public float getTranslationX() {
13325        return mRenderNode.getTranslationX();
13326    }
13327
13328    /**
13329     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
13330     * This effectively positions the object post-layout, in addition to wherever the object's
13331     * layout placed it.
13332     *
13333     * @param translationX The horizontal position of this view relative to its left position,
13334     * in pixels.
13335     *
13336     * @attr ref android.R.styleable#View_translationX
13337     */
13338    public void setTranslationX(float translationX) {
13339        if (translationX != getTranslationX()) {
13340            invalidateViewProperty(true, false);
13341            mRenderNode.setTranslationX(translationX);
13342            invalidateViewProperty(false, true);
13343
13344            invalidateParentIfNeededAndWasQuickRejected();
13345            notifySubtreeAccessibilityStateChangedIfNeeded();
13346        }
13347    }
13348
13349    /**
13350     * The vertical location of this view relative to its {@link #getTop() top} position.
13351     * This position is post-layout, in addition to wherever the object's
13352     * layout placed it.
13353     *
13354     * @return The vertical position of this view relative to its top position,
13355     * in pixels.
13356     */
13357    @ViewDebug.ExportedProperty(category = "drawing")
13358    public float getTranslationY() {
13359        return mRenderNode.getTranslationY();
13360    }
13361
13362    /**
13363     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
13364     * This effectively positions the object post-layout, in addition to wherever the object's
13365     * layout placed it.
13366     *
13367     * @param translationY The vertical position of this view relative to its top position,
13368     * in pixels.
13369     *
13370     * @attr ref android.R.styleable#View_translationY
13371     */
13372    public void setTranslationY(float translationY) {
13373        if (translationY != getTranslationY()) {
13374            invalidateViewProperty(true, false);
13375            mRenderNode.setTranslationY(translationY);
13376            invalidateViewProperty(false, true);
13377
13378            invalidateParentIfNeededAndWasQuickRejected();
13379            notifySubtreeAccessibilityStateChangedIfNeeded();
13380        }
13381    }
13382
13383    /**
13384     * The depth location of this view relative to its {@link #getElevation() elevation}.
13385     *
13386     * @return The depth of this view relative to its elevation.
13387     */
13388    @ViewDebug.ExportedProperty(category = "drawing")
13389    public float getTranslationZ() {
13390        return mRenderNode.getTranslationZ();
13391    }
13392
13393    /**
13394     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
13395     *
13396     * @attr ref android.R.styleable#View_translationZ
13397     */
13398    public void setTranslationZ(float translationZ) {
13399        if (translationZ != getTranslationZ()) {
13400            invalidateViewProperty(true, false);
13401            mRenderNode.setTranslationZ(translationZ);
13402            invalidateViewProperty(false, true);
13403
13404            invalidateParentIfNeededAndWasQuickRejected();
13405        }
13406    }
13407
13408    /** @hide */
13409    public void setAnimationMatrix(Matrix matrix) {
13410        invalidateViewProperty(true, false);
13411        mRenderNode.setAnimationMatrix(matrix);
13412        invalidateViewProperty(false, true);
13413
13414        invalidateParentIfNeededAndWasQuickRejected();
13415    }
13416
13417    /**
13418     * Returns the current StateListAnimator if exists.
13419     *
13420     * @return StateListAnimator or null if it does not exists
13421     * @see    #setStateListAnimator(android.animation.StateListAnimator)
13422     */
13423    public StateListAnimator getStateListAnimator() {
13424        return mStateListAnimator;
13425    }
13426
13427    /**
13428     * Attaches the provided StateListAnimator to this View.
13429     * <p>
13430     * Any previously attached StateListAnimator will be detached.
13431     *
13432     * @param stateListAnimator The StateListAnimator to update the view
13433     * @see {@link android.animation.StateListAnimator}
13434     */
13435    public void setStateListAnimator(StateListAnimator stateListAnimator) {
13436        if (mStateListAnimator == stateListAnimator) {
13437            return;
13438        }
13439        if (mStateListAnimator != null) {
13440            mStateListAnimator.setTarget(null);
13441        }
13442        mStateListAnimator = stateListAnimator;
13443        if (stateListAnimator != null) {
13444            stateListAnimator.setTarget(this);
13445            if (isAttachedToWindow()) {
13446                stateListAnimator.setState(getDrawableState());
13447            }
13448        }
13449    }
13450
13451    /**
13452     * Returns whether the Outline should be used to clip the contents of the View.
13453     * <p>
13454     * Note that this flag will only be respected if the View's Outline returns true from
13455     * {@link Outline#canClip()}.
13456     *
13457     * @see #setOutlineProvider(ViewOutlineProvider)
13458     * @see #setClipToOutline(boolean)
13459     */
13460    public final boolean getClipToOutline() {
13461        return mRenderNode.getClipToOutline();
13462    }
13463
13464    /**
13465     * Sets whether the View's Outline should be used to clip the contents of the View.
13466     * <p>
13467     * Only a single non-rectangular clip can be applied on a View at any time.
13468     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
13469     * circular reveal} animation take priority over Outline clipping, and
13470     * child Outline clipping takes priority over Outline clipping done by a
13471     * parent.
13472     * <p>
13473     * Note that this flag will only be respected if the View's Outline returns true from
13474     * {@link Outline#canClip()}.
13475     *
13476     * @see #setOutlineProvider(ViewOutlineProvider)
13477     * @see #getClipToOutline()
13478     */
13479    public void setClipToOutline(boolean clipToOutline) {
13480        damageInParent();
13481        if (getClipToOutline() != clipToOutline) {
13482            mRenderNode.setClipToOutline(clipToOutline);
13483        }
13484    }
13485
13486    // correspond to the enum values of View_outlineProvider
13487    private static final int PROVIDER_BACKGROUND = 0;
13488    private static final int PROVIDER_NONE = 1;
13489    private static final int PROVIDER_BOUNDS = 2;
13490    private static final int PROVIDER_PADDED_BOUNDS = 3;
13491    private void setOutlineProviderFromAttribute(int providerInt) {
13492        switch (providerInt) {
13493            case PROVIDER_BACKGROUND:
13494                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
13495                break;
13496            case PROVIDER_NONE:
13497                setOutlineProvider(null);
13498                break;
13499            case PROVIDER_BOUNDS:
13500                setOutlineProvider(ViewOutlineProvider.BOUNDS);
13501                break;
13502            case PROVIDER_PADDED_BOUNDS:
13503                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
13504                break;
13505        }
13506    }
13507
13508    /**
13509     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
13510     * the shape of the shadow it casts, and enables outline clipping.
13511     * <p>
13512     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
13513     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
13514     * outline provider with this method allows this behavior to be overridden.
13515     * <p>
13516     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
13517     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
13518     * <p>
13519     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
13520     *
13521     * @see #setClipToOutline(boolean)
13522     * @see #getClipToOutline()
13523     * @see #getOutlineProvider()
13524     */
13525    public void setOutlineProvider(ViewOutlineProvider provider) {
13526        mOutlineProvider = provider;
13527        invalidateOutline();
13528    }
13529
13530    /**
13531     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
13532     * that defines the shape of the shadow it casts, and enables outline clipping.
13533     *
13534     * @see #setOutlineProvider(ViewOutlineProvider)
13535     */
13536    public ViewOutlineProvider getOutlineProvider() {
13537        return mOutlineProvider;
13538    }
13539
13540    /**
13541     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
13542     *
13543     * @see #setOutlineProvider(ViewOutlineProvider)
13544     */
13545    public void invalidateOutline() {
13546        rebuildOutline();
13547
13548        notifySubtreeAccessibilityStateChangedIfNeeded();
13549        invalidateViewProperty(false, false);
13550    }
13551
13552    /**
13553     * Internal version of {@link #invalidateOutline()} which invalidates the
13554     * outline without invalidating the view itself. This is intended to be called from
13555     * within methods in the View class itself which are the result of the view being
13556     * invalidated already. For example, when we are drawing the background of a View,
13557     * we invalidate the outline in case it changed in the meantime, but we do not
13558     * need to invalidate the view because we're already drawing the background as part
13559     * of drawing the view in response to an earlier invalidation of the view.
13560     */
13561    private void rebuildOutline() {
13562        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
13563        if (mAttachInfo == null) return;
13564
13565        if (mOutlineProvider == null) {
13566            // no provider, remove outline
13567            mRenderNode.setOutline(null);
13568        } else {
13569            final Outline outline = mAttachInfo.mTmpOutline;
13570            outline.setEmpty();
13571            outline.setAlpha(1.0f);
13572
13573            mOutlineProvider.getOutline(this, outline);
13574            mRenderNode.setOutline(outline);
13575        }
13576    }
13577
13578    /**
13579     * HierarchyViewer only
13580     *
13581     * @hide
13582     */
13583    @ViewDebug.ExportedProperty(category = "drawing")
13584    public boolean hasShadow() {
13585        return mRenderNode.hasShadow();
13586    }
13587
13588
13589    /** @hide */
13590    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
13591        mRenderNode.setRevealClip(shouldClip, x, y, radius);
13592        invalidateViewProperty(false, false);
13593    }
13594
13595    /**
13596     * Hit rectangle in parent's coordinates
13597     *
13598     * @param outRect The hit rectangle of the view.
13599     */
13600    public void getHitRect(Rect outRect) {
13601        if (hasIdentityMatrix() || mAttachInfo == null) {
13602            outRect.set(mLeft, mTop, mRight, mBottom);
13603        } else {
13604            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
13605            tmpRect.set(0, 0, getWidth(), getHeight());
13606            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
13607            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
13608                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
13609        }
13610    }
13611
13612    /**
13613     * Determines whether the given point, in local coordinates is inside the view.
13614     */
13615    /*package*/ final boolean pointInView(float localX, float localY) {
13616        return pointInView(localX, localY, 0);
13617    }
13618
13619    /**
13620     * Utility method to determine whether the given point, in local coordinates,
13621     * is inside the view, where the area of the view is expanded by the slop factor.
13622     * This method is called while processing touch-move events to determine if the event
13623     * is still within the view.
13624     *
13625     * @hide
13626     */
13627    public boolean pointInView(float localX, float localY, float slop) {
13628        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
13629                localY < ((mBottom - mTop) + slop);
13630    }
13631
13632    /**
13633     * When a view has focus and the user navigates away from it, the next view is searched for
13634     * starting from the rectangle filled in by this method.
13635     *
13636     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
13637     * of the view.  However, if your view maintains some idea of internal selection,
13638     * such as a cursor, or a selected row or column, you should override this method and
13639     * fill in a more specific rectangle.
13640     *
13641     * @param r The rectangle to fill in, in this view's coordinates.
13642     */
13643    public void getFocusedRect(Rect r) {
13644        getDrawingRect(r);
13645    }
13646
13647    /**
13648     * If some part of this view is not clipped by any of its parents, then
13649     * return that area in r in global (root) coordinates. To convert r to local
13650     * coordinates (without taking possible View rotations into account), offset
13651     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
13652     * If the view is completely clipped or translated out, return false.
13653     *
13654     * @param r If true is returned, r holds the global coordinates of the
13655     *        visible portion of this view.
13656     * @param globalOffset If true is returned, globalOffset holds the dx,dy
13657     *        between this view and its root. globalOffet may be null.
13658     * @return true if r is non-empty (i.e. part of the view is visible at the
13659     *         root level.
13660     */
13661    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
13662        int width = mRight - mLeft;
13663        int height = mBottom - mTop;
13664        if (width > 0 && height > 0) {
13665            r.set(0, 0, width, height);
13666            if (globalOffset != null) {
13667                globalOffset.set(-mScrollX, -mScrollY);
13668            }
13669            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
13670        }
13671        return false;
13672    }
13673
13674    public final boolean getGlobalVisibleRect(Rect r) {
13675        return getGlobalVisibleRect(r, null);
13676    }
13677
13678    public final boolean getLocalVisibleRect(Rect r) {
13679        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
13680        if (getGlobalVisibleRect(r, offset)) {
13681            r.offset(-offset.x, -offset.y); // make r local
13682            return true;
13683        }
13684        return false;
13685    }
13686
13687    /**
13688     * Offset this view's vertical location by the specified number of pixels.
13689     *
13690     * @param offset the number of pixels to offset the view by
13691     */
13692    public void offsetTopAndBottom(int offset) {
13693        if (offset != 0) {
13694            final boolean matrixIsIdentity = hasIdentityMatrix();
13695            if (matrixIsIdentity) {
13696                if (isHardwareAccelerated()) {
13697                    invalidateViewProperty(false, false);
13698                } else {
13699                    final ViewParent p = mParent;
13700                    if (p != null && mAttachInfo != null) {
13701                        final Rect r = mAttachInfo.mTmpInvalRect;
13702                        int minTop;
13703                        int maxBottom;
13704                        int yLoc;
13705                        if (offset < 0) {
13706                            minTop = mTop + offset;
13707                            maxBottom = mBottom;
13708                            yLoc = offset;
13709                        } else {
13710                            minTop = mTop;
13711                            maxBottom = mBottom + offset;
13712                            yLoc = 0;
13713                        }
13714                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
13715                        p.invalidateChild(this, r);
13716                    }
13717                }
13718            } else {
13719                invalidateViewProperty(false, false);
13720            }
13721
13722            mTop += offset;
13723            mBottom += offset;
13724            mRenderNode.offsetTopAndBottom(offset);
13725            if (isHardwareAccelerated()) {
13726                invalidateViewProperty(false, false);
13727                invalidateParentIfNeededAndWasQuickRejected();
13728            } else {
13729                if (!matrixIsIdentity) {
13730                    invalidateViewProperty(false, true);
13731                }
13732                invalidateParentIfNeeded();
13733            }
13734            notifySubtreeAccessibilityStateChangedIfNeeded();
13735        }
13736    }
13737
13738    /**
13739     * Offset this view's horizontal location by the specified amount of pixels.
13740     *
13741     * @param offset the number of pixels to offset the view by
13742     */
13743    public void offsetLeftAndRight(int offset) {
13744        if (offset != 0) {
13745            final boolean matrixIsIdentity = hasIdentityMatrix();
13746            if (matrixIsIdentity) {
13747                if (isHardwareAccelerated()) {
13748                    invalidateViewProperty(false, false);
13749                } else {
13750                    final ViewParent p = mParent;
13751                    if (p != null && mAttachInfo != null) {
13752                        final Rect r = mAttachInfo.mTmpInvalRect;
13753                        int minLeft;
13754                        int maxRight;
13755                        if (offset < 0) {
13756                            minLeft = mLeft + offset;
13757                            maxRight = mRight;
13758                        } else {
13759                            minLeft = mLeft;
13760                            maxRight = mRight + offset;
13761                        }
13762                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
13763                        p.invalidateChild(this, r);
13764                    }
13765                }
13766            } else {
13767                invalidateViewProperty(false, false);
13768            }
13769
13770            mLeft += offset;
13771            mRight += offset;
13772            mRenderNode.offsetLeftAndRight(offset);
13773            if (isHardwareAccelerated()) {
13774                invalidateViewProperty(false, false);
13775                invalidateParentIfNeededAndWasQuickRejected();
13776            } else {
13777                if (!matrixIsIdentity) {
13778                    invalidateViewProperty(false, true);
13779                }
13780                invalidateParentIfNeeded();
13781            }
13782            notifySubtreeAccessibilityStateChangedIfNeeded();
13783        }
13784    }
13785
13786    /**
13787     * Get the LayoutParams associated with this view. All views should have
13788     * layout parameters. These supply parameters to the <i>parent</i> of this
13789     * view specifying how it should be arranged. There are many subclasses of
13790     * ViewGroup.LayoutParams, and these correspond to the different subclasses
13791     * of ViewGroup that are responsible for arranging their children.
13792     *
13793     * This method may return null if this View is not attached to a parent
13794     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
13795     * was not invoked successfully. When a View is attached to a parent
13796     * ViewGroup, this method must not return null.
13797     *
13798     * @return The LayoutParams associated with this view, or null if no
13799     *         parameters have been set yet
13800     */
13801    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
13802    public ViewGroup.LayoutParams getLayoutParams() {
13803        return mLayoutParams;
13804    }
13805
13806    /**
13807     * Set the layout parameters associated with this view. These supply
13808     * parameters to the <i>parent</i> of this view specifying how it should be
13809     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
13810     * correspond to the different subclasses of ViewGroup that are responsible
13811     * for arranging their children.
13812     *
13813     * @param params The layout parameters for this view, cannot be null
13814     */
13815    public void setLayoutParams(ViewGroup.LayoutParams params) {
13816        if (params == null) {
13817            throw new NullPointerException("Layout parameters cannot be null");
13818        }
13819        mLayoutParams = params;
13820        resolveLayoutParams();
13821        if (mParent instanceof ViewGroup) {
13822            ((ViewGroup) mParent).onSetLayoutParams(this, params);
13823        }
13824        requestLayout();
13825    }
13826
13827    /**
13828     * Resolve the layout parameters depending on the resolved layout direction
13829     *
13830     * @hide
13831     */
13832    public void resolveLayoutParams() {
13833        if (mLayoutParams != null) {
13834            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
13835        }
13836    }
13837
13838    /**
13839     * Set the scrolled position of your view. This will cause a call to
13840     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13841     * invalidated.
13842     * @param x the x position to scroll to
13843     * @param y the y position to scroll to
13844     */
13845    public void scrollTo(int x, int y) {
13846        if (mScrollX != x || mScrollY != y) {
13847            int oldX = mScrollX;
13848            int oldY = mScrollY;
13849            mScrollX = x;
13850            mScrollY = y;
13851            invalidateParentCaches();
13852            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
13853            if (!awakenScrollBars()) {
13854                postInvalidateOnAnimation();
13855            }
13856        }
13857    }
13858
13859    /**
13860     * Move the scrolled position of your view. This will cause a call to
13861     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13862     * invalidated.
13863     * @param x the amount of pixels to scroll by horizontally
13864     * @param y the amount of pixels to scroll by vertically
13865     */
13866    public void scrollBy(int x, int y) {
13867        scrollTo(mScrollX + x, mScrollY + y);
13868    }
13869
13870    /**
13871     * <p>Trigger the scrollbars to draw. When invoked this method starts an
13872     * animation to fade the scrollbars out after a default delay. If a subclass
13873     * provides animated scrolling, the start delay should equal the duration
13874     * of the scrolling animation.</p>
13875     *
13876     * <p>The animation starts only if at least one of the scrollbars is
13877     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
13878     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13879     * this method returns true, and false otherwise. If the animation is
13880     * started, this method calls {@link #invalidate()}; in that case the
13881     * caller should not call {@link #invalidate()}.</p>
13882     *
13883     * <p>This method should be invoked every time a subclass directly updates
13884     * the scroll parameters.</p>
13885     *
13886     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
13887     * and {@link #scrollTo(int, int)}.</p>
13888     *
13889     * @return true if the animation is played, false otherwise
13890     *
13891     * @see #awakenScrollBars(int)
13892     * @see #scrollBy(int, int)
13893     * @see #scrollTo(int, int)
13894     * @see #isHorizontalScrollBarEnabled()
13895     * @see #isVerticalScrollBarEnabled()
13896     * @see #setHorizontalScrollBarEnabled(boolean)
13897     * @see #setVerticalScrollBarEnabled(boolean)
13898     */
13899    protected boolean awakenScrollBars() {
13900        return mScrollCache != null &&
13901                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
13902    }
13903
13904    /**
13905     * Trigger the scrollbars to draw.
13906     * This method differs from awakenScrollBars() only in its default duration.
13907     * initialAwakenScrollBars() will show the scroll bars for longer than
13908     * usual to give the user more of a chance to notice them.
13909     *
13910     * @return true if the animation is played, false otherwise.
13911     */
13912    private boolean initialAwakenScrollBars() {
13913        return mScrollCache != null &&
13914                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
13915    }
13916
13917    /**
13918     * <p>
13919     * Trigger the scrollbars to draw. When invoked this method starts an
13920     * animation to fade the scrollbars out after a fixed delay. If a subclass
13921     * provides animated scrolling, the start delay should equal the duration of
13922     * the scrolling animation.
13923     * </p>
13924     *
13925     * <p>
13926     * The animation starts only if at least one of the scrollbars is enabled,
13927     * as specified by {@link #isHorizontalScrollBarEnabled()} and
13928     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13929     * this method returns true, and false otherwise. If the animation is
13930     * started, this method calls {@link #invalidate()}; in that case the caller
13931     * should not call {@link #invalidate()}.
13932     * </p>
13933     *
13934     * <p>
13935     * This method should be invoked every time a subclass directly updates the
13936     * scroll parameters.
13937     * </p>
13938     *
13939     * @param startDelay the delay, in milliseconds, after which the animation
13940     *        should start; when the delay is 0, the animation starts
13941     *        immediately
13942     * @return true if the animation is played, false otherwise
13943     *
13944     * @see #scrollBy(int, int)
13945     * @see #scrollTo(int, int)
13946     * @see #isHorizontalScrollBarEnabled()
13947     * @see #isVerticalScrollBarEnabled()
13948     * @see #setHorizontalScrollBarEnabled(boolean)
13949     * @see #setVerticalScrollBarEnabled(boolean)
13950     */
13951    protected boolean awakenScrollBars(int startDelay) {
13952        return awakenScrollBars(startDelay, true);
13953    }
13954
13955    /**
13956     * <p>
13957     * Trigger the scrollbars to draw. When invoked this method starts an
13958     * animation to fade the scrollbars out after a fixed delay. If a subclass
13959     * provides animated scrolling, the start delay should equal the duration of
13960     * the scrolling animation.
13961     * </p>
13962     *
13963     * <p>
13964     * The animation starts only if at least one of the scrollbars is enabled,
13965     * as specified by {@link #isHorizontalScrollBarEnabled()} and
13966     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13967     * this method returns true, and false otherwise. If the animation is
13968     * started, this method calls {@link #invalidate()} if the invalidate parameter
13969     * is set to true; in that case the caller
13970     * should not call {@link #invalidate()}.
13971     * </p>
13972     *
13973     * <p>
13974     * This method should be invoked every time a subclass directly updates the
13975     * scroll parameters.
13976     * </p>
13977     *
13978     * @param startDelay the delay, in milliseconds, after which the animation
13979     *        should start; when the delay is 0, the animation starts
13980     *        immediately
13981     *
13982     * @param invalidate Whether this method should call invalidate
13983     *
13984     * @return true if the animation is played, false otherwise
13985     *
13986     * @see #scrollBy(int, int)
13987     * @see #scrollTo(int, int)
13988     * @see #isHorizontalScrollBarEnabled()
13989     * @see #isVerticalScrollBarEnabled()
13990     * @see #setHorizontalScrollBarEnabled(boolean)
13991     * @see #setVerticalScrollBarEnabled(boolean)
13992     */
13993    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
13994        final ScrollabilityCache scrollCache = mScrollCache;
13995
13996        if (scrollCache == null || !scrollCache.fadeScrollBars) {
13997            return false;
13998        }
13999
14000        if (scrollCache.scrollBar == null) {
14001            scrollCache.scrollBar = new ScrollBarDrawable();
14002            scrollCache.scrollBar.setState(getDrawableState());
14003            scrollCache.scrollBar.setCallback(this);
14004        }
14005
14006        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
14007
14008            if (invalidate) {
14009                // Invalidate to show the scrollbars
14010                postInvalidateOnAnimation();
14011            }
14012
14013            if (scrollCache.state == ScrollabilityCache.OFF) {
14014                // FIXME: this is copied from WindowManagerService.
14015                // We should get this value from the system when it
14016                // is possible to do so.
14017                final int KEY_REPEAT_FIRST_DELAY = 750;
14018                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
14019            }
14020
14021            // Tell mScrollCache when we should start fading. This may
14022            // extend the fade start time if one was already scheduled
14023            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
14024            scrollCache.fadeStartTime = fadeStartTime;
14025            scrollCache.state = ScrollabilityCache.ON;
14026
14027            // Schedule our fader to run, unscheduling any old ones first
14028            if (mAttachInfo != null) {
14029                mAttachInfo.mHandler.removeCallbacks(scrollCache);
14030                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
14031            }
14032
14033            return true;
14034        }
14035
14036        return false;
14037    }
14038
14039    /**
14040     * Do not invalidate views which are not visible and which are not running an animation. They
14041     * will not get drawn and they should not set dirty flags as if they will be drawn
14042     */
14043    private boolean skipInvalidate() {
14044        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
14045                (!(mParent instanceof ViewGroup) ||
14046                        !((ViewGroup) mParent).isViewTransitioning(this));
14047    }
14048
14049    /**
14050     * Mark the area defined by dirty as needing to be drawn. If the view is
14051     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14052     * point in the future.
14053     * <p>
14054     * This must be called from a UI thread. To call from a non-UI thread, call
14055     * {@link #postInvalidate()}.
14056     * <p>
14057     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
14058     * {@code dirty}.
14059     *
14060     * @param dirty the rectangle representing the bounds of the dirty region
14061     */
14062    public void invalidate(Rect dirty) {
14063        final int scrollX = mScrollX;
14064        final int scrollY = mScrollY;
14065        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
14066                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
14067    }
14068
14069    /**
14070     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
14071     * coordinates of the dirty rect are relative to the view. If the view is
14072     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14073     * point in the future.
14074     * <p>
14075     * This must be called from a UI thread. To call from a non-UI thread, call
14076     * {@link #postInvalidate()}.
14077     *
14078     * @param l the left position of the dirty region
14079     * @param t the top position of the dirty region
14080     * @param r the right position of the dirty region
14081     * @param b the bottom position of the dirty region
14082     */
14083    public void invalidate(int l, int t, int r, int b) {
14084        final int scrollX = mScrollX;
14085        final int scrollY = mScrollY;
14086        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
14087    }
14088
14089    /**
14090     * Invalidate the whole view. If the view is visible,
14091     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
14092     * the future.
14093     * <p>
14094     * This must be called from a UI thread. To call from a non-UI thread, call
14095     * {@link #postInvalidate()}.
14096     */
14097    public void invalidate() {
14098        invalidate(true);
14099    }
14100
14101    /**
14102     * This is where the invalidate() work actually happens. A full invalidate()
14103     * causes the drawing cache to be invalidated, but this function can be
14104     * called with invalidateCache set to false to skip that invalidation step
14105     * for cases that do not need it (for example, a component that remains at
14106     * the same dimensions with the same content).
14107     *
14108     * @param invalidateCache Whether the drawing cache for this view should be
14109     *            invalidated as well. This is usually true for a full
14110     *            invalidate, but may be set to false if the View's contents or
14111     *            dimensions have not changed.
14112     */
14113    void invalidate(boolean invalidateCache) {
14114        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
14115    }
14116
14117    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
14118            boolean fullInvalidate) {
14119        if (mGhostView != null) {
14120            mGhostView.invalidate(true);
14121            return;
14122        }
14123
14124        if (skipInvalidate()) {
14125            return;
14126        }
14127
14128        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
14129                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
14130                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
14131                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
14132            if (fullInvalidate) {
14133                mLastIsOpaque = isOpaque();
14134                mPrivateFlags &= ~PFLAG_DRAWN;
14135            }
14136
14137            mPrivateFlags |= PFLAG_DIRTY;
14138
14139            if (invalidateCache) {
14140                mPrivateFlags |= PFLAG_INVALIDATED;
14141                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14142            }
14143
14144            // Propagate the damage rectangle to the parent view.
14145            final AttachInfo ai = mAttachInfo;
14146            final ViewParent p = mParent;
14147            if (p != null && ai != null && l < r && t < b) {
14148                final Rect damage = ai.mTmpInvalRect;
14149                damage.set(l, t, r, b);
14150                p.invalidateChild(this, damage);
14151            }
14152
14153            // Damage the entire projection receiver, if necessary.
14154            if (mBackground != null && mBackground.isProjected()) {
14155                final View receiver = getProjectionReceiver();
14156                if (receiver != null) {
14157                    receiver.damageInParent();
14158                }
14159            }
14160        }
14161    }
14162
14163    /**
14164     * @return this view's projection receiver, or {@code null} if none exists
14165     */
14166    private View getProjectionReceiver() {
14167        ViewParent p = getParent();
14168        while (p != null && p instanceof View) {
14169            final View v = (View) p;
14170            if (v.isProjectionReceiver()) {
14171                return v;
14172            }
14173            p = p.getParent();
14174        }
14175
14176        return null;
14177    }
14178
14179    /**
14180     * @return whether the view is a projection receiver
14181     */
14182    private boolean isProjectionReceiver() {
14183        return mBackground != null;
14184    }
14185
14186    /**
14187     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
14188     * set any flags or handle all of the cases handled by the default invalidation methods.
14189     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
14190     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
14191     * walk up the hierarchy, transforming the dirty rect as necessary.
14192     *
14193     * The method also handles normal invalidation logic if display list properties are not
14194     * being used in this view. The invalidateParent and forceRedraw flags are used by that
14195     * backup approach, to handle these cases used in the various property-setting methods.
14196     *
14197     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
14198     * are not being used in this view
14199     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
14200     * list properties are not being used in this view
14201     */
14202    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
14203        if (!isHardwareAccelerated()
14204                || !mRenderNode.isValid()
14205                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
14206            if (invalidateParent) {
14207                invalidateParentCaches();
14208            }
14209            if (forceRedraw) {
14210                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14211            }
14212            invalidate(false);
14213        } else {
14214            damageInParent();
14215        }
14216    }
14217
14218    /**
14219     * Tells the parent view to damage this view's bounds.
14220     *
14221     * @hide
14222     */
14223    protected void damageInParent() {
14224        final AttachInfo ai = mAttachInfo;
14225        final ViewParent p = mParent;
14226        if (p != null && ai != null) {
14227            final Rect r = ai.mTmpInvalRect;
14228            r.set(0, 0, mRight - mLeft, mBottom - mTop);
14229            if (mParent instanceof ViewGroup) {
14230                ((ViewGroup) mParent).damageChild(this, r);
14231            } else {
14232                mParent.invalidateChild(this, r);
14233            }
14234        }
14235    }
14236
14237    /**
14238     * Utility method to transform a given Rect by the current matrix of this view.
14239     */
14240    void transformRect(final Rect rect) {
14241        if (!getMatrix().isIdentity()) {
14242            RectF boundingRect = mAttachInfo.mTmpTransformRect;
14243            boundingRect.set(rect);
14244            getMatrix().mapRect(boundingRect);
14245            rect.set((int) Math.floor(boundingRect.left),
14246                    (int) Math.floor(boundingRect.top),
14247                    (int) Math.ceil(boundingRect.right),
14248                    (int) Math.ceil(boundingRect.bottom));
14249        }
14250    }
14251
14252    /**
14253     * Used to indicate that the parent of this view should clear its caches. This functionality
14254     * is used to force the parent to rebuild its display list (when hardware-accelerated),
14255     * which is necessary when various parent-managed properties of the view change, such as
14256     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
14257     * clears the parent caches and does not causes an invalidate event.
14258     *
14259     * @hide
14260     */
14261    protected void invalidateParentCaches() {
14262        if (mParent instanceof View) {
14263            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
14264        }
14265    }
14266
14267    /**
14268     * Used to indicate that the parent of this view should be invalidated. This functionality
14269     * is used to force the parent to rebuild its display list (when hardware-accelerated),
14270     * which is necessary when various parent-managed properties of the view change, such as
14271     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
14272     * an invalidation event to the parent.
14273     *
14274     * @hide
14275     */
14276    protected void invalidateParentIfNeeded() {
14277        if (isHardwareAccelerated() && mParent instanceof View) {
14278            ((View) mParent).invalidate(true);
14279        }
14280    }
14281
14282    /**
14283     * @hide
14284     */
14285    protected void invalidateParentIfNeededAndWasQuickRejected() {
14286        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
14287            // View was rejected last time it was drawn by its parent; this may have changed
14288            invalidateParentIfNeeded();
14289        }
14290    }
14291
14292    /**
14293     * Indicates whether this View is opaque. An opaque View guarantees that it will
14294     * draw all the pixels overlapping its bounds using a fully opaque color.
14295     *
14296     * Subclasses of View should override this method whenever possible to indicate
14297     * whether an instance is opaque. Opaque Views are treated in a special way by
14298     * the View hierarchy, possibly allowing it to perform optimizations during
14299     * invalidate/draw passes.
14300     *
14301     * @return True if this View is guaranteed to be fully opaque, false otherwise.
14302     */
14303    @ViewDebug.ExportedProperty(category = "drawing")
14304    public boolean isOpaque() {
14305        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
14306                getFinalAlpha() >= 1.0f;
14307    }
14308
14309    /**
14310     * @hide
14311     */
14312    protected void computeOpaqueFlags() {
14313        // Opaque if:
14314        //   - Has a background
14315        //   - Background is opaque
14316        //   - Doesn't have scrollbars or scrollbars overlay
14317
14318        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
14319            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
14320        } else {
14321            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
14322        }
14323
14324        final int flags = mViewFlags;
14325        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
14326                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
14327                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
14328            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
14329        } else {
14330            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
14331        }
14332    }
14333
14334    /**
14335     * @hide
14336     */
14337    protected boolean hasOpaqueScrollbars() {
14338        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
14339    }
14340
14341    /**
14342     * @return A handler associated with the thread running the View. This
14343     * handler can be used to pump events in the UI events queue.
14344     */
14345    public Handler getHandler() {
14346        final AttachInfo attachInfo = mAttachInfo;
14347        if (attachInfo != null) {
14348            return attachInfo.mHandler;
14349        }
14350        return null;
14351    }
14352
14353    /**
14354     * Returns the queue of runnable for this view.
14355     *
14356     * @return the queue of runnables for this view
14357     */
14358    private HandlerActionQueue getRunQueue() {
14359        if (mRunQueue == null) {
14360            mRunQueue = new HandlerActionQueue();
14361        }
14362        return mRunQueue;
14363    }
14364
14365    /**
14366     * Gets the view root associated with the View.
14367     * @return The view root, or null if none.
14368     * @hide
14369     */
14370    public ViewRootImpl getViewRootImpl() {
14371        if (mAttachInfo != null) {
14372            return mAttachInfo.mViewRootImpl;
14373        }
14374        return null;
14375    }
14376
14377    /**
14378     * @hide
14379     */
14380    public ThreadedRenderer getThreadedRenderer() {
14381        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
14382    }
14383
14384    /**
14385     * <p>Causes the Runnable to be added to the message queue.
14386     * The runnable will be run on the user interface thread.</p>
14387     *
14388     * @param action The Runnable that will be executed.
14389     *
14390     * @return Returns true if the Runnable was successfully placed in to the
14391     *         message queue.  Returns false on failure, usually because the
14392     *         looper processing the message queue is exiting.
14393     *
14394     * @see #postDelayed
14395     * @see #removeCallbacks
14396     */
14397    public boolean post(Runnable action) {
14398        final AttachInfo attachInfo = mAttachInfo;
14399        if (attachInfo != null) {
14400            return attachInfo.mHandler.post(action);
14401        }
14402
14403        // Postpone the runnable until we know on which thread it needs to run.
14404        // Assume that the runnable will be successfully placed after attach.
14405        getRunQueue().post(action);
14406        return true;
14407    }
14408
14409    /**
14410     * <p>Causes the Runnable to be added to the message queue, to be run
14411     * after the specified amount of time elapses.
14412     * The runnable will be run on the user interface thread.</p>
14413     *
14414     * @param action The Runnable that will be executed.
14415     * @param delayMillis The delay (in milliseconds) until the Runnable
14416     *        will be executed.
14417     *
14418     * @return true if the Runnable was successfully placed in to the
14419     *         message queue.  Returns false on failure, usually because the
14420     *         looper processing the message queue is exiting.  Note that a
14421     *         result of true does not mean the Runnable will be processed --
14422     *         if the looper is quit before the delivery time of the message
14423     *         occurs then the message will be dropped.
14424     *
14425     * @see #post
14426     * @see #removeCallbacks
14427     */
14428    public boolean postDelayed(Runnable action, long delayMillis) {
14429        final AttachInfo attachInfo = mAttachInfo;
14430        if (attachInfo != null) {
14431            return attachInfo.mHandler.postDelayed(action, delayMillis);
14432        }
14433
14434        // Postpone the runnable until we know on which thread it needs to run.
14435        // Assume that the runnable will be successfully placed after attach.
14436        getRunQueue().postDelayed(action, delayMillis);
14437        return true;
14438    }
14439
14440    /**
14441     * <p>Causes the Runnable to execute on the next animation time step.
14442     * The runnable will be run on the user interface thread.</p>
14443     *
14444     * @param action The Runnable that will be executed.
14445     *
14446     * @see #postOnAnimationDelayed
14447     * @see #removeCallbacks
14448     */
14449    public void postOnAnimation(Runnable action) {
14450        final AttachInfo attachInfo = mAttachInfo;
14451        if (attachInfo != null) {
14452            attachInfo.mViewRootImpl.mChoreographer.postCallback(
14453                    Choreographer.CALLBACK_ANIMATION, action, null);
14454        } else {
14455            // Postpone the runnable until we know
14456            // on which thread it needs to run.
14457            getRunQueue().post(action);
14458        }
14459    }
14460
14461    /**
14462     * <p>Causes the Runnable to execute on the next animation time step,
14463     * after the specified amount of time elapses.
14464     * The runnable will be run on the user interface thread.</p>
14465     *
14466     * @param action The Runnable that will be executed.
14467     * @param delayMillis The delay (in milliseconds) until the Runnable
14468     *        will be executed.
14469     *
14470     * @see #postOnAnimation
14471     * @see #removeCallbacks
14472     */
14473    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
14474        final AttachInfo attachInfo = mAttachInfo;
14475        if (attachInfo != null) {
14476            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
14477                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
14478        } else {
14479            // Postpone the runnable until we know
14480            // on which thread it needs to run.
14481            getRunQueue().postDelayed(action, delayMillis);
14482        }
14483    }
14484
14485    /**
14486     * <p>Removes the specified Runnable from the message queue.</p>
14487     *
14488     * @param action The Runnable to remove from the message handling queue
14489     *
14490     * @return true if this view could ask the Handler to remove the Runnable,
14491     *         false otherwise. When the returned value is true, the Runnable
14492     *         may or may not have been actually removed from the message queue
14493     *         (for instance, if the Runnable was not in the queue already.)
14494     *
14495     * @see #post
14496     * @see #postDelayed
14497     * @see #postOnAnimation
14498     * @see #postOnAnimationDelayed
14499     */
14500    public boolean removeCallbacks(Runnable action) {
14501        if (action != null) {
14502            final AttachInfo attachInfo = mAttachInfo;
14503            if (attachInfo != null) {
14504                attachInfo.mHandler.removeCallbacks(action);
14505                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14506                        Choreographer.CALLBACK_ANIMATION, action, null);
14507            }
14508            getRunQueue().removeCallbacks(action);
14509        }
14510        return true;
14511    }
14512
14513    /**
14514     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
14515     * Use this to invalidate the View from a non-UI thread.</p>
14516     *
14517     * <p>This method can be invoked from outside of the UI thread
14518     * only when this View is attached to a window.</p>
14519     *
14520     * @see #invalidate()
14521     * @see #postInvalidateDelayed(long)
14522     */
14523    public void postInvalidate() {
14524        postInvalidateDelayed(0);
14525    }
14526
14527    /**
14528     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14529     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
14530     *
14531     * <p>This method can be invoked from outside of the UI thread
14532     * only when this View is attached to a window.</p>
14533     *
14534     * @param left The left coordinate of the rectangle to invalidate.
14535     * @param top The top coordinate of the rectangle to invalidate.
14536     * @param right The right coordinate of the rectangle to invalidate.
14537     * @param bottom The bottom coordinate of the rectangle to invalidate.
14538     *
14539     * @see #invalidate(int, int, int, int)
14540     * @see #invalidate(Rect)
14541     * @see #postInvalidateDelayed(long, int, int, int, int)
14542     */
14543    public void postInvalidate(int left, int top, int right, int bottom) {
14544        postInvalidateDelayed(0, left, top, right, bottom);
14545    }
14546
14547    /**
14548     * <p>Cause an invalidate to happen on a subsequent cycle through the event
14549     * loop. Waits for the specified amount of time.</p>
14550     *
14551     * <p>This method can be invoked from outside of the UI thread
14552     * only when this View is attached to a window.</p>
14553     *
14554     * @param delayMilliseconds the duration in milliseconds to delay the
14555     *         invalidation by
14556     *
14557     * @see #invalidate()
14558     * @see #postInvalidate()
14559     */
14560    public void postInvalidateDelayed(long delayMilliseconds) {
14561        // We try only with the AttachInfo because there's no point in invalidating
14562        // if we are not attached to our window
14563        final AttachInfo attachInfo = mAttachInfo;
14564        if (attachInfo != null) {
14565            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
14566        }
14567    }
14568
14569    /**
14570     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14571     * through the event loop. Waits for the specified amount of time.</p>
14572     *
14573     * <p>This method can be invoked from outside of the UI thread
14574     * only when this View is attached to a window.</p>
14575     *
14576     * @param delayMilliseconds the duration in milliseconds to delay the
14577     *         invalidation by
14578     * @param left The left coordinate of the rectangle to invalidate.
14579     * @param top The top coordinate of the rectangle to invalidate.
14580     * @param right The right coordinate of the rectangle to invalidate.
14581     * @param bottom The bottom coordinate of the rectangle to invalidate.
14582     *
14583     * @see #invalidate(int, int, int, int)
14584     * @see #invalidate(Rect)
14585     * @see #postInvalidate(int, int, int, int)
14586     */
14587    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
14588            int right, int bottom) {
14589
14590        // We try only with the AttachInfo because there's no point in invalidating
14591        // if we are not attached to our window
14592        final AttachInfo attachInfo = mAttachInfo;
14593        if (attachInfo != null) {
14594            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14595            info.target = this;
14596            info.left = left;
14597            info.top = top;
14598            info.right = right;
14599            info.bottom = bottom;
14600
14601            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
14602        }
14603    }
14604
14605    /**
14606     * <p>Cause an invalidate to happen on the next animation time step, typically the
14607     * next display frame.</p>
14608     *
14609     * <p>This method can be invoked from outside of the UI thread
14610     * only when this View is attached to a window.</p>
14611     *
14612     * @see #invalidate()
14613     */
14614    public void postInvalidateOnAnimation() {
14615        // We try only with the AttachInfo because there's no point in invalidating
14616        // if we are not attached to our window
14617        final AttachInfo attachInfo = mAttachInfo;
14618        if (attachInfo != null) {
14619            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
14620        }
14621    }
14622
14623    /**
14624     * <p>Cause an invalidate of the specified area to happen on the next animation
14625     * time step, typically the next display frame.</p>
14626     *
14627     * <p>This method can be invoked from outside of the UI thread
14628     * only when this View is attached to a window.</p>
14629     *
14630     * @param left The left coordinate of the rectangle to invalidate.
14631     * @param top The top coordinate of the rectangle to invalidate.
14632     * @param right The right coordinate of the rectangle to invalidate.
14633     * @param bottom The bottom coordinate of the rectangle to invalidate.
14634     *
14635     * @see #invalidate(int, int, int, int)
14636     * @see #invalidate(Rect)
14637     */
14638    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
14639        // We try only with the AttachInfo because there's no point in invalidating
14640        // if we are not attached to our window
14641        final AttachInfo attachInfo = mAttachInfo;
14642        if (attachInfo != null) {
14643            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14644            info.target = this;
14645            info.left = left;
14646            info.top = top;
14647            info.right = right;
14648            info.bottom = bottom;
14649
14650            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
14651        }
14652    }
14653
14654    /**
14655     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
14656     * This event is sent at most once every
14657     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
14658     */
14659    private void postSendViewScrolledAccessibilityEventCallback() {
14660        if (mSendViewScrolledAccessibilityEvent == null) {
14661            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
14662        }
14663        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
14664            mSendViewScrolledAccessibilityEvent.mIsPending = true;
14665            postDelayed(mSendViewScrolledAccessibilityEvent,
14666                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
14667        }
14668    }
14669
14670    /**
14671     * Called by a parent to request that a child update its values for mScrollX
14672     * and mScrollY if necessary. This will typically be done if the child is
14673     * animating a scroll using a {@link android.widget.Scroller Scroller}
14674     * object.
14675     */
14676    public void computeScroll() {
14677    }
14678
14679    /**
14680     * <p>Indicate whether the horizontal edges are faded when the view is
14681     * scrolled horizontally.</p>
14682     *
14683     * @return true if the horizontal edges should are faded on scroll, false
14684     *         otherwise
14685     *
14686     * @see #setHorizontalFadingEdgeEnabled(boolean)
14687     *
14688     * @attr ref android.R.styleable#View_requiresFadingEdge
14689     */
14690    public boolean isHorizontalFadingEdgeEnabled() {
14691        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
14692    }
14693
14694    /**
14695     * <p>Define whether the horizontal edges should be faded when this view
14696     * is scrolled horizontally.</p>
14697     *
14698     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
14699     *                                    be faded when the view is scrolled
14700     *                                    horizontally
14701     *
14702     * @see #isHorizontalFadingEdgeEnabled()
14703     *
14704     * @attr ref android.R.styleable#View_requiresFadingEdge
14705     */
14706    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
14707        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
14708            if (horizontalFadingEdgeEnabled) {
14709                initScrollCache();
14710            }
14711
14712            mViewFlags ^= FADING_EDGE_HORIZONTAL;
14713        }
14714    }
14715
14716    /**
14717     * <p>Indicate whether the vertical edges are faded when the view is
14718     * scrolled horizontally.</p>
14719     *
14720     * @return true if the vertical edges should are faded on scroll, false
14721     *         otherwise
14722     *
14723     * @see #setVerticalFadingEdgeEnabled(boolean)
14724     *
14725     * @attr ref android.R.styleable#View_requiresFadingEdge
14726     */
14727    public boolean isVerticalFadingEdgeEnabled() {
14728        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
14729    }
14730
14731    /**
14732     * <p>Define whether the vertical edges should be faded when this view
14733     * is scrolled vertically.</p>
14734     *
14735     * @param verticalFadingEdgeEnabled true if the vertical edges should
14736     *                                  be faded when the view is scrolled
14737     *                                  vertically
14738     *
14739     * @see #isVerticalFadingEdgeEnabled()
14740     *
14741     * @attr ref android.R.styleable#View_requiresFadingEdge
14742     */
14743    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
14744        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
14745            if (verticalFadingEdgeEnabled) {
14746                initScrollCache();
14747            }
14748
14749            mViewFlags ^= FADING_EDGE_VERTICAL;
14750        }
14751    }
14752
14753    /**
14754     * Returns the strength, or intensity, of the top faded edge. The strength is
14755     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14756     * returns 0.0 or 1.0 but no value in between.
14757     *
14758     * Subclasses should override this method to provide a smoother fade transition
14759     * when scrolling occurs.
14760     *
14761     * @return the intensity of the top fade as a float between 0.0f and 1.0f
14762     */
14763    protected float getTopFadingEdgeStrength() {
14764        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
14765    }
14766
14767    /**
14768     * Returns the strength, or intensity, of the bottom faded edge. The strength is
14769     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14770     * returns 0.0 or 1.0 but no value in between.
14771     *
14772     * Subclasses should override this method to provide a smoother fade transition
14773     * when scrolling occurs.
14774     *
14775     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
14776     */
14777    protected float getBottomFadingEdgeStrength() {
14778        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
14779                computeVerticalScrollRange() ? 1.0f : 0.0f;
14780    }
14781
14782    /**
14783     * Returns the strength, or intensity, of the left faded edge. The strength is
14784     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14785     * returns 0.0 or 1.0 but no value in between.
14786     *
14787     * Subclasses should override this method to provide a smoother fade transition
14788     * when scrolling occurs.
14789     *
14790     * @return the intensity of the left fade as a float between 0.0f and 1.0f
14791     */
14792    protected float getLeftFadingEdgeStrength() {
14793        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
14794    }
14795
14796    /**
14797     * Returns the strength, or intensity, of the right faded edge. The strength is
14798     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14799     * returns 0.0 or 1.0 but no value in between.
14800     *
14801     * Subclasses should override this method to provide a smoother fade transition
14802     * when scrolling occurs.
14803     *
14804     * @return the intensity of the right fade as a float between 0.0f and 1.0f
14805     */
14806    protected float getRightFadingEdgeStrength() {
14807        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
14808                computeHorizontalScrollRange() ? 1.0f : 0.0f;
14809    }
14810
14811    /**
14812     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
14813     * scrollbar is not drawn by default.</p>
14814     *
14815     * @return true if the horizontal scrollbar should be painted, false
14816     *         otherwise
14817     *
14818     * @see #setHorizontalScrollBarEnabled(boolean)
14819     */
14820    public boolean isHorizontalScrollBarEnabled() {
14821        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14822    }
14823
14824    /**
14825     * <p>Define whether the horizontal scrollbar should be drawn or not. The
14826     * scrollbar is not drawn by default.</p>
14827     *
14828     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
14829     *                                   be painted
14830     *
14831     * @see #isHorizontalScrollBarEnabled()
14832     */
14833    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
14834        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
14835            mViewFlags ^= SCROLLBARS_HORIZONTAL;
14836            computeOpaqueFlags();
14837            resolvePadding();
14838        }
14839    }
14840
14841    /**
14842     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
14843     * scrollbar is not drawn by default.</p>
14844     *
14845     * @return true if the vertical scrollbar should be painted, false
14846     *         otherwise
14847     *
14848     * @see #setVerticalScrollBarEnabled(boolean)
14849     */
14850    public boolean isVerticalScrollBarEnabled() {
14851        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
14852    }
14853
14854    /**
14855     * <p>Define whether the vertical scrollbar should be drawn or not. The
14856     * scrollbar is not drawn by default.</p>
14857     *
14858     * @param verticalScrollBarEnabled true if the vertical scrollbar should
14859     *                                 be painted
14860     *
14861     * @see #isVerticalScrollBarEnabled()
14862     */
14863    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
14864        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
14865            mViewFlags ^= SCROLLBARS_VERTICAL;
14866            computeOpaqueFlags();
14867            resolvePadding();
14868        }
14869    }
14870
14871    /**
14872     * @hide
14873     */
14874    protected void recomputePadding() {
14875        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14876    }
14877
14878    /**
14879     * Define whether scrollbars will fade when the view is not scrolling.
14880     *
14881     * @param fadeScrollbars whether to enable fading
14882     *
14883     * @attr ref android.R.styleable#View_fadeScrollbars
14884     */
14885    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
14886        initScrollCache();
14887        final ScrollabilityCache scrollabilityCache = mScrollCache;
14888        scrollabilityCache.fadeScrollBars = fadeScrollbars;
14889        if (fadeScrollbars) {
14890            scrollabilityCache.state = ScrollabilityCache.OFF;
14891        } else {
14892            scrollabilityCache.state = ScrollabilityCache.ON;
14893        }
14894    }
14895
14896    /**
14897     *
14898     * Returns true if scrollbars will fade when this view is not scrolling
14899     *
14900     * @return true if scrollbar fading is enabled
14901     *
14902     * @attr ref android.R.styleable#View_fadeScrollbars
14903     */
14904    public boolean isScrollbarFadingEnabled() {
14905        return mScrollCache != null && mScrollCache.fadeScrollBars;
14906    }
14907
14908    /**
14909     *
14910     * Returns the delay before scrollbars fade.
14911     *
14912     * @return the delay before scrollbars fade
14913     *
14914     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14915     */
14916    public int getScrollBarDefaultDelayBeforeFade() {
14917        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
14918                mScrollCache.scrollBarDefaultDelayBeforeFade;
14919    }
14920
14921    /**
14922     * Define the delay before scrollbars fade.
14923     *
14924     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
14925     *
14926     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14927     */
14928    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
14929        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
14930    }
14931
14932    /**
14933     *
14934     * Returns the scrollbar fade duration.
14935     *
14936     * @return the scrollbar fade duration, in milliseconds
14937     *
14938     * @attr ref android.R.styleable#View_scrollbarFadeDuration
14939     */
14940    public int getScrollBarFadeDuration() {
14941        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
14942                mScrollCache.scrollBarFadeDuration;
14943    }
14944
14945    /**
14946     * Define the scrollbar fade duration.
14947     *
14948     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
14949     *
14950     * @attr ref android.R.styleable#View_scrollbarFadeDuration
14951     */
14952    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
14953        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
14954    }
14955
14956    /**
14957     *
14958     * Returns the scrollbar size.
14959     *
14960     * @return the scrollbar size
14961     *
14962     * @attr ref android.R.styleable#View_scrollbarSize
14963     */
14964    public int getScrollBarSize() {
14965        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
14966                mScrollCache.scrollBarSize;
14967    }
14968
14969    /**
14970     * Define the scrollbar size.
14971     *
14972     * @param scrollBarSize - the scrollbar size
14973     *
14974     * @attr ref android.R.styleable#View_scrollbarSize
14975     */
14976    public void setScrollBarSize(int scrollBarSize) {
14977        getScrollCache().scrollBarSize = scrollBarSize;
14978    }
14979
14980    /**
14981     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
14982     * inset. When inset, they add to the padding of the view. And the scrollbars
14983     * can be drawn inside the padding area or on the edge of the view. For example,
14984     * if a view has a background drawable and you want to draw the scrollbars
14985     * inside the padding specified by the drawable, you can use
14986     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
14987     * appear at the edge of the view, ignoring the padding, then you can use
14988     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
14989     * @param style the style of the scrollbars. Should be one of
14990     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
14991     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
14992     * @see #SCROLLBARS_INSIDE_OVERLAY
14993     * @see #SCROLLBARS_INSIDE_INSET
14994     * @see #SCROLLBARS_OUTSIDE_OVERLAY
14995     * @see #SCROLLBARS_OUTSIDE_INSET
14996     *
14997     * @attr ref android.R.styleable#View_scrollbarStyle
14998     */
14999    public void setScrollBarStyle(@ScrollBarStyle int style) {
15000        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
15001            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
15002            computeOpaqueFlags();
15003            resolvePadding();
15004        }
15005    }
15006
15007    /**
15008     * <p>Returns the current scrollbar style.</p>
15009     * @return the current scrollbar style
15010     * @see #SCROLLBARS_INSIDE_OVERLAY
15011     * @see #SCROLLBARS_INSIDE_INSET
15012     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15013     * @see #SCROLLBARS_OUTSIDE_INSET
15014     *
15015     * @attr ref android.R.styleable#View_scrollbarStyle
15016     */
15017    @ViewDebug.ExportedProperty(mapping = {
15018            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
15019            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
15020            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
15021            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
15022    })
15023    @ScrollBarStyle
15024    public int getScrollBarStyle() {
15025        return mViewFlags & SCROLLBARS_STYLE_MASK;
15026    }
15027
15028    /**
15029     * <p>Compute the horizontal range that the horizontal scrollbar
15030     * represents.</p>
15031     *
15032     * <p>The range is expressed in arbitrary units that must be the same as the
15033     * units used by {@link #computeHorizontalScrollExtent()} and
15034     * {@link #computeHorizontalScrollOffset()}.</p>
15035     *
15036     * <p>The default range is the drawing width of this view.</p>
15037     *
15038     * @return the total horizontal range represented by the horizontal
15039     *         scrollbar
15040     *
15041     * @see #computeHorizontalScrollExtent()
15042     * @see #computeHorizontalScrollOffset()
15043     * @see android.widget.ScrollBarDrawable
15044     */
15045    protected int computeHorizontalScrollRange() {
15046        return getWidth();
15047    }
15048
15049    /**
15050     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
15051     * within the horizontal range. This value is used to compute the position
15052     * of the thumb within the scrollbar's track.</p>
15053     *
15054     * <p>The range is expressed in arbitrary units that must be the same as the
15055     * units used by {@link #computeHorizontalScrollRange()} and
15056     * {@link #computeHorizontalScrollExtent()}.</p>
15057     *
15058     * <p>The default offset is the scroll offset of this view.</p>
15059     *
15060     * @return the horizontal offset of the scrollbar's thumb
15061     *
15062     * @see #computeHorizontalScrollRange()
15063     * @see #computeHorizontalScrollExtent()
15064     * @see android.widget.ScrollBarDrawable
15065     */
15066    protected int computeHorizontalScrollOffset() {
15067        return mScrollX;
15068    }
15069
15070    /**
15071     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
15072     * within the horizontal range. This value is used to compute the length
15073     * of the thumb within the scrollbar's track.</p>
15074     *
15075     * <p>The range is expressed in arbitrary units that must be the same as the
15076     * units used by {@link #computeHorizontalScrollRange()} and
15077     * {@link #computeHorizontalScrollOffset()}.</p>
15078     *
15079     * <p>The default extent is the drawing width of this view.</p>
15080     *
15081     * @return the horizontal extent of the scrollbar's thumb
15082     *
15083     * @see #computeHorizontalScrollRange()
15084     * @see #computeHorizontalScrollOffset()
15085     * @see android.widget.ScrollBarDrawable
15086     */
15087    protected int computeHorizontalScrollExtent() {
15088        return getWidth();
15089    }
15090
15091    /**
15092     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
15093     *
15094     * <p>The range is expressed in arbitrary units that must be the same as the
15095     * units used by {@link #computeVerticalScrollExtent()} and
15096     * {@link #computeVerticalScrollOffset()}.</p>
15097     *
15098     * @return the total vertical range represented by the vertical scrollbar
15099     *
15100     * <p>The default range is the drawing height of this view.</p>
15101     *
15102     * @see #computeVerticalScrollExtent()
15103     * @see #computeVerticalScrollOffset()
15104     * @see android.widget.ScrollBarDrawable
15105     */
15106    protected int computeVerticalScrollRange() {
15107        return getHeight();
15108    }
15109
15110    /**
15111     * <p>Compute the vertical offset of the vertical scrollbar's thumb
15112     * within the horizontal range. This value is used to compute the position
15113     * of the thumb within the scrollbar's track.</p>
15114     *
15115     * <p>The range is expressed in arbitrary units that must be the same as the
15116     * units used by {@link #computeVerticalScrollRange()} and
15117     * {@link #computeVerticalScrollExtent()}.</p>
15118     *
15119     * <p>The default offset is the scroll offset of this view.</p>
15120     *
15121     * @return the vertical offset of the scrollbar's thumb
15122     *
15123     * @see #computeVerticalScrollRange()
15124     * @see #computeVerticalScrollExtent()
15125     * @see android.widget.ScrollBarDrawable
15126     */
15127    protected int computeVerticalScrollOffset() {
15128        return mScrollY;
15129    }
15130
15131    /**
15132     * <p>Compute the vertical extent of the vertical scrollbar's thumb
15133     * within the vertical range. This value is used to compute the length
15134     * of the thumb within the scrollbar's track.</p>
15135     *
15136     * <p>The range is expressed in arbitrary units that must be the same as the
15137     * units used by {@link #computeVerticalScrollRange()} and
15138     * {@link #computeVerticalScrollOffset()}.</p>
15139     *
15140     * <p>The default extent is the drawing height of this view.</p>
15141     *
15142     * @return the vertical extent of the scrollbar's thumb
15143     *
15144     * @see #computeVerticalScrollRange()
15145     * @see #computeVerticalScrollOffset()
15146     * @see android.widget.ScrollBarDrawable
15147     */
15148    protected int computeVerticalScrollExtent() {
15149        return getHeight();
15150    }
15151
15152    /**
15153     * Check if this view can be scrolled horizontally in a certain direction.
15154     *
15155     * @param direction Negative to check scrolling left, positive to check scrolling right.
15156     * @return true if this view can be scrolled in the specified direction, false otherwise.
15157     */
15158    public boolean canScrollHorizontally(int direction) {
15159        final int offset = computeHorizontalScrollOffset();
15160        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
15161        if (range == 0) return false;
15162        if (direction < 0) {
15163            return offset > 0;
15164        } else {
15165            return offset < range - 1;
15166        }
15167    }
15168
15169    /**
15170     * Check if this view can be scrolled vertically in a certain direction.
15171     *
15172     * @param direction Negative to check scrolling up, positive to check scrolling down.
15173     * @return true if this view can be scrolled in the specified direction, false otherwise.
15174     */
15175    public boolean canScrollVertically(int direction) {
15176        final int offset = computeVerticalScrollOffset();
15177        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
15178        if (range == 0) return false;
15179        if (direction < 0) {
15180            return offset > 0;
15181        } else {
15182            return offset < range - 1;
15183        }
15184    }
15185
15186    void getScrollIndicatorBounds(@NonNull Rect out) {
15187        out.left = mScrollX;
15188        out.right = mScrollX + mRight - mLeft;
15189        out.top = mScrollY;
15190        out.bottom = mScrollY + mBottom - mTop;
15191    }
15192
15193    private void onDrawScrollIndicators(Canvas c) {
15194        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
15195            // No scroll indicators enabled.
15196            return;
15197        }
15198
15199        final Drawable dr = mScrollIndicatorDrawable;
15200        if (dr == null) {
15201            // Scroll indicators aren't supported here.
15202            return;
15203        }
15204
15205        final int h = dr.getIntrinsicHeight();
15206        final int w = dr.getIntrinsicWidth();
15207        final Rect rect = mAttachInfo.mTmpInvalRect;
15208        getScrollIndicatorBounds(rect);
15209
15210        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
15211            final boolean canScrollUp = canScrollVertically(-1);
15212            if (canScrollUp) {
15213                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
15214                dr.draw(c);
15215            }
15216        }
15217
15218        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
15219            final boolean canScrollDown = canScrollVertically(1);
15220            if (canScrollDown) {
15221                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
15222                dr.draw(c);
15223            }
15224        }
15225
15226        final int leftRtl;
15227        final int rightRtl;
15228        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15229            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
15230            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
15231        } else {
15232            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
15233            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
15234        }
15235
15236        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
15237        if ((mPrivateFlags3 & leftMask) != 0) {
15238            final boolean canScrollLeft = canScrollHorizontally(-1);
15239            if (canScrollLeft) {
15240                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
15241                dr.draw(c);
15242            }
15243        }
15244
15245        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
15246        if ((mPrivateFlags3 & rightMask) != 0) {
15247            final boolean canScrollRight = canScrollHorizontally(1);
15248            if (canScrollRight) {
15249                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
15250                dr.draw(c);
15251            }
15252        }
15253    }
15254
15255    private void getHorizontalScrollBarBounds(Rect bounds) {
15256        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
15257        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
15258                && !isVerticalScrollBarHidden();
15259        final int size = getHorizontalScrollbarHeight();
15260        final int verticalScrollBarGap = drawVerticalScrollBar ?
15261                getVerticalScrollbarWidth() : 0;
15262        final int width = mRight - mLeft;
15263        final int height = mBottom - mTop;
15264        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
15265        bounds.left = mScrollX + (mPaddingLeft & inside);
15266        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
15267        bounds.bottom = bounds.top + size;
15268    }
15269
15270    private void getVerticalScrollBarBounds(Rect bounds) {
15271        if (mRoundScrollbarRenderer == null) {
15272            getStraightVerticalScrollBarBounds(bounds);
15273        } else {
15274            getRoundVerticalScrollBarBounds(bounds);
15275        }
15276    }
15277
15278    private void getRoundVerticalScrollBarBounds(Rect bounds) {
15279        final int width = mRight - mLeft;
15280        final int height = mBottom - mTop;
15281        // Do not take padding into account as we always want the scrollbars
15282        // to hug the screen for round wearable devices.
15283        bounds.left = mScrollX;
15284        bounds.top = mScrollY;
15285        bounds.right = bounds.left + width;
15286        bounds.bottom = mScrollY + height;
15287    }
15288
15289    private void getStraightVerticalScrollBarBounds(Rect bounds) {
15290        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
15291        final int size = getVerticalScrollbarWidth();
15292        int verticalScrollbarPosition = mVerticalScrollbarPosition;
15293        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
15294            verticalScrollbarPosition = isLayoutRtl() ?
15295                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
15296        }
15297        final int width = mRight - mLeft;
15298        final int height = mBottom - mTop;
15299        switch (verticalScrollbarPosition) {
15300            default:
15301            case SCROLLBAR_POSITION_RIGHT:
15302                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
15303                break;
15304            case SCROLLBAR_POSITION_LEFT:
15305                bounds.left = mScrollX + (mUserPaddingLeft & inside);
15306                break;
15307        }
15308        bounds.top = mScrollY + (mPaddingTop & inside);
15309        bounds.right = bounds.left + size;
15310        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
15311    }
15312
15313    /**
15314     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
15315     * scrollbars are painted only if they have been awakened first.</p>
15316     *
15317     * @param canvas the canvas on which to draw the scrollbars
15318     *
15319     * @see #awakenScrollBars(int)
15320     */
15321    protected final void onDrawScrollBars(Canvas canvas) {
15322        // scrollbars are drawn only when the animation is running
15323        final ScrollabilityCache cache = mScrollCache;
15324
15325        if (cache != null) {
15326
15327            int state = cache.state;
15328
15329            if (state == ScrollabilityCache.OFF) {
15330                return;
15331            }
15332
15333            boolean invalidate = false;
15334
15335            if (state == ScrollabilityCache.FADING) {
15336                // We're fading -- get our fade interpolation
15337                if (cache.interpolatorValues == null) {
15338                    cache.interpolatorValues = new float[1];
15339                }
15340
15341                float[] values = cache.interpolatorValues;
15342
15343                // Stops the animation if we're done
15344                if (cache.scrollBarInterpolator.timeToValues(values) ==
15345                        Interpolator.Result.FREEZE_END) {
15346                    cache.state = ScrollabilityCache.OFF;
15347                } else {
15348                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
15349                }
15350
15351                // This will make the scroll bars inval themselves after
15352                // drawing. We only want this when we're fading so that
15353                // we prevent excessive redraws
15354                invalidate = true;
15355            } else {
15356                // We're just on -- but we may have been fading before so
15357                // reset alpha
15358                cache.scrollBar.mutate().setAlpha(255);
15359            }
15360
15361            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
15362            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
15363                    && !isVerticalScrollBarHidden();
15364
15365            // Fork out the scroll bar drawing for round wearable devices.
15366            if (mRoundScrollbarRenderer != null) {
15367                if (drawVerticalScrollBar) {
15368                    final Rect bounds = cache.mScrollBarBounds;
15369                    getVerticalScrollBarBounds(bounds);
15370                    mRoundScrollbarRenderer.drawRoundScrollbars(
15371                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
15372                    if (invalidate) {
15373                        invalidate();
15374                    }
15375                }
15376                // Do not draw horizontal scroll bars for round wearable devices.
15377            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
15378                final ScrollBarDrawable scrollBar = cache.scrollBar;
15379
15380                if (drawHorizontalScrollBar) {
15381                    scrollBar.setParameters(computeHorizontalScrollRange(),
15382                            computeHorizontalScrollOffset(),
15383                            computeHorizontalScrollExtent(), false);
15384                    final Rect bounds = cache.mScrollBarBounds;
15385                    getHorizontalScrollBarBounds(bounds);
15386                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
15387                            bounds.right, bounds.bottom);
15388                    if (invalidate) {
15389                        invalidate(bounds);
15390                    }
15391                }
15392
15393                if (drawVerticalScrollBar) {
15394                    scrollBar.setParameters(computeVerticalScrollRange(),
15395                            computeVerticalScrollOffset(),
15396                            computeVerticalScrollExtent(), true);
15397                    final Rect bounds = cache.mScrollBarBounds;
15398                    getVerticalScrollBarBounds(bounds);
15399                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
15400                            bounds.right, bounds.bottom);
15401                    if (invalidate) {
15402                        invalidate(bounds);
15403                    }
15404                }
15405            }
15406        }
15407    }
15408
15409    /**
15410     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
15411     * FastScroller is visible.
15412     * @return whether to temporarily hide the vertical scrollbar
15413     * @hide
15414     */
15415    protected boolean isVerticalScrollBarHidden() {
15416        return false;
15417    }
15418
15419    /**
15420     * <p>Draw the horizontal scrollbar if
15421     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
15422     *
15423     * @param canvas the canvas on which to draw the scrollbar
15424     * @param scrollBar the scrollbar's drawable
15425     *
15426     * @see #isHorizontalScrollBarEnabled()
15427     * @see #computeHorizontalScrollRange()
15428     * @see #computeHorizontalScrollExtent()
15429     * @see #computeHorizontalScrollOffset()
15430     * @see android.widget.ScrollBarDrawable
15431     * @hide
15432     */
15433    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
15434            int l, int t, int r, int b) {
15435        scrollBar.setBounds(l, t, r, b);
15436        scrollBar.draw(canvas);
15437    }
15438
15439    /**
15440     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
15441     * returns true.</p>
15442     *
15443     * @param canvas the canvas on which to draw the scrollbar
15444     * @param scrollBar the scrollbar's drawable
15445     *
15446     * @see #isVerticalScrollBarEnabled()
15447     * @see #computeVerticalScrollRange()
15448     * @see #computeVerticalScrollExtent()
15449     * @see #computeVerticalScrollOffset()
15450     * @see android.widget.ScrollBarDrawable
15451     * @hide
15452     */
15453    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
15454            int l, int t, int r, int b) {
15455        scrollBar.setBounds(l, t, r, b);
15456        scrollBar.draw(canvas);
15457    }
15458
15459    /**
15460     * Implement this to do your drawing.
15461     *
15462     * @param canvas the canvas on which the background will be drawn
15463     */
15464    protected void onDraw(Canvas canvas) {
15465    }
15466
15467    /*
15468     * Caller is responsible for calling requestLayout if necessary.
15469     * (This allows addViewInLayout to not request a new layout.)
15470     */
15471    void assignParent(ViewParent parent) {
15472        if (mParent == null) {
15473            mParent = parent;
15474        } else if (parent == null) {
15475            mParent = null;
15476        } else {
15477            throw new RuntimeException("view " + this + " being added, but"
15478                    + " it already has a parent");
15479        }
15480    }
15481
15482    /**
15483     * This is called when the view is attached to a window.  At this point it
15484     * has a Surface and will start drawing.  Note that this function is
15485     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
15486     * however it may be called any time before the first onDraw -- including
15487     * before or after {@link #onMeasure(int, int)}.
15488     *
15489     * @see #onDetachedFromWindow()
15490     */
15491    @CallSuper
15492    protected void onAttachedToWindow() {
15493        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
15494            mParent.requestTransparentRegion(this);
15495        }
15496
15497        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15498
15499        jumpDrawablesToCurrentState();
15500
15501        resetSubtreeAccessibilityStateChanged();
15502
15503        // rebuild, since Outline not maintained while View is detached
15504        rebuildOutline();
15505
15506        if (isFocused()) {
15507            InputMethodManager imm = InputMethodManager.peekInstance();
15508            if (imm != null) {
15509                imm.focusIn(this);
15510            }
15511        }
15512    }
15513
15514    /**
15515     * Resolve all RTL related properties.
15516     *
15517     * @return true if resolution of RTL properties has been done
15518     *
15519     * @hide
15520     */
15521    public boolean resolveRtlPropertiesIfNeeded() {
15522        if (!needRtlPropertiesResolution()) return false;
15523
15524        // Order is important here: LayoutDirection MUST be resolved first
15525        if (!isLayoutDirectionResolved()) {
15526            resolveLayoutDirection();
15527            resolveLayoutParams();
15528        }
15529        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
15530        if (!isTextDirectionResolved()) {
15531            resolveTextDirection();
15532        }
15533        if (!isTextAlignmentResolved()) {
15534            resolveTextAlignment();
15535        }
15536        // Should resolve Drawables before Padding because we need the layout direction of the
15537        // Drawable to correctly resolve Padding.
15538        if (!areDrawablesResolved()) {
15539            resolveDrawables();
15540        }
15541        if (!isPaddingResolved()) {
15542            resolvePadding();
15543        }
15544        onRtlPropertiesChanged(getLayoutDirection());
15545        return true;
15546    }
15547
15548    /**
15549     * Reset resolution of all RTL related properties.
15550     *
15551     * @hide
15552     */
15553    public void resetRtlProperties() {
15554        resetResolvedLayoutDirection();
15555        resetResolvedTextDirection();
15556        resetResolvedTextAlignment();
15557        resetResolvedPadding();
15558        resetResolvedDrawables();
15559    }
15560
15561    /**
15562     * @see #onScreenStateChanged(int)
15563     */
15564    void dispatchScreenStateChanged(int screenState) {
15565        onScreenStateChanged(screenState);
15566    }
15567
15568    /**
15569     * This method is called whenever the state of the screen this view is
15570     * attached to changes. A state change will usually occurs when the screen
15571     * turns on or off (whether it happens automatically or the user does it
15572     * manually.)
15573     *
15574     * @param screenState The new state of the screen. Can be either
15575     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
15576     */
15577    public void onScreenStateChanged(int screenState) {
15578    }
15579
15580    /**
15581     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
15582     */
15583    private boolean hasRtlSupport() {
15584        return mContext.getApplicationInfo().hasRtlSupport();
15585    }
15586
15587    /**
15588     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
15589     * RTL not supported)
15590     */
15591    private boolean isRtlCompatibilityMode() {
15592        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
15593        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
15594    }
15595
15596    /**
15597     * @return true if RTL properties need resolution.
15598     *
15599     */
15600    private boolean needRtlPropertiesResolution() {
15601        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
15602    }
15603
15604    /**
15605     * Called when any RTL property (layout direction or text direction or text alignment) has
15606     * been changed.
15607     *
15608     * Subclasses need to override this method to take care of cached information that depends on the
15609     * resolved layout direction, or to inform child views that inherit their layout direction.
15610     *
15611     * The default implementation does nothing.
15612     *
15613     * @param layoutDirection the direction of the layout
15614     *
15615     * @see #LAYOUT_DIRECTION_LTR
15616     * @see #LAYOUT_DIRECTION_RTL
15617     */
15618    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
15619    }
15620
15621    /**
15622     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
15623     * that the parent directionality can and will be resolved before its children.
15624     *
15625     * @return true if resolution has been done, false otherwise.
15626     *
15627     * @hide
15628     */
15629    public boolean resolveLayoutDirection() {
15630        // Clear any previous layout direction resolution
15631        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15632
15633        if (hasRtlSupport()) {
15634            // Set resolved depending on layout direction
15635            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
15636                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
15637                case LAYOUT_DIRECTION_INHERIT:
15638                    // We cannot resolve yet. LTR is by default and let the resolution happen again
15639                    // later to get the correct resolved value
15640                    if (!canResolveLayoutDirection()) return false;
15641
15642                    // Parent has not yet resolved, LTR is still the default
15643                    try {
15644                        if (!mParent.isLayoutDirectionResolved()) return false;
15645
15646                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15647                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15648                        }
15649                    } catch (AbstractMethodError e) {
15650                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15651                                " does not fully implement ViewParent", e);
15652                    }
15653                    break;
15654                case LAYOUT_DIRECTION_RTL:
15655                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15656                    break;
15657                case LAYOUT_DIRECTION_LOCALE:
15658                    if((LAYOUT_DIRECTION_RTL ==
15659                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
15660                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15661                    }
15662                    break;
15663                default:
15664                    // Nothing to do, LTR by default
15665            }
15666        }
15667
15668        // Set to resolved
15669        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15670        return true;
15671    }
15672
15673    /**
15674     * Check if layout direction resolution can be done.
15675     *
15676     * @return true if layout direction resolution can be done otherwise return false.
15677     */
15678    public boolean canResolveLayoutDirection() {
15679        switch (getRawLayoutDirection()) {
15680            case LAYOUT_DIRECTION_INHERIT:
15681                if (mParent != null) {
15682                    try {
15683                        return mParent.canResolveLayoutDirection();
15684                    } catch (AbstractMethodError e) {
15685                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15686                                " does not fully implement ViewParent", e);
15687                    }
15688                }
15689                return false;
15690
15691            default:
15692                return true;
15693        }
15694    }
15695
15696    /**
15697     * Reset the resolved layout direction. Layout direction will be resolved during a call to
15698     * {@link #onMeasure(int, int)}.
15699     *
15700     * @hide
15701     */
15702    public void resetResolvedLayoutDirection() {
15703        // Reset the current resolved bits
15704        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15705    }
15706
15707    /**
15708     * @return true if the layout direction is inherited.
15709     *
15710     * @hide
15711     */
15712    public boolean isLayoutDirectionInherited() {
15713        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
15714    }
15715
15716    /**
15717     * @return true if layout direction has been resolved.
15718     */
15719    public boolean isLayoutDirectionResolved() {
15720        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15721    }
15722
15723    /**
15724     * Return if padding has been resolved
15725     *
15726     * @hide
15727     */
15728    boolean isPaddingResolved() {
15729        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
15730    }
15731
15732    /**
15733     * Resolves padding depending on layout direction, if applicable, and
15734     * recomputes internal padding values to adjust for scroll bars.
15735     *
15736     * @hide
15737     */
15738    public void resolvePadding() {
15739        final int resolvedLayoutDirection = getLayoutDirection();
15740
15741        if (!isRtlCompatibilityMode()) {
15742            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
15743            // If start / end padding are defined, they will be resolved (hence overriding) to
15744            // left / right or right / left depending on the resolved layout direction.
15745            // If start / end padding are not defined, use the left / right ones.
15746            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
15747                Rect padding = sThreadLocal.get();
15748                if (padding == null) {
15749                    padding = new Rect();
15750                    sThreadLocal.set(padding);
15751                }
15752                mBackground.getPadding(padding);
15753                if (!mLeftPaddingDefined) {
15754                    mUserPaddingLeftInitial = padding.left;
15755                }
15756                if (!mRightPaddingDefined) {
15757                    mUserPaddingRightInitial = padding.right;
15758                }
15759            }
15760            switch (resolvedLayoutDirection) {
15761                case LAYOUT_DIRECTION_RTL:
15762                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15763                        mUserPaddingRight = mUserPaddingStart;
15764                    } else {
15765                        mUserPaddingRight = mUserPaddingRightInitial;
15766                    }
15767                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15768                        mUserPaddingLeft = mUserPaddingEnd;
15769                    } else {
15770                        mUserPaddingLeft = mUserPaddingLeftInitial;
15771                    }
15772                    break;
15773                case LAYOUT_DIRECTION_LTR:
15774                default:
15775                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15776                        mUserPaddingLeft = mUserPaddingStart;
15777                    } else {
15778                        mUserPaddingLeft = mUserPaddingLeftInitial;
15779                    }
15780                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15781                        mUserPaddingRight = mUserPaddingEnd;
15782                    } else {
15783                        mUserPaddingRight = mUserPaddingRightInitial;
15784                    }
15785            }
15786
15787            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
15788        }
15789
15790        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15791        onRtlPropertiesChanged(resolvedLayoutDirection);
15792
15793        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
15794    }
15795
15796    /**
15797     * Reset the resolved layout direction.
15798     *
15799     * @hide
15800     */
15801    public void resetResolvedPadding() {
15802        resetResolvedPaddingInternal();
15803    }
15804
15805    /**
15806     * Used when we only want to reset *this* view's padding and not trigger overrides
15807     * in ViewGroup that reset children too.
15808     */
15809    void resetResolvedPaddingInternal() {
15810        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
15811    }
15812
15813    /**
15814     * This is called when the view is detached from a window.  At this point it
15815     * no longer has a surface for drawing.
15816     *
15817     * @see #onAttachedToWindow()
15818     */
15819    @CallSuper
15820    protected void onDetachedFromWindow() {
15821    }
15822
15823    /**
15824     * This is a framework-internal mirror of onDetachedFromWindow() that's called
15825     * after onDetachedFromWindow().
15826     *
15827     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
15828     * The super method should be called at the end of the overridden method to ensure
15829     * subclasses are destroyed first
15830     *
15831     * @hide
15832     */
15833    @CallSuper
15834    protected void onDetachedFromWindowInternal() {
15835        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
15836        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15837        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
15838
15839        removeUnsetPressCallback();
15840        removeLongPressCallback();
15841        removePerformClickCallback();
15842        removeSendViewScrolledAccessibilityEventCallback();
15843        stopNestedScroll();
15844
15845        // Anything that started animating right before detach should already
15846        // be in its final state when re-attached.
15847        jumpDrawablesToCurrentState();
15848
15849        destroyDrawingCache();
15850
15851        cleanupDraw();
15852        mCurrentAnimation = null;
15853
15854        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
15855            hideTooltip();
15856        }
15857    }
15858
15859    private void cleanupDraw() {
15860        resetDisplayList();
15861        if (mAttachInfo != null) {
15862            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
15863        }
15864    }
15865
15866    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
15867    }
15868
15869    /**
15870     * @return The number of times this view has been attached to a window
15871     */
15872    protected int getWindowAttachCount() {
15873        return mWindowAttachCount;
15874    }
15875
15876    /**
15877     * Retrieve a unique token identifying the window this view is attached to.
15878     * @return Return the window's token for use in
15879     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
15880     */
15881    public IBinder getWindowToken() {
15882        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
15883    }
15884
15885    /**
15886     * Retrieve the {@link WindowId} for the window this view is
15887     * currently attached to.
15888     */
15889    public WindowId getWindowId() {
15890        if (mAttachInfo == null) {
15891            return null;
15892        }
15893        if (mAttachInfo.mWindowId == null) {
15894            try {
15895                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
15896                        mAttachInfo.mWindowToken);
15897                mAttachInfo.mWindowId = new WindowId(
15898                        mAttachInfo.mIWindowId);
15899            } catch (RemoteException e) {
15900            }
15901        }
15902        return mAttachInfo.mWindowId;
15903    }
15904
15905    /**
15906     * Retrieve a unique token identifying the top-level "real" window of
15907     * the window that this view is attached to.  That is, this is like
15908     * {@link #getWindowToken}, except if the window this view in is a panel
15909     * window (attached to another containing window), then the token of
15910     * the containing window is returned instead.
15911     *
15912     * @return Returns the associated window token, either
15913     * {@link #getWindowToken()} or the containing window's token.
15914     */
15915    public IBinder getApplicationWindowToken() {
15916        AttachInfo ai = mAttachInfo;
15917        if (ai != null) {
15918            IBinder appWindowToken = ai.mPanelParentWindowToken;
15919            if (appWindowToken == null) {
15920                appWindowToken = ai.mWindowToken;
15921            }
15922            return appWindowToken;
15923        }
15924        return null;
15925    }
15926
15927    /**
15928     * Gets the logical display to which the view's window has been attached.
15929     *
15930     * @return The logical display, or null if the view is not currently attached to a window.
15931     */
15932    public Display getDisplay() {
15933        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
15934    }
15935
15936    /**
15937     * Retrieve private session object this view hierarchy is using to
15938     * communicate with the window manager.
15939     * @return the session object to communicate with the window manager
15940     */
15941    /*package*/ IWindowSession getWindowSession() {
15942        return mAttachInfo != null ? mAttachInfo.mSession : null;
15943    }
15944
15945    /**
15946     * Return the visibility value of the least visible component passed.
15947     */
15948    int combineVisibility(int vis1, int vis2) {
15949        // This works because VISIBLE < INVISIBLE < GONE.
15950        return Math.max(vis1, vis2);
15951    }
15952
15953    /**
15954     * @param info the {@link android.view.View.AttachInfo} to associated with
15955     *        this view
15956     */
15957    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
15958        mAttachInfo = info;
15959        if (mOverlay != null) {
15960            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
15961        }
15962        mWindowAttachCount++;
15963        // We will need to evaluate the drawable state at least once.
15964        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15965        if (mFloatingTreeObserver != null) {
15966            info.mTreeObserver.merge(mFloatingTreeObserver);
15967            mFloatingTreeObserver = null;
15968        }
15969
15970        registerPendingFrameMetricsObservers();
15971
15972        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
15973            mAttachInfo.mScrollContainers.add(this);
15974            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
15975        }
15976        // Transfer all pending runnables.
15977        if (mRunQueue != null) {
15978            mRunQueue.executeActions(info.mHandler);
15979            mRunQueue = null;
15980        }
15981        performCollectViewAttributes(mAttachInfo, visibility);
15982        onAttachedToWindow();
15983
15984        ListenerInfo li = mListenerInfo;
15985        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15986                li != null ? li.mOnAttachStateChangeListeners : null;
15987        if (listeners != null && listeners.size() > 0) {
15988            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15989            // perform the dispatching. The iterator is a safe guard against listeners that
15990            // could mutate the list by calling the various add/remove methods. This prevents
15991            // the array from being modified while we iterate it.
15992            for (OnAttachStateChangeListener listener : listeners) {
15993                listener.onViewAttachedToWindow(this);
15994            }
15995        }
15996
15997        int vis = info.mWindowVisibility;
15998        if (vis != GONE) {
15999            onWindowVisibilityChanged(vis);
16000            if (isShown()) {
16001                // Calling onVisibilityAggregated directly here since the subtree will also
16002                // receive dispatchAttachedToWindow and this same call
16003                onVisibilityAggregated(vis == VISIBLE);
16004            }
16005        }
16006
16007        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
16008        // As all views in the subtree will already receive dispatchAttachedToWindow
16009        // traversing the subtree again here is not desired.
16010        onVisibilityChanged(this, visibility);
16011
16012        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
16013            // If nobody has evaluated the drawable state yet, then do it now.
16014            refreshDrawableState();
16015        }
16016        needGlobalAttributesUpdate(false);
16017    }
16018
16019    void dispatchDetachedFromWindow() {
16020        AttachInfo info = mAttachInfo;
16021        if (info != null) {
16022            int vis = info.mWindowVisibility;
16023            if (vis != GONE) {
16024                onWindowVisibilityChanged(GONE);
16025                if (isShown()) {
16026                    // Invoking onVisibilityAggregated directly here since the subtree
16027                    // will also receive detached from window
16028                    onVisibilityAggregated(false);
16029                }
16030            }
16031        }
16032
16033        onDetachedFromWindow();
16034        onDetachedFromWindowInternal();
16035
16036        InputMethodManager imm = InputMethodManager.peekInstance();
16037        if (imm != null) {
16038            imm.onViewDetachedFromWindow(this);
16039        }
16040
16041        ListenerInfo li = mListenerInfo;
16042        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
16043                li != null ? li.mOnAttachStateChangeListeners : null;
16044        if (listeners != null && listeners.size() > 0) {
16045            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
16046            // perform the dispatching. The iterator is a safe guard against listeners that
16047            // could mutate the list by calling the various add/remove methods. This prevents
16048            // the array from being modified while we iterate it.
16049            for (OnAttachStateChangeListener listener : listeners) {
16050                listener.onViewDetachedFromWindow(this);
16051            }
16052        }
16053
16054        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
16055            mAttachInfo.mScrollContainers.remove(this);
16056            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
16057        }
16058
16059        mAttachInfo = null;
16060        if (mOverlay != null) {
16061            mOverlay.getOverlayView().dispatchDetachedFromWindow();
16062        }
16063    }
16064
16065    /**
16066     * Cancel any deferred high-level input events that were previously posted to the event queue.
16067     *
16068     * <p>Many views post high-level events such as click handlers to the event queue
16069     * to run deferred in order to preserve a desired user experience - clearing visible
16070     * pressed states before executing, etc. This method will abort any events of this nature
16071     * that are currently in flight.</p>
16072     *
16073     * <p>Custom views that generate their own high-level deferred input events should override
16074     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
16075     *
16076     * <p>This will also cancel pending input events for any child views.</p>
16077     *
16078     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
16079     * This will not impact newer events posted after this call that may occur as a result of
16080     * lower-level input events still waiting in the queue. If you are trying to prevent
16081     * double-submitted  events for the duration of some sort of asynchronous transaction
16082     * you should also take other steps to protect against unexpected double inputs e.g. calling
16083     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
16084     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
16085     */
16086    public final void cancelPendingInputEvents() {
16087        dispatchCancelPendingInputEvents();
16088    }
16089
16090    /**
16091     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
16092     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
16093     */
16094    void dispatchCancelPendingInputEvents() {
16095        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
16096        onCancelPendingInputEvents();
16097        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
16098            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
16099                    " did not call through to super.onCancelPendingInputEvents()");
16100        }
16101    }
16102
16103    /**
16104     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
16105     * a parent view.
16106     *
16107     * <p>This method is responsible for removing any pending high-level input events that were
16108     * posted to the event queue to run later. Custom view classes that post their own deferred
16109     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
16110     * {@link android.os.Handler} should override this method, call
16111     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
16112     * </p>
16113     */
16114    public void onCancelPendingInputEvents() {
16115        removePerformClickCallback();
16116        cancelLongPress();
16117        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
16118    }
16119
16120    /**
16121     * Store this view hierarchy's frozen state into the given container.
16122     *
16123     * @param container The SparseArray in which to save the view's state.
16124     *
16125     * @see #restoreHierarchyState(android.util.SparseArray)
16126     * @see #dispatchSaveInstanceState(android.util.SparseArray)
16127     * @see #onSaveInstanceState()
16128     */
16129    public void saveHierarchyState(SparseArray<Parcelable> container) {
16130        dispatchSaveInstanceState(container);
16131    }
16132
16133    /**
16134     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
16135     * this view and its children. May be overridden to modify how freezing happens to a
16136     * view's children; for example, some views may want to not store state for their children.
16137     *
16138     * @param container The SparseArray in which to save the view's state.
16139     *
16140     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
16141     * @see #saveHierarchyState(android.util.SparseArray)
16142     * @see #onSaveInstanceState()
16143     */
16144    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
16145        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
16146            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
16147            Parcelable state = onSaveInstanceState();
16148            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
16149                throw new IllegalStateException(
16150                        "Derived class did not call super.onSaveInstanceState()");
16151            }
16152            if (state != null) {
16153                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
16154                // + ": " + state);
16155                container.put(mID, state);
16156            }
16157        }
16158    }
16159
16160    /**
16161     * Hook allowing a view to generate a representation of its internal state
16162     * that can later be used to create a new instance with that same state.
16163     * This state should only contain information that is not persistent or can
16164     * not be reconstructed later. For example, you will never store your
16165     * current position on screen because that will be computed again when a
16166     * new instance of the view is placed in its view hierarchy.
16167     * <p>
16168     * Some examples of things you may store here: the current cursor position
16169     * in a text view (but usually not the text itself since that is stored in a
16170     * content provider or other persistent storage), the currently selected
16171     * item in a list view.
16172     *
16173     * @return Returns a Parcelable object containing the view's current dynamic
16174     *         state, or null if there is nothing interesting to save. The
16175     *         default implementation returns null.
16176     * @see #onRestoreInstanceState(android.os.Parcelable)
16177     * @see #saveHierarchyState(android.util.SparseArray)
16178     * @see #dispatchSaveInstanceState(android.util.SparseArray)
16179     * @see #setSaveEnabled(boolean)
16180     */
16181    @CallSuper
16182    protected Parcelable onSaveInstanceState() {
16183        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
16184        if (mStartActivityRequestWho != null) {
16185            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
16186            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
16187            return state;
16188        }
16189        return BaseSavedState.EMPTY_STATE;
16190    }
16191
16192    /**
16193     * Restore this view hierarchy's frozen state from the given container.
16194     *
16195     * @param container The SparseArray which holds previously frozen states.
16196     *
16197     * @see #saveHierarchyState(android.util.SparseArray)
16198     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
16199     * @see #onRestoreInstanceState(android.os.Parcelable)
16200     */
16201    public void restoreHierarchyState(SparseArray<Parcelable> container) {
16202        dispatchRestoreInstanceState(container);
16203    }
16204
16205    /**
16206     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
16207     * state for this view and its children. May be overridden to modify how restoring
16208     * happens to a view's children; for example, some views may want to not store state
16209     * for their children.
16210     *
16211     * @param container The SparseArray which holds previously saved state.
16212     *
16213     * @see #dispatchSaveInstanceState(android.util.SparseArray)
16214     * @see #restoreHierarchyState(android.util.SparseArray)
16215     * @see #onRestoreInstanceState(android.os.Parcelable)
16216     */
16217    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
16218        if (mID != NO_ID) {
16219            Parcelable state = container.get(mID);
16220            if (state != null) {
16221                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
16222                // + ": " + state);
16223                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
16224                onRestoreInstanceState(state);
16225                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
16226                    throw new IllegalStateException(
16227                            "Derived class did not call super.onRestoreInstanceState()");
16228                }
16229            }
16230        }
16231    }
16232
16233    /**
16234     * Hook allowing a view to re-apply a representation of its internal state that had previously
16235     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
16236     * null state.
16237     *
16238     * @param state The frozen state that had previously been returned by
16239     *        {@link #onSaveInstanceState}.
16240     *
16241     * @see #onSaveInstanceState()
16242     * @see #restoreHierarchyState(android.util.SparseArray)
16243     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
16244     */
16245    @CallSuper
16246    protected void onRestoreInstanceState(Parcelable state) {
16247        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
16248        if (state != null && !(state instanceof AbsSavedState)) {
16249            throw new IllegalArgumentException("Wrong state class, expecting View State but "
16250                    + "received " + state.getClass().toString() + " instead. This usually happens "
16251                    + "when two views of different type have the same id in the same hierarchy. "
16252                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
16253                    + "other views do not use the same id.");
16254        }
16255        if (state != null && state instanceof BaseSavedState) {
16256            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
16257        }
16258    }
16259
16260    /**
16261     * <p>Return the time at which the drawing of the view hierarchy started.</p>
16262     *
16263     * @return the drawing start time in milliseconds
16264     */
16265    public long getDrawingTime() {
16266        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
16267    }
16268
16269    /**
16270     * <p>Enables or disables the duplication of the parent's state into this view. When
16271     * duplication is enabled, this view gets its drawable state from its parent rather
16272     * than from its own internal properties.</p>
16273     *
16274     * <p>Note: in the current implementation, setting this property to true after the
16275     * view was added to a ViewGroup might have no effect at all. This property should
16276     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
16277     *
16278     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
16279     * property is enabled, an exception will be thrown.</p>
16280     *
16281     * <p>Note: if the child view uses and updates additional states which are unknown to the
16282     * parent, these states should not be affected by this method.</p>
16283     *
16284     * @param enabled True to enable duplication of the parent's drawable state, false
16285     *                to disable it.
16286     *
16287     * @see #getDrawableState()
16288     * @see #isDuplicateParentStateEnabled()
16289     */
16290    public void setDuplicateParentStateEnabled(boolean enabled) {
16291        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
16292    }
16293
16294    /**
16295     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
16296     *
16297     * @return True if this view's drawable state is duplicated from the parent,
16298     *         false otherwise
16299     *
16300     * @see #getDrawableState()
16301     * @see #setDuplicateParentStateEnabled(boolean)
16302     */
16303    public boolean isDuplicateParentStateEnabled() {
16304        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
16305    }
16306
16307    /**
16308     * <p>Specifies the type of layer backing this view. The layer can be
16309     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
16310     * {@link #LAYER_TYPE_HARDWARE}.</p>
16311     *
16312     * <p>A layer is associated with an optional {@link android.graphics.Paint}
16313     * instance that controls how the layer is composed on screen. The following
16314     * properties of the paint are taken into account when composing the layer:</p>
16315     * <ul>
16316     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
16317     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
16318     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
16319     * </ul>
16320     *
16321     * <p>If this view has an alpha value set to < 1.0 by calling
16322     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
16323     * by this view's alpha value.</p>
16324     *
16325     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
16326     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
16327     * for more information on when and how to use layers.</p>
16328     *
16329     * @param layerType The type of layer to use with this view, must be one of
16330     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
16331     *        {@link #LAYER_TYPE_HARDWARE}
16332     * @param paint The paint used to compose the layer. This argument is optional
16333     *        and can be null. It is ignored when the layer type is
16334     *        {@link #LAYER_TYPE_NONE}
16335     *
16336     * @see #getLayerType()
16337     * @see #LAYER_TYPE_NONE
16338     * @see #LAYER_TYPE_SOFTWARE
16339     * @see #LAYER_TYPE_HARDWARE
16340     * @see #setAlpha(float)
16341     *
16342     * @attr ref android.R.styleable#View_layerType
16343     */
16344    public void setLayerType(int layerType, @Nullable Paint paint) {
16345        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
16346            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
16347                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
16348        }
16349
16350        boolean typeChanged = mRenderNode.setLayerType(layerType);
16351
16352        if (!typeChanged) {
16353            setLayerPaint(paint);
16354            return;
16355        }
16356
16357        if (layerType != LAYER_TYPE_SOFTWARE) {
16358            // Destroy any previous software drawing cache if present
16359            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
16360            // drawing cache created in View#draw when drawing to a SW canvas.
16361            destroyDrawingCache();
16362        }
16363
16364        mLayerType = layerType;
16365        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
16366        mRenderNode.setLayerPaint(mLayerPaint);
16367
16368        // draw() behaves differently if we are on a layer, so we need to
16369        // invalidate() here
16370        invalidateParentCaches();
16371        invalidate(true);
16372    }
16373
16374    /**
16375     * Updates the {@link Paint} object used with the current layer (used only if the current
16376     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
16377     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
16378     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
16379     * ensure that the view gets redrawn immediately.
16380     *
16381     * <p>A layer is associated with an optional {@link android.graphics.Paint}
16382     * instance that controls how the layer is composed on screen. The following
16383     * properties of the paint are taken into account when composing the layer:</p>
16384     * <ul>
16385     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
16386     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
16387     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
16388     * </ul>
16389     *
16390     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
16391     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
16392     *
16393     * @param paint The paint used to compose the layer. This argument is optional
16394     *        and can be null. It is ignored when the layer type is
16395     *        {@link #LAYER_TYPE_NONE}
16396     *
16397     * @see #setLayerType(int, android.graphics.Paint)
16398     */
16399    public void setLayerPaint(@Nullable Paint paint) {
16400        int layerType = getLayerType();
16401        if (layerType != LAYER_TYPE_NONE) {
16402            mLayerPaint = paint;
16403            if (layerType == LAYER_TYPE_HARDWARE) {
16404                if (mRenderNode.setLayerPaint(paint)) {
16405                    invalidateViewProperty(false, false);
16406                }
16407            } else {
16408                invalidate();
16409            }
16410        }
16411    }
16412
16413    /**
16414     * Indicates what type of layer is currently associated with this view. By default
16415     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
16416     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
16417     * for more information on the different types of layers.
16418     *
16419     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
16420     *         {@link #LAYER_TYPE_HARDWARE}
16421     *
16422     * @see #setLayerType(int, android.graphics.Paint)
16423     * @see #buildLayer()
16424     * @see #LAYER_TYPE_NONE
16425     * @see #LAYER_TYPE_SOFTWARE
16426     * @see #LAYER_TYPE_HARDWARE
16427     */
16428    public int getLayerType() {
16429        return mLayerType;
16430    }
16431
16432    /**
16433     * Forces this view's layer to be created and this view to be rendered
16434     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
16435     * invoking this method will have no effect.
16436     *
16437     * This method can for instance be used to render a view into its layer before
16438     * starting an animation. If this view is complex, rendering into the layer
16439     * before starting the animation will avoid skipping frames.
16440     *
16441     * @throws IllegalStateException If this view is not attached to a window
16442     *
16443     * @see #setLayerType(int, android.graphics.Paint)
16444     */
16445    public void buildLayer() {
16446        if (mLayerType == LAYER_TYPE_NONE) return;
16447
16448        final AttachInfo attachInfo = mAttachInfo;
16449        if (attachInfo == null) {
16450            throw new IllegalStateException("This view must be attached to a window first");
16451        }
16452
16453        if (getWidth() == 0 || getHeight() == 0) {
16454            return;
16455        }
16456
16457        switch (mLayerType) {
16458            case LAYER_TYPE_HARDWARE:
16459                updateDisplayListIfDirty();
16460                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
16461                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
16462                }
16463                break;
16464            case LAYER_TYPE_SOFTWARE:
16465                buildDrawingCache(true);
16466                break;
16467        }
16468    }
16469
16470    /**
16471     * Destroys all hardware rendering resources. This method is invoked
16472     * when the system needs to reclaim resources. Upon execution of this
16473     * method, you should free any OpenGL resources created by the view.
16474     *
16475     * Note: you <strong>must</strong> call
16476     * <code>super.destroyHardwareResources()</code> when overriding
16477     * this method.
16478     *
16479     * @hide
16480     */
16481    @CallSuper
16482    protected void destroyHardwareResources() {
16483        // Although the Layer will be destroyed by RenderNode, we want to release
16484        // the staging display list, which is also a signal to RenderNode that it's
16485        // safe to free its copy of the display list as it knows that we will
16486        // push an updated DisplayList if we try to draw again
16487        resetDisplayList();
16488    }
16489
16490    /**
16491     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
16492     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
16493     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
16494     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
16495     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
16496     * null.</p>
16497     *
16498     * <p>Enabling the drawing cache is similar to
16499     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
16500     * acceleration is turned off. When hardware acceleration is turned on, enabling the
16501     * drawing cache has no effect on rendering because the system uses a different mechanism
16502     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
16503     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
16504     * for information on how to enable software and hardware layers.</p>
16505     *
16506     * <p>This API can be used to manually generate
16507     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
16508     * {@link #getDrawingCache()}.</p>
16509     *
16510     * @param enabled true to enable the drawing cache, false otherwise
16511     *
16512     * @see #isDrawingCacheEnabled()
16513     * @see #getDrawingCache()
16514     * @see #buildDrawingCache()
16515     * @see #setLayerType(int, android.graphics.Paint)
16516     */
16517    public void setDrawingCacheEnabled(boolean enabled) {
16518        mCachingFailed = false;
16519        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
16520    }
16521
16522    /**
16523     * <p>Indicates whether the drawing cache is enabled for this view.</p>
16524     *
16525     * @return true if the drawing cache is enabled
16526     *
16527     * @see #setDrawingCacheEnabled(boolean)
16528     * @see #getDrawingCache()
16529     */
16530    @ViewDebug.ExportedProperty(category = "drawing")
16531    public boolean isDrawingCacheEnabled() {
16532        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
16533    }
16534
16535    /**
16536     * Debugging utility which recursively outputs the dirty state of a view and its
16537     * descendants.
16538     *
16539     * @hide
16540     */
16541    @SuppressWarnings({"UnusedDeclaration"})
16542    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
16543        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
16544                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
16545                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
16546                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
16547        if (clear) {
16548            mPrivateFlags &= clearMask;
16549        }
16550        if (this instanceof ViewGroup) {
16551            ViewGroup parent = (ViewGroup) this;
16552            final int count = parent.getChildCount();
16553            for (int i = 0; i < count; i++) {
16554                final View child = parent.getChildAt(i);
16555                child.outputDirtyFlags(indent + "  ", clear, clearMask);
16556            }
16557        }
16558    }
16559
16560    /**
16561     * This method is used by ViewGroup to cause its children to restore or recreate their
16562     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
16563     * to recreate its own display list, which would happen if it went through the normal
16564     * draw/dispatchDraw mechanisms.
16565     *
16566     * @hide
16567     */
16568    protected void dispatchGetDisplayList() {}
16569
16570    /**
16571     * A view that is not attached or hardware accelerated cannot create a display list.
16572     * This method checks these conditions and returns the appropriate result.
16573     *
16574     * @return true if view has the ability to create a display list, false otherwise.
16575     *
16576     * @hide
16577     */
16578    public boolean canHaveDisplayList() {
16579        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
16580    }
16581
16582    /**
16583     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
16584     * @hide
16585     */
16586    @NonNull
16587    public RenderNode updateDisplayListIfDirty() {
16588        final RenderNode renderNode = mRenderNode;
16589        if (!canHaveDisplayList()) {
16590            // can't populate RenderNode, don't try
16591            return renderNode;
16592        }
16593
16594        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
16595                || !renderNode.isValid()
16596                || (mRecreateDisplayList)) {
16597            // Don't need to recreate the display list, just need to tell our
16598            // children to restore/recreate theirs
16599            if (renderNode.isValid()
16600                    && !mRecreateDisplayList) {
16601                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16602                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16603                dispatchGetDisplayList();
16604
16605                return renderNode; // no work needed
16606            }
16607
16608            // If we got here, we're recreating it. Mark it as such to ensure that
16609            // we copy in child display lists into ours in drawChild()
16610            mRecreateDisplayList = true;
16611
16612            int width = mRight - mLeft;
16613            int height = mBottom - mTop;
16614            int layerType = getLayerType();
16615
16616            final DisplayListCanvas canvas = renderNode.start(width, height);
16617            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
16618
16619            try {
16620                if (layerType == LAYER_TYPE_SOFTWARE) {
16621                    buildDrawingCache(true);
16622                    Bitmap cache = getDrawingCache(true);
16623                    if (cache != null) {
16624                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
16625                    }
16626                } else {
16627                    computeScroll();
16628
16629                    canvas.translate(-mScrollX, -mScrollY);
16630                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16631                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16632
16633                    // Fast path for layouts with no backgrounds
16634                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16635                        dispatchDraw(canvas);
16636                        if (mOverlay != null && !mOverlay.isEmpty()) {
16637                            mOverlay.getOverlayView().draw(canvas);
16638                        }
16639                        if (debugDraw()) {
16640                            debugDrawFocus(canvas);
16641                        }
16642                    } else {
16643                        draw(canvas);
16644                    }
16645                }
16646            } finally {
16647                renderNode.end(canvas);
16648                setDisplayListProperties(renderNode);
16649            }
16650        } else {
16651            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16652            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16653        }
16654        return renderNode;
16655    }
16656
16657    private void resetDisplayList() {
16658        if (mRenderNode.isValid()) {
16659            mRenderNode.discardDisplayList();
16660        }
16661
16662        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
16663            mBackgroundRenderNode.discardDisplayList();
16664        }
16665    }
16666
16667    /**
16668     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
16669     *
16670     * @return A non-scaled bitmap representing this view or null if cache is disabled.
16671     *
16672     * @see #getDrawingCache(boolean)
16673     */
16674    public Bitmap getDrawingCache() {
16675        return getDrawingCache(false);
16676    }
16677
16678    /**
16679     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
16680     * is null when caching is disabled. If caching is enabled and the cache is not ready,
16681     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
16682     * draw from the cache when the cache is enabled. To benefit from the cache, you must
16683     * request the drawing cache by calling this method and draw it on screen if the
16684     * returned bitmap is not null.</p>
16685     *
16686     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16687     * this method will create a bitmap of the same size as this view. Because this bitmap
16688     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16689     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16690     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16691     * size than the view. This implies that your application must be able to handle this
16692     * size.</p>
16693     *
16694     * @param autoScale Indicates whether the generated bitmap should be scaled based on
16695     *        the current density of the screen when the application is in compatibility
16696     *        mode.
16697     *
16698     * @return A bitmap representing this view or null if cache is disabled.
16699     *
16700     * @see #setDrawingCacheEnabled(boolean)
16701     * @see #isDrawingCacheEnabled()
16702     * @see #buildDrawingCache(boolean)
16703     * @see #destroyDrawingCache()
16704     */
16705    public Bitmap getDrawingCache(boolean autoScale) {
16706        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
16707            return null;
16708        }
16709        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
16710            buildDrawingCache(autoScale);
16711        }
16712        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
16713    }
16714
16715    /**
16716     * <p>Frees the resources used by the drawing cache. If you call
16717     * {@link #buildDrawingCache()} manually without calling
16718     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16719     * should cleanup the cache with this method afterwards.</p>
16720     *
16721     * @see #setDrawingCacheEnabled(boolean)
16722     * @see #buildDrawingCache()
16723     * @see #getDrawingCache()
16724     */
16725    public void destroyDrawingCache() {
16726        if (mDrawingCache != null) {
16727            mDrawingCache.recycle();
16728            mDrawingCache = null;
16729        }
16730        if (mUnscaledDrawingCache != null) {
16731            mUnscaledDrawingCache.recycle();
16732            mUnscaledDrawingCache = null;
16733        }
16734    }
16735
16736    /**
16737     * Setting a solid background color for the drawing cache's bitmaps will improve
16738     * performance and memory usage. Note, though that this should only be used if this
16739     * view will always be drawn on top of a solid color.
16740     *
16741     * @param color The background color to use for the drawing cache's bitmap
16742     *
16743     * @see #setDrawingCacheEnabled(boolean)
16744     * @see #buildDrawingCache()
16745     * @see #getDrawingCache()
16746     */
16747    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
16748        if (color != mDrawingCacheBackgroundColor) {
16749            mDrawingCacheBackgroundColor = color;
16750            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16751        }
16752    }
16753
16754    /**
16755     * @see #setDrawingCacheBackgroundColor(int)
16756     *
16757     * @return The background color to used for the drawing cache's bitmap
16758     */
16759    @ColorInt
16760    public int getDrawingCacheBackgroundColor() {
16761        return mDrawingCacheBackgroundColor;
16762    }
16763
16764    /**
16765     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
16766     *
16767     * @see #buildDrawingCache(boolean)
16768     */
16769    public void buildDrawingCache() {
16770        buildDrawingCache(false);
16771    }
16772
16773    /**
16774     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
16775     *
16776     * <p>If you call {@link #buildDrawingCache()} manually without calling
16777     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16778     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
16779     *
16780     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16781     * this method will create a bitmap of the same size as this view. Because this bitmap
16782     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16783     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16784     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16785     * size than the view. This implies that your application must be able to handle this
16786     * size.</p>
16787     *
16788     * <p>You should avoid calling this method when hardware acceleration is enabled. If
16789     * you do not need the drawing cache bitmap, calling this method will increase memory
16790     * usage and cause the view to be rendered in software once, thus negatively impacting
16791     * performance.</p>
16792     *
16793     * @see #getDrawingCache()
16794     * @see #destroyDrawingCache()
16795     */
16796    public void buildDrawingCache(boolean autoScale) {
16797        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
16798                mDrawingCache == null : mUnscaledDrawingCache == null)) {
16799            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
16800                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
16801                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
16802            }
16803            try {
16804                buildDrawingCacheImpl(autoScale);
16805            } finally {
16806                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
16807            }
16808        }
16809    }
16810
16811    /**
16812     * private, internal implementation of buildDrawingCache, used to enable tracing
16813     */
16814    private void buildDrawingCacheImpl(boolean autoScale) {
16815        mCachingFailed = false;
16816
16817        int width = mRight - mLeft;
16818        int height = mBottom - mTop;
16819
16820        final AttachInfo attachInfo = mAttachInfo;
16821        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
16822
16823        if (autoScale && scalingRequired) {
16824            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
16825            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
16826        }
16827
16828        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
16829        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
16830        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
16831
16832        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
16833        final long drawingCacheSize =
16834                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
16835        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
16836            if (width > 0 && height > 0) {
16837                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
16838                        + " too large to fit into a software layer (or drawing cache), needs "
16839                        + projectedBitmapSize + " bytes, only "
16840                        + drawingCacheSize + " available");
16841            }
16842            destroyDrawingCache();
16843            mCachingFailed = true;
16844            return;
16845        }
16846
16847        boolean clear = true;
16848        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
16849
16850        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
16851            Bitmap.Config quality;
16852            if (!opaque) {
16853                // Never pick ARGB_4444 because it looks awful
16854                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
16855                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
16856                    case DRAWING_CACHE_QUALITY_AUTO:
16857                    case DRAWING_CACHE_QUALITY_LOW:
16858                    case DRAWING_CACHE_QUALITY_HIGH:
16859                    default:
16860                        quality = Bitmap.Config.ARGB_8888;
16861                        break;
16862                }
16863            } else {
16864                // Optimization for translucent windows
16865                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
16866                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
16867            }
16868
16869            // Try to cleanup memory
16870            if (bitmap != null) bitmap.recycle();
16871
16872            try {
16873                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16874                        width, height, quality);
16875                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
16876                if (autoScale) {
16877                    mDrawingCache = bitmap;
16878                } else {
16879                    mUnscaledDrawingCache = bitmap;
16880                }
16881                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
16882            } catch (OutOfMemoryError e) {
16883                // If there is not enough memory to create the bitmap cache, just
16884                // ignore the issue as bitmap caches are not required to draw the
16885                // view hierarchy
16886                if (autoScale) {
16887                    mDrawingCache = null;
16888                } else {
16889                    mUnscaledDrawingCache = null;
16890                }
16891                mCachingFailed = true;
16892                return;
16893            }
16894
16895            clear = drawingCacheBackgroundColor != 0;
16896        }
16897
16898        Canvas canvas;
16899        if (attachInfo != null) {
16900            canvas = attachInfo.mCanvas;
16901            if (canvas == null) {
16902                canvas = new Canvas();
16903            }
16904            canvas.setBitmap(bitmap);
16905            // Temporarily clobber the cached Canvas in case one of our children
16906            // is also using a drawing cache. Without this, the children would
16907            // steal the canvas by attaching their own bitmap to it and bad, bad
16908            // thing would happen (invisible views, corrupted drawings, etc.)
16909            attachInfo.mCanvas = null;
16910        } else {
16911            // This case should hopefully never or seldom happen
16912            canvas = new Canvas(bitmap);
16913        }
16914
16915        if (clear) {
16916            bitmap.eraseColor(drawingCacheBackgroundColor);
16917        }
16918
16919        computeScroll();
16920        final int restoreCount = canvas.save();
16921
16922        if (autoScale && scalingRequired) {
16923            final float scale = attachInfo.mApplicationScale;
16924            canvas.scale(scale, scale);
16925        }
16926
16927        canvas.translate(-mScrollX, -mScrollY);
16928
16929        mPrivateFlags |= PFLAG_DRAWN;
16930        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
16931                mLayerType != LAYER_TYPE_NONE) {
16932            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
16933        }
16934
16935        // Fast path for layouts with no backgrounds
16936        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16937            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16938            dispatchDraw(canvas);
16939            if (mOverlay != null && !mOverlay.isEmpty()) {
16940                mOverlay.getOverlayView().draw(canvas);
16941            }
16942        } else {
16943            draw(canvas);
16944        }
16945
16946        canvas.restoreToCount(restoreCount);
16947        canvas.setBitmap(null);
16948
16949        if (attachInfo != null) {
16950            // Restore the cached Canvas for our siblings
16951            attachInfo.mCanvas = canvas;
16952        }
16953    }
16954
16955    /**
16956     * Create a snapshot of the view into a bitmap.  We should probably make
16957     * some form of this public, but should think about the API.
16958     *
16959     * @hide
16960     */
16961    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
16962        int width = mRight - mLeft;
16963        int height = mBottom - mTop;
16964
16965        final AttachInfo attachInfo = mAttachInfo;
16966        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
16967        width = (int) ((width * scale) + 0.5f);
16968        height = (int) ((height * scale) + 0.5f);
16969
16970        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16971                width > 0 ? width : 1, height > 0 ? height : 1, quality);
16972        if (bitmap == null) {
16973            throw new OutOfMemoryError();
16974        }
16975
16976        Resources resources = getResources();
16977        if (resources != null) {
16978            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
16979        }
16980
16981        Canvas canvas;
16982        if (attachInfo != null) {
16983            canvas = attachInfo.mCanvas;
16984            if (canvas == null) {
16985                canvas = new Canvas();
16986            }
16987            canvas.setBitmap(bitmap);
16988            // Temporarily clobber the cached Canvas in case one of our children
16989            // is also using a drawing cache. Without this, the children would
16990            // steal the canvas by attaching their own bitmap to it and bad, bad
16991            // things would happen (invisible views, corrupted drawings, etc.)
16992            attachInfo.mCanvas = null;
16993        } else {
16994            // This case should hopefully never or seldom happen
16995            canvas = new Canvas(bitmap);
16996        }
16997
16998        if ((backgroundColor & 0xff000000) != 0) {
16999            bitmap.eraseColor(backgroundColor);
17000        }
17001
17002        computeScroll();
17003        final int restoreCount = canvas.save();
17004        canvas.scale(scale, scale);
17005        canvas.translate(-mScrollX, -mScrollY);
17006
17007        // Temporarily remove the dirty mask
17008        int flags = mPrivateFlags;
17009        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17010
17011        // Fast path for layouts with no backgrounds
17012        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17013            dispatchDraw(canvas);
17014            if (mOverlay != null && !mOverlay.isEmpty()) {
17015                mOverlay.getOverlayView().draw(canvas);
17016            }
17017        } else {
17018            draw(canvas);
17019        }
17020
17021        mPrivateFlags = flags;
17022
17023        canvas.restoreToCount(restoreCount);
17024        canvas.setBitmap(null);
17025
17026        if (attachInfo != null) {
17027            // Restore the cached Canvas for our siblings
17028            attachInfo.mCanvas = canvas;
17029        }
17030
17031        return bitmap;
17032    }
17033
17034    /**
17035     * Indicates whether this View is currently in edit mode. A View is usually
17036     * in edit mode when displayed within a developer tool. For instance, if
17037     * this View is being drawn by a visual user interface builder, this method
17038     * should return true.
17039     *
17040     * Subclasses should check the return value of this method to provide
17041     * different behaviors if their normal behavior might interfere with the
17042     * host environment. For instance: the class spawns a thread in its
17043     * constructor, the drawing code relies on device-specific features, etc.
17044     *
17045     * This method is usually checked in the drawing code of custom widgets.
17046     *
17047     * @return True if this View is in edit mode, false otherwise.
17048     */
17049    public boolean isInEditMode() {
17050        return false;
17051    }
17052
17053    /**
17054     * If the View draws content inside its padding and enables fading edges,
17055     * it needs to support padding offsets. Padding offsets are added to the
17056     * fading edges to extend the length of the fade so that it covers pixels
17057     * drawn inside the padding.
17058     *
17059     * Subclasses of this class should override this method if they need
17060     * to draw content inside the padding.
17061     *
17062     * @return True if padding offset must be applied, false otherwise.
17063     *
17064     * @see #getLeftPaddingOffset()
17065     * @see #getRightPaddingOffset()
17066     * @see #getTopPaddingOffset()
17067     * @see #getBottomPaddingOffset()
17068     *
17069     * @since CURRENT
17070     */
17071    protected boolean isPaddingOffsetRequired() {
17072        return false;
17073    }
17074
17075    /**
17076     * Amount by which to extend the left fading region. Called only when
17077     * {@link #isPaddingOffsetRequired()} returns true.
17078     *
17079     * @return The left padding offset in pixels.
17080     *
17081     * @see #isPaddingOffsetRequired()
17082     *
17083     * @since CURRENT
17084     */
17085    protected int getLeftPaddingOffset() {
17086        return 0;
17087    }
17088
17089    /**
17090     * Amount by which to extend the right fading region. Called only when
17091     * {@link #isPaddingOffsetRequired()} returns true.
17092     *
17093     * @return The right padding offset in pixels.
17094     *
17095     * @see #isPaddingOffsetRequired()
17096     *
17097     * @since CURRENT
17098     */
17099    protected int getRightPaddingOffset() {
17100        return 0;
17101    }
17102
17103    /**
17104     * Amount by which to extend the top fading region. Called only when
17105     * {@link #isPaddingOffsetRequired()} returns true.
17106     *
17107     * @return The top padding offset in pixels.
17108     *
17109     * @see #isPaddingOffsetRequired()
17110     *
17111     * @since CURRENT
17112     */
17113    protected int getTopPaddingOffset() {
17114        return 0;
17115    }
17116
17117    /**
17118     * Amount by which to extend the bottom fading region. Called only when
17119     * {@link #isPaddingOffsetRequired()} returns true.
17120     *
17121     * @return The bottom padding offset in pixels.
17122     *
17123     * @see #isPaddingOffsetRequired()
17124     *
17125     * @since CURRENT
17126     */
17127    protected int getBottomPaddingOffset() {
17128        return 0;
17129    }
17130
17131    /**
17132     * @hide
17133     * @param offsetRequired
17134     */
17135    protected int getFadeTop(boolean offsetRequired) {
17136        int top = mPaddingTop;
17137        if (offsetRequired) top += getTopPaddingOffset();
17138        return top;
17139    }
17140
17141    /**
17142     * @hide
17143     * @param offsetRequired
17144     */
17145    protected int getFadeHeight(boolean offsetRequired) {
17146        int padding = mPaddingTop;
17147        if (offsetRequired) padding += getTopPaddingOffset();
17148        return mBottom - mTop - mPaddingBottom - padding;
17149    }
17150
17151    /**
17152     * <p>Indicates whether this view is attached to a hardware accelerated
17153     * window or not.</p>
17154     *
17155     * <p>Even if this method returns true, it does not mean that every call
17156     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
17157     * accelerated {@link android.graphics.Canvas}. For instance, if this view
17158     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
17159     * window is hardware accelerated,
17160     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
17161     * return false, and this method will return true.</p>
17162     *
17163     * @return True if the view is attached to a window and the window is
17164     *         hardware accelerated; false in any other case.
17165     */
17166    @ViewDebug.ExportedProperty(category = "drawing")
17167    public boolean isHardwareAccelerated() {
17168        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
17169    }
17170
17171    /**
17172     * Sets a rectangular area on this view to which the view will be clipped
17173     * when it is drawn. Setting the value to null will remove the clip bounds
17174     * and the view will draw normally, using its full bounds.
17175     *
17176     * @param clipBounds The rectangular area, in the local coordinates of
17177     * this view, to which future drawing operations will be clipped.
17178     */
17179    public void setClipBounds(Rect clipBounds) {
17180        if (clipBounds == mClipBounds
17181                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
17182            return;
17183        }
17184        if (clipBounds != null) {
17185            if (mClipBounds == null) {
17186                mClipBounds = new Rect(clipBounds);
17187            } else {
17188                mClipBounds.set(clipBounds);
17189            }
17190        } else {
17191            mClipBounds = null;
17192        }
17193        mRenderNode.setClipBounds(mClipBounds);
17194        invalidateViewProperty(false, false);
17195    }
17196
17197    /**
17198     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
17199     *
17200     * @return A copy of the current clip bounds if clip bounds are set,
17201     * otherwise null.
17202     */
17203    public Rect getClipBounds() {
17204        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
17205    }
17206
17207
17208    /**
17209     * Populates an output rectangle with the clip bounds of the view,
17210     * returning {@code true} if successful or {@code false} if the view's
17211     * clip bounds are {@code null}.
17212     *
17213     * @param outRect rectangle in which to place the clip bounds of the view
17214     * @return {@code true} if successful or {@code false} if the view's
17215     *         clip bounds are {@code null}
17216     */
17217    public boolean getClipBounds(Rect outRect) {
17218        if (mClipBounds != null) {
17219            outRect.set(mClipBounds);
17220            return true;
17221        }
17222        return false;
17223    }
17224
17225    /**
17226     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
17227     * case of an active Animation being run on the view.
17228     */
17229    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
17230            Animation a, boolean scalingRequired) {
17231        Transformation invalidationTransform;
17232        final int flags = parent.mGroupFlags;
17233        final boolean initialized = a.isInitialized();
17234        if (!initialized) {
17235            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
17236            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
17237            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
17238            onAnimationStart();
17239        }
17240
17241        final Transformation t = parent.getChildTransformation();
17242        boolean more = a.getTransformation(drawingTime, t, 1f);
17243        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
17244            if (parent.mInvalidationTransformation == null) {
17245                parent.mInvalidationTransformation = new Transformation();
17246            }
17247            invalidationTransform = parent.mInvalidationTransformation;
17248            a.getTransformation(drawingTime, invalidationTransform, 1f);
17249        } else {
17250            invalidationTransform = t;
17251        }
17252
17253        if (more) {
17254            if (!a.willChangeBounds()) {
17255                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
17256                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
17257                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
17258                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
17259                    // The child need to draw an animation, potentially offscreen, so
17260                    // make sure we do not cancel invalidate requests
17261                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
17262                    parent.invalidate(mLeft, mTop, mRight, mBottom);
17263                }
17264            } else {
17265                if (parent.mInvalidateRegion == null) {
17266                    parent.mInvalidateRegion = new RectF();
17267                }
17268                final RectF region = parent.mInvalidateRegion;
17269                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
17270                        invalidationTransform);
17271
17272                // The child need to draw an animation, potentially offscreen, so
17273                // make sure we do not cancel invalidate requests
17274                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
17275
17276                final int left = mLeft + (int) region.left;
17277                final int top = mTop + (int) region.top;
17278                parent.invalidate(left, top, left + (int) (region.width() + .5f),
17279                        top + (int) (region.height() + .5f));
17280            }
17281        }
17282        return more;
17283    }
17284
17285    /**
17286     * This method is called by getDisplayList() when a display list is recorded for a View.
17287     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
17288     */
17289    void setDisplayListProperties(RenderNode renderNode) {
17290        if (renderNode != null) {
17291            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
17292            renderNode.setClipToBounds(mParent instanceof ViewGroup
17293                    && ((ViewGroup) mParent).getClipChildren());
17294
17295            float alpha = 1;
17296            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
17297                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
17298                ViewGroup parentVG = (ViewGroup) mParent;
17299                final Transformation t = parentVG.getChildTransformation();
17300                if (parentVG.getChildStaticTransformation(this, t)) {
17301                    final int transformType = t.getTransformationType();
17302                    if (transformType != Transformation.TYPE_IDENTITY) {
17303                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
17304                            alpha = t.getAlpha();
17305                        }
17306                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
17307                            renderNode.setStaticMatrix(t.getMatrix());
17308                        }
17309                    }
17310                }
17311            }
17312            if (mTransformationInfo != null) {
17313                alpha *= getFinalAlpha();
17314                if (alpha < 1) {
17315                    final int multipliedAlpha = (int) (255 * alpha);
17316                    if (onSetAlpha(multipliedAlpha)) {
17317                        alpha = 1;
17318                    }
17319                }
17320                renderNode.setAlpha(alpha);
17321            } else if (alpha < 1) {
17322                renderNode.setAlpha(alpha);
17323            }
17324        }
17325    }
17326
17327    /**
17328     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
17329     *
17330     * This is where the View specializes rendering behavior based on layer type,
17331     * and hardware acceleration.
17332     */
17333    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
17334        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
17335        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
17336         *
17337         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
17338         * HW accelerated, it can't handle drawing RenderNodes.
17339         */
17340        boolean drawingWithRenderNode = mAttachInfo != null
17341                && mAttachInfo.mHardwareAccelerated
17342                && hardwareAcceleratedCanvas;
17343
17344        boolean more = false;
17345        final boolean childHasIdentityMatrix = hasIdentityMatrix();
17346        final int parentFlags = parent.mGroupFlags;
17347
17348        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
17349            parent.getChildTransformation().clear();
17350            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17351        }
17352
17353        Transformation transformToApply = null;
17354        boolean concatMatrix = false;
17355        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
17356        final Animation a = getAnimation();
17357        if (a != null) {
17358            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
17359            concatMatrix = a.willChangeTransformationMatrix();
17360            if (concatMatrix) {
17361                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
17362            }
17363            transformToApply = parent.getChildTransformation();
17364        } else {
17365            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
17366                // No longer animating: clear out old animation matrix
17367                mRenderNode.setAnimationMatrix(null);
17368                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
17369            }
17370            if (!drawingWithRenderNode
17371                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
17372                final Transformation t = parent.getChildTransformation();
17373                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
17374                if (hasTransform) {
17375                    final int transformType = t.getTransformationType();
17376                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
17377                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
17378                }
17379            }
17380        }
17381
17382        concatMatrix |= !childHasIdentityMatrix;
17383
17384        // Sets the flag as early as possible to allow draw() implementations
17385        // to call invalidate() successfully when doing animations
17386        mPrivateFlags |= PFLAG_DRAWN;
17387
17388        if (!concatMatrix &&
17389                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
17390                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
17391                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
17392                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
17393            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
17394            return more;
17395        }
17396        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
17397
17398        if (hardwareAcceleratedCanvas) {
17399            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
17400            // retain the flag's value temporarily in the mRecreateDisplayList flag
17401            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
17402            mPrivateFlags &= ~PFLAG_INVALIDATED;
17403        }
17404
17405        RenderNode renderNode = null;
17406        Bitmap cache = null;
17407        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
17408        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
17409             if (layerType != LAYER_TYPE_NONE) {
17410                 // If not drawing with RenderNode, treat HW layers as SW
17411                 layerType = LAYER_TYPE_SOFTWARE;
17412                 buildDrawingCache(true);
17413            }
17414            cache = getDrawingCache(true);
17415        }
17416
17417        if (drawingWithRenderNode) {
17418            // Delay getting the display list until animation-driven alpha values are
17419            // set up and possibly passed on to the view
17420            renderNode = updateDisplayListIfDirty();
17421            if (!renderNode.isValid()) {
17422                // Uncommon, but possible. If a view is removed from the hierarchy during the call
17423                // to getDisplayList(), the display list will be marked invalid and we should not
17424                // try to use it again.
17425                renderNode = null;
17426                drawingWithRenderNode = false;
17427            }
17428        }
17429
17430        int sx = 0;
17431        int sy = 0;
17432        if (!drawingWithRenderNode) {
17433            computeScroll();
17434            sx = mScrollX;
17435            sy = mScrollY;
17436        }
17437
17438        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
17439        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
17440
17441        int restoreTo = -1;
17442        if (!drawingWithRenderNode || transformToApply != null) {
17443            restoreTo = canvas.save();
17444        }
17445        if (offsetForScroll) {
17446            canvas.translate(mLeft - sx, mTop - sy);
17447        } else {
17448            if (!drawingWithRenderNode) {
17449                canvas.translate(mLeft, mTop);
17450            }
17451            if (scalingRequired) {
17452                if (drawingWithRenderNode) {
17453                    // TODO: Might not need this if we put everything inside the DL
17454                    restoreTo = canvas.save();
17455                }
17456                // mAttachInfo cannot be null, otherwise scalingRequired == false
17457                final float scale = 1.0f / mAttachInfo.mApplicationScale;
17458                canvas.scale(scale, scale);
17459            }
17460        }
17461
17462        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
17463        if (transformToApply != null
17464                || alpha < 1
17465                || !hasIdentityMatrix()
17466                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17467            if (transformToApply != null || !childHasIdentityMatrix) {
17468                int transX = 0;
17469                int transY = 0;
17470
17471                if (offsetForScroll) {
17472                    transX = -sx;
17473                    transY = -sy;
17474                }
17475
17476                if (transformToApply != null) {
17477                    if (concatMatrix) {
17478                        if (drawingWithRenderNode) {
17479                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
17480                        } else {
17481                            // Undo the scroll translation, apply the transformation matrix,
17482                            // then redo the scroll translate to get the correct result.
17483                            canvas.translate(-transX, -transY);
17484                            canvas.concat(transformToApply.getMatrix());
17485                            canvas.translate(transX, transY);
17486                        }
17487                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17488                    }
17489
17490                    float transformAlpha = transformToApply.getAlpha();
17491                    if (transformAlpha < 1) {
17492                        alpha *= transformAlpha;
17493                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17494                    }
17495                }
17496
17497                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
17498                    canvas.translate(-transX, -transY);
17499                    canvas.concat(getMatrix());
17500                    canvas.translate(transX, transY);
17501                }
17502            }
17503
17504            // Deal with alpha if it is or used to be <1
17505            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17506                if (alpha < 1) {
17507                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17508                } else {
17509                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17510                }
17511                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17512                if (!drawingWithDrawingCache) {
17513                    final int multipliedAlpha = (int) (255 * alpha);
17514                    if (!onSetAlpha(multipliedAlpha)) {
17515                        if (drawingWithRenderNode) {
17516                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
17517                        } else if (layerType == LAYER_TYPE_NONE) {
17518                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
17519                                    multipliedAlpha);
17520                        }
17521                    } else {
17522                        // Alpha is handled by the child directly, clobber the layer's alpha
17523                        mPrivateFlags |= PFLAG_ALPHA_SET;
17524                    }
17525                }
17526            }
17527        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17528            onSetAlpha(255);
17529            mPrivateFlags &= ~PFLAG_ALPHA_SET;
17530        }
17531
17532        if (!drawingWithRenderNode) {
17533            // apply clips directly, since RenderNode won't do it for this draw
17534            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
17535                if (offsetForScroll) {
17536                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
17537                } else {
17538                    if (!scalingRequired || cache == null) {
17539                        canvas.clipRect(0, 0, getWidth(), getHeight());
17540                    } else {
17541                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
17542                    }
17543                }
17544            }
17545
17546            if (mClipBounds != null) {
17547                // clip bounds ignore scroll
17548                canvas.clipRect(mClipBounds);
17549            }
17550        }
17551
17552        if (!drawingWithDrawingCache) {
17553            if (drawingWithRenderNode) {
17554                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17555                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17556            } else {
17557                // Fast path for layouts with no backgrounds
17558                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17559                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17560                    dispatchDraw(canvas);
17561                } else {
17562                    draw(canvas);
17563                }
17564            }
17565        } else if (cache != null) {
17566            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17567            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
17568                // no layer paint, use temporary paint to draw bitmap
17569                Paint cachePaint = parent.mCachePaint;
17570                if (cachePaint == null) {
17571                    cachePaint = new Paint();
17572                    cachePaint.setDither(false);
17573                    parent.mCachePaint = cachePaint;
17574                }
17575                cachePaint.setAlpha((int) (alpha * 255));
17576                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
17577            } else {
17578                // use layer paint to draw the bitmap, merging the two alphas, but also restore
17579                int layerPaintAlpha = mLayerPaint.getAlpha();
17580                if (alpha < 1) {
17581                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
17582                }
17583                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
17584                if (alpha < 1) {
17585                    mLayerPaint.setAlpha(layerPaintAlpha);
17586                }
17587            }
17588        }
17589
17590        if (restoreTo >= 0) {
17591            canvas.restoreToCount(restoreTo);
17592        }
17593
17594        if (a != null && !more) {
17595            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
17596                onSetAlpha(255);
17597            }
17598            parent.finishAnimatingView(this, a);
17599        }
17600
17601        if (more && hardwareAcceleratedCanvas) {
17602            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17603                // alpha animations should cause the child to recreate its display list
17604                invalidate(true);
17605            }
17606        }
17607
17608        mRecreateDisplayList = false;
17609
17610        return more;
17611    }
17612
17613    static Paint getDebugPaint() {
17614        if (sDebugPaint == null) {
17615            sDebugPaint = new Paint();
17616            sDebugPaint.setAntiAlias(false);
17617        }
17618        return sDebugPaint;
17619    }
17620
17621    final int dipsToPixels(int dips) {
17622        float scale = getContext().getResources().getDisplayMetrics().density;
17623        return (int) (dips * scale + 0.5f);
17624    }
17625
17626    final private void debugDrawFocus(Canvas canvas) {
17627        if (isFocused()) {
17628            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
17629            final int l = mScrollX;
17630            final int r = l + mRight - mLeft;
17631            final int t = mScrollY;
17632            final int b = t + mBottom - mTop;
17633
17634            final Paint paint = getDebugPaint();
17635            paint.setColor(DEBUG_CORNERS_COLOR);
17636
17637            // Draw squares in corners.
17638            paint.setStyle(Paint.Style.FILL);
17639            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
17640            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
17641            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
17642            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
17643
17644            // Draw big X across the view.
17645            paint.setStyle(Paint.Style.STROKE);
17646            canvas.drawLine(l, t, r, b, paint);
17647            canvas.drawLine(l, b, r, t, paint);
17648        }
17649    }
17650
17651    /**
17652     * Manually render this view (and all of its children) to the given Canvas.
17653     * The view must have already done a full layout before this function is
17654     * called.  When implementing a view, implement
17655     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
17656     * If you do need to override this method, call the superclass version.
17657     *
17658     * @param canvas The Canvas to which the View is rendered.
17659     */
17660    @CallSuper
17661    public void draw(Canvas canvas) {
17662        final int privateFlags = mPrivateFlags;
17663        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
17664                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
17665        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
17666
17667        /*
17668         * Draw traversal performs several drawing steps which must be executed
17669         * in the appropriate order:
17670         *
17671         *      1. Draw the background
17672         *      2. If necessary, save the canvas' layers to prepare for fading
17673         *      3. Draw view's content
17674         *      4. Draw children
17675         *      5. If necessary, draw the fading edges and restore layers
17676         *      6. Draw decorations (scrollbars for instance)
17677         */
17678
17679        // Step 1, draw the background, if needed
17680        int saveCount;
17681
17682        if (!dirtyOpaque) {
17683            drawBackground(canvas);
17684        }
17685
17686        // skip step 2 & 5 if possible (common case)
17687        final int viewFlags = mViewFlags;
17688        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
17689        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
17690        if (!verticalEdges && !horizontalEdges) {
17691            // Step 3, draw the content
17692            if (!dirtyOpaque) onDraw(canvas);
17693
17694            // Step 4, draw the children
17695            dispatchDraw(canvas);
17696
17697            // Overlay is part of the content and draws beneath Foreground
17698            if (mOverlay != null && !mOverlay.isEmpty()) {
17699                mOverlay.getOverlayView().dispatchDraw(canvas);
17700            }
17701
17702            // Step 6, draw decorations (foreground, scrollbars)
17703            onDrawForeground(canvas);
17704
17705            if (debugDraw()) {
17706                debugDrawFocus(canvas);
17707            }
17708
17709            // we're done...
17710            return;
17711        }
17712
17713        /*
17714         * Here we do the full fledged routine...
17715         * (this is an uncommon case where speed matters less,
17716         * this is why we repeat some of the tests that have been
17717         * done above)
17718         */
17719
17720        boolean drawTop = false;
17721        boolean drawBottom = false;
17722        boolean drawLeft = false;
17723        boolean drawRight = false;
17724
17725        float topFadeStrength = 0.0f;
17726        float bottomFadeStrength = 0.0f;
17727        float leftFadeStrength = 0.0f;
17728        float rightFadeStrength = 0.0f;
17729
17730        // Step 2, save the canvas' layers
17731        int paddingLeft = mPaddingLeft;
17732
17733        final boolean offsetRequired = isPaddingOffsetRequired();
17734        if (offsetRequired) {
17735            paddingLeft += getLeftPaddingOffset();
17736        }
17737
17738        int left = mScrollX + paddingLeft;
17739        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
17740        int top = mScrollY + getFadeTop(offsetRequired);
17741        int bottom = top + getFadeHeight(offsetRequired);
17742
17743        if (offsetRequired) {
17744            right += getRightPaddingOffset();
17745            bottom += getBottomPaddingOffset();
17746        }
17747
17748        final ScrollabilityCache scrollabilityCache = mScrollCache;
17749        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
17750        int length = (int) fadeHeight;
17751
17752        // clip the fade length if top and bottom fades overlap
17753        // overlapping fades produce odd-looking artifacts
17754        if (verticalEdges && (top + length > bottom - length)) {
17755            length = (bottom - top) / 2;
17756        }
17757
17758        // also clip horizontal fades if necessary
17759        if (horizontalEdges && (left + length > right - length)) {
17760            length = (right - left) / 2;
17761        }
17762
17763        if (verticalEdges) {
17764            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
17765            drawTop = topFadeStrength * fadeHeight > 1.0f;
17766            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
17767            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
17768        }
17769
17770        if (horizontalEdges) {
17771            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
17772            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
17773            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
17774            drawRight = rightFadeStrength * fadeHeight > 1.0f;
17775        }
17776
17777        saveCount = canvas.getSaveCount();
17778
17779        int solidColor = getSolidColor();
17780        if (solidColor == 0) {
17781            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
17782
17783            if (drawTop) {
17784                canvas.saveLayer(left, top, right, top + length, null, flags);
17785            }
17786
17787            if (drawBottom) {
17788                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
17789            }
17790
17791            if (drawLeft) {
17792                canvas.saveLayer(left, top, left + length, bottom, null, flags);
17793            }
17794
17795            if (drawRight) {
17796                canvas.saveLayer(right - length, top, right, bottom, null, flags);
17797            }
17798        } else {
17799            scrollabilityCache.setFadeColor(solidColor);
17800        }
17801
17802        // Step 3, draw the content
17803        if (!dirtyOpaque) onDraw(canvas);
17804
17805        // Step 4, draw the children
17806        dispatchDraw(canvas);
17807
17808        // Step 5, draw the fade effect and restore layers
17809        final Paint p = scrollabilityCache.paint;
17810        final Matrix matrix = scrollabilityCache.matrix;
17811        final Shader fade = scrollabilityCache.shader;
17812
17813        if (drawTop) {
17814            matrix.setScale(1, fadeHeight * topFadeStrength);
17815            matrix.postTranslate(left, top);
17816            fade.setLocalMatrix(matrix);
17817            p.setShader(fade);
17818            canvas.drawRect(left, top, right, top + length, p);
17819        }
17820
17821        if (drawBottom) {
17822            matrix.setScale(1, fadeHeight * bottomFadeStrength);
17823            matrix.postRotate(180);
17824            matrix.postTranslate(left, bottom);
17825            fade.setLocalMatrix(matrix);
17826            p.setShader(fade);
17827            canvas.drawRect(left, bottom - length, right, bottom, p);
17828        }
17829
17830        if (drawLeft) {
17831            matrix.setScale(1, fadeHeight * leftFadeStrength);
17832            matrix.postRotate(-90);
17833            matrix.postTranslate(left, top);
17834            fade.setLocalMatrix(matrix);
17835            p.setShader(fade);
17836            canvas.drawRect(left, top, left + length, bottom, p);
17837        }
17838
17839        if (drawRight) {
17840            matrix.setScale(1, fadeHeight * rightFadeStrength);
17841            matrix.postRotate(90);
17842            matrix.postTranslate(right, top);
17843            fade.setLocalMatrix(matrix);
17844            p.setShader(fade);
17845            canvas.drawRect(right - length, top, right, bottom, p);
17846        }
17847
17848        canvas.restoreToCount(saveCount);
17849
17850        // Overlay is part of the content and draws beneath Foreground
17851        if (mOverlay != null && !mOverlay.isEmpty()) {
17852            mOverlay.getOverlayView().dispatchDraw(canvas);
17853        }
17854
17855        // Step 6, draw decorations (foreground, scrollbars)
17856        onDrawForeground(canvas);
17857
17858        if (debugDraw()) {
17859            debugDrawFocus(canvas);
17860        }
17861    }
17862
17863    /**
17864     * Draws the background onto the specified canvas.
17865     *
17866     * @param canvas Canvas on which to draw the background
17867     */
17868    private void drawBackground(Canvas canvas) {
17869        final Drawable background = mBackground;
17870        if (background == null) {
17871            return;
17872        }
17873
17874        setBackgroundBounds();
17875
17876        // Attempt to use a display list if requested.
17877        if (canvas.isHardwareAccelerated() && mAttachInfo != null
17878                && mAttachInfo.mThreadedRenderer != null) {
17879            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
17880
17881            final RenderNode renderNode = mBackgroundRenderNode;
17882            if (renderNode != null && renderNode.isValid()) {
17883                setBackgroundRenderNodeProperties(renderNode);
17884                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17885                return;
17886            }
17887        }
17888
17889        final int scrollX = mScrollX;
17890        final int scrollY = mScrollY;
17891        if ((scrollX | scrollY) == 0) {
17892            background.draw(canvas);
17893        } else {
17894            canvas.translate(scrollX, scrollY);
17895            background.draw(canvas);
17896            canvas.translate(-scrollX, -scrollY);
17897        }
17898    }
17899
17900    /**
17901     * Sets the correct background bounds and rebuilds the outline, if needed.
17902     * <p/>
17903     * This is called by LayoutLib.
17904     */
17905    void setBackgroundBounds() {
17906        if (mBackgroundSizeChanged && mBackground != null) {
17907            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
17908            mBackgroundSizeChanged = false;
17909            rebuildOutline();
17910        }
17911    }
17912
17913    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
17914        renderNode.setTranslationX(mScrollX);
17915        renderNode.setTranslationY(mScrollY);
17916    }
17917
17918    /**
17919     * Creates a new display list or updates the existing display list for the
17920     * specified Drawable.
17921     *
17922     * @param drawable Drawable for which to create a display list
17923     * @param renderNode Existing RenderNode, or {@code null}
17924     * @return A valid display list for the specified drawable
17925     */
17926    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
17927        if (renderNode == null) {
17928            renderNode = RenderNode.create(drawable.getClass().getName(), this);
17929        }
17930
17931        final Rect bounds = drawable.getBounds();
17932        final int width = bounds.width();
17933        final int height = bounds.height();
17934        final DisplayListCanvas canvas = renderNode.start(width, height);
17935
17936        // Reverse left/top translation done by drawable canvas, which will
17937        // instead be applied by rendernode's LTRB bounds below. This way, the
17938        // drawable's bounds match with its rendernode bounds and its content
17939        // will lie within those bounds in the rendernode tree.
17940        canvas.translate(-bounds.left, -bounds.top);
17941
17942        try {
17943            drawable.draw(canvas);
17944        } finally {
17945            renderNode.end(canvas);
17946        }
17947
17948        // Set up drawable properties that are view-independent.
17949        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
17950        renderNode.setProjectBackwards(drawable.isProjected());
17951        renderNode.setProjectionReceiver(true);
17952        renderNode.setClipToBounds(false);
17953        return renderNode;
17954    }
17955
17956    /**
17957     * Returns the overlay for this view, creating it if it does not yet exist.
17958     * Adding drawables to the overlay will cause them to be displayed whenever
17959     * the view itself is redrawn. Objects in the overlay should be actively
17960     * managed: remove them when they should not be displayed anymore. The
17961     * overlay will always have the same size as its host view.
17962     *
17963     * <p>Note: Overlays do not currently work correctly with {@link
17964     * SurfaceView} or {@link TextureView}; contents in overlays for these
17965     * types of views may not display correctly.</p>
17966     *
17967     * @return The ViewOverlay object for this view.
17968     * @see ViewOverlay
17969     */
17970    public ViewOverlay getOverlay() {
17971        if (mOverlay == null) {
17972            mOverlay = new ViewOverlay(mContext, this);
17973        }
17974        return mOverlay;
17975    }
17976
17977    /**
17978     * Override this if your view is known to always be drawn on top of a solid color background,
17979     * and needs to draw fading edges. Returning a non-zero color enables the view system to
17980     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
17981     * should be set to 0xFF.
17982     *
17983     * @see #setVerticalFadingEdgeEnabled(boolean)
17984     * @see #setHorizontalFadingEdgeEnabled(boolean)
17985     *
17986     * @return The known solid color background for this view, or 0 if the color may vary
17987     */
17988    @ViewDebug.ExportedProperty(category = "drawing")
17989    @ColorInt
17990    public int getSolidColor() {
17991        return 0;
17992    }
17993
17994    /**
17995     * Build a human readable string representation of the specified view flags.
17996     *
17997     * @param flags the view flags to convert to a string
17998     * @return a String representing the supplied flags
17999     */
18000    private static String printFlags(int flags) {
18001        String output = "";
18002        int numFlags = 0;
18003        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
18004            output += "TAKES_FOCUS";
18005            numFlags++;
18006        }
18007
18008        switch (flags & VISIBILITY_MASK) {
18009        case INVISIBLE:
18010            if (numFlags > 0) {
18011                output += " ";
18012            }
18013            output += "INVISIBLE";
18014            // USELESS HERE numFlags++;
18015            break;
18016        case GONE:
18017            if (numFlags > 0) {
18018                output += " ";
18019            }
18020            output += "GONE";
18021            // USELESS HERE numFlags++;
18022            break;
18023        default:
18024            break;
18025        }
18026        return output;
18027    }
18028
18029    /**
18030     * Build a human readable string representation of the specified private
18031     * view flags.
18032     *
18033     * @param privateFlags the private view flags to convert to a string
18034     * @return a String representing the supplied flags
18035     */
18036    private static String printPrivateFlags(int privateFlags) {
18037        String output = "";
18038        int numFlags = 0;
18039
18040        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
18041            output += "WANTS_FOCUS";
18042            numFlags++;
18043        }
18044
18045        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
18046            if (numFlags > 0) {
18047                output += " ";
18048            }
18049            output += "FOCUSED";
18050            numFlags++;
18051        }
18052
18053        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
18054            if (numFlags > 0) {
18055                output += " ";
18056            }
18057            output += "SELECTED";
18058            numFlags++;
18059        }
18060
18061        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
18062            if (numFlags > 0) {
18063                output += " ";
18064            }
18065            output += "IS_ROOT_NAMESPACE";
18066            numFlags++;
18067        }
18068
18069        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
18070            if (numFlags > 0) {
18071                output += " ";
18072            }
18073            output += "HAS_BOUNDS";
18074            numFlags++;
18075        }
18076
18077        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
18078            if (numFlags > 0) {
18079                output += " ";
18080            }
18081            output += "DRAWN";
18082            // USELESS HERE numFlags++;
18083        }
18084        return output;
18085    }
18086
18087    /**
18088     * <p>Indicates whether or not this view's layout will be requested during
18089     * the next hierarchy layout pass.</p>
18090     *
18091     * @return true if the layout will be forced during next layout pass
18092     */
18093    public boolean isLayoutRequested() {
18094        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
18095    }
18096
18097    /**
18098     * Return true if o is a ViewGroup that is laying out using optical bounds.
18099     * @hide
18100     */
18101    public static boolean isLayoutModeOptical(Object o) {
18102        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
18103    }
18104
18105    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
18106        Insets parentInsets = mParent instanceof View ?
18107                ((View) mParent).getOpticalInsets() : Insets.NONE;
18108        Insets childInsets = getOpticalInsets();
18109        return setFrame(
18110                left   + parentInsets.left - childInsets.left,
18111                top    + parentInsets.top  - childInsets.top,
18112                right  + parentInsets.left + childInsets.right,
18113                bottom + parentInsets.top  + childInsets.bottom);
18114    }
18115
18116    /**
18117     * Assign a size and position to a view and all of its
18118     * descendants
18119     *
18120     * <p>This is the second phase of the layout mechanism.
18121     * (The first is measuring). In this phase, each parent calls
18122     * layout on all of its children to position them.
18123     * This is typically done using the child measurements
18124     * that were stored in the measure pass().</p>
18125     *
18126     * <p>Derived classes should not override this method.
18127     * Derived classes with children should override
18128     * onLayout. In that method, they should
18129     * call layout on each of their children.</p>
18130     *
18131     * @param l Left position, relative to parent
18132     * @param t Top position, relative to parent
18133     * @param r Right position, relative to parent
18134     * @param b Bottom position, relative to parent
18135     */
18136    @SuppressWarnings({"unchecked"})
18137    public void layout(int l, int t, int r, int b) {
18138        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
18139            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
18140            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18141        }
18142
18143        int oldL = mLeft;
18144        int oldT = mTop;
18145        int oldB = mBottom;
18146        int oldR = mRight;
18147
18148        boolean changed = isLayoutModeOptical(mParent) ?
18149                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
18150
18151        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
18152            onLayout(changed, l, t, r, b);
18153
18154            if (shouldDrawRoundScrollbar()) {
18155                if(mRoundScrollbarRenderer == null) {
18156                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
18157                }
18158            } else {
18159                mRoundScrollbarRenderer = null;
18160            }
18161
18162            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
18163
18164            ListenerInfo li = mListenerInfo;
18165            if (li != null && li.mOnLayoutChangeListeners != null) {
18166                ArrayList<OnLayoutChangeListener> listenersCopy =
18167                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
18168                int numListeners = listenersCopy.size();
18169                for (int i = 0; i < numListeners; ++i) {
18170                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
18171                }
18172            }
18173        }
18174
18175        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
18176        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
18177    }
18178
18179    /**
18180     * Called from layout when this view should
18181     * assign a size and position to each of its children.
18182     *
18183     * Derived classes with children should override
18184     * this method and call layout on each of
18185     * their children.
18186     * @param changed This is a new size or position for this view
18187     * @param left Left position, relative to parent
18188     * @param top Top position, relative to parent
18189     * @param right Right position, relative to parent
18190     * @param bottom Bottom position, relative to parent
18191     */
18192    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
18193    }
18194
18195    /**
18196     * Assign a size and position to this view.
18197     *
18198     * This is called from layout.
18199     *
18200     * @param left Left position, relative to parent
18201     * @param top Top position, relative to parent
18202     * @param right Right position, relative to parent
18203     * @param bottom Bottom position, relative to parent
18204     * @return true if the new size and position are different than the
18205     *         previous ones
18206     * {@hide}
18207     */
18208    protected boolean setFrame(int left, int top, int right, int bottom) {
18209        boolean changed = false;
18210
18211        if (DBG) {
18212            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
18213                    + right + "," + bottom + ")");
18214        }
18215
18216        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
18217            changed = true;
18218
18219            // Remember our drawn bit
18220            int drawn = mPrivateFlags & PFLAG_DRAWN;
18221
18222            int oldWidth = mRight - mLeft;
18223            int oldHeight = mBottom - mTop;
18224            int newWidth = right - left;
18225            int newHeight = bottom - top;
18226            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
18227
18228            // Invalidate our old position
18229            invalidate(sizeChanged);
18230
18231            mLeft = left;
18232            mTop = top;
18233            mRight = right;
18234            mBottom = bottom;
18235            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
18236
18237            mPrivateFlags |= PFLAG_HAS_BOUNDS;
18238
18239
18240            if (sizeChanged) {
18241                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
18242            }
18243
18244            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
18245                // If we are visible, force the DRAWN bit to on so that
18246                // this invalidate will go through (at least to our parent).
18247                // This is because someone may have invalidated this view
18248                // before this call to setFrame came in, thereby clearing
18249                // the DRAWN bit.
18250                mPrivateFlags |= PFLAG_DRAWN;
18251                invalidate(sizeChanged);
18252                // parent display list may need to be recreated based on a change in the bounds
18253                // of any child
18254                invalidateParentCaches();
18255            }
18256
18257            // Reset drawn bit to original value (invalidate turns it off)
18258            mPrivateFlags |= drawn;
18259
18260            mBackgroundSizeChanged = true;
18261            if (mForegroundInfo != null) {
18262                mForegroundInfo.mBoundsChanged = true;
18263            }
18264
18265            notifySubtreeAccessibilityStateChangedIfNeeded();
18266        }
18267        return changed;
18268    }
18269
18270    /**
18271     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
18272     * @hide
18273     */
18274    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
18275        setFrame(left, top, right, bottom);
18276    }
18277
18278    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
18279        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
18280        if (mOverlay != null) {
18281            mOverlay.getOverlayView().setRight(newWidth);
18282            mOverlay.getOverlayView().setBottom(newHeight);
18283        }
18284        rebuildOutline();
18285    }
18286
18287    /**
18288     * Finalize inflating a view from XML.  This is called as the last phase
18289     * of inflation, after all child views have been added.
18290     *
18291     * <p>Even if the subclass overrides onFinishInflate, they should always be
18292     * sure to call the super method, so that we get called.
18293     */
18294    @CallSuper
18295    protected void onFinishInflate() {
18296    }
18297
18298    /**
18299     * Returns the resources associated with this view.
18300     *
18301     * @return Resources object.
18302     */
18303    public Resources getResources() {
18304        return mResources;
18305    }
18306
18307    /**
18308     * Invalidates the specified Drawable.
18309     *
18310     * @param drawable the drawable to invalidate
18311     */
18312    @Override
18313    public void invalidateDrawable(@NonNull Drawable drawable) {
18314        if (verifyDrawable(drawable)) {
18315            final Rect dirty = drawable.getDirtyBounds();
18316            final int scrollX = mScrollX;
18317            final int scrollY = mScrollY;
18318
18319            invalidate(dirty.left + scrollX, dirty.top + scrollY,
18320                    dirty.right + scrollX, dirty.bottom + scrollY);
18321            rebuildOutline();
18322        }
18323    }
18324
18325    /**
18326     * Schedules an action on a drawable to occur at a specified time.
18327     *
18328     * @param who the recipient of the action
18329     * @param what the action to run on the drawable
18330     * @param when the time at which the action must occur. Uses the
18331     *        {@link SystemClock#uptimeMillis} timebase.
18332     */
18333    @Override
18334    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
18335        if (verifyDrawable(who) && what != null) {
18336            final long delay = when - SystemClock.uptimeMillis();
18337            if (mAttachInfo != null) {
18338                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
18339                        Choreographer.CALLBACK_ANIMATION, what, who,
18340                        Choreographer.subtractFrameDelay(delay));
18341            } else {
18342                // Postpone the runnable until we know
18343                // on which thread it needs to run.
18344                getRunQueue().postDelayed(what, delay);
18345            }
18346        }
18347    }
18348
18349    /**
18350     * Cancels a scheduled action on a drawable.
18351     *
18352     * @param who the recipient of the action
18353     * @param what the action to cancel
18354     */
18355    @Override
18356    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
18357        if (verifyDrawable(who) && what != null) {
18358            if (mAttachInfo != null) {
18359                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
18360                        Choreographer.CALLBACK_ANIMATION, what, who);
18361            }
18362            getRunQueue().removeCallbacks(what);
18363        }
18364    }
18365
18366    /**
18367     * Unschedule any events associated with the given Drawable.  This can be
18368     * used when selecting a new Drawable into a view, so that the previous
18369     * one is completely unscheduled.
18370     *
18371     * @param who The Drawable to unschedule.
18372     *
18373     * @see #drawableStateChanged
18374     */
18375    public void unscheduleDrawable(Drawable who) {
18376        if (mAttachInfo != null && who != null) {
18377            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
18378                    Choreographer.CALLBACK_ANIMATION, null, who);
18379        }
18380    }
18381
18382    /**
18383     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
18384     * that the View directionality can and will be resolved before its Drawables.
18385     *
18386     * Will call {@link View#onResolveDrawables} when resolution is done.
18387     *
18388     * @hide
18389     */
18390    protected void resolveDrawables() {
18391        // Drawables resolution may need to happen before resolving the layout direction (which is
18392        // done only during the measure() call).
18393        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
18394        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
18395        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
18396        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
18397        // direction to be resolved as its resolved value will be the same as its raw value.
18398        if (!isLayoutDirectionResolved() &&
18399                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
18400            return;
18401        }
18402
18403        final int layoutDirection = isLayoutDirectionResolved() ?
18404                getLayoutDirection() : getRawLayoutDirection();
18405
18406        if (mBackground != null) {
18407            mBackground.setLayoutDirection(layoutDirection);
18408        }
18409        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18410            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
18411        }
18412        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
18413        onResolveDrawables(layoutDirection);
18414    }
18415
18416    boolean areDrawablesResolved() {
18417        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
18418    }
18419
18420    /**
18421     * Called when layout direction has been resolved.
18422     *
18423     * The default implementation does nothing.
18424     *
18425     * @param layoutDirection The resolved layout direction.
18426     *
18427     * @see #LAYOUT_DIRECTION_LTR
18428     * @see #LAYOUT_DIRECTION_RTL
18429     *
18430     * @hide
18431     */
18432    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
18433    }
18434
18435    /**
18436     * @hide
18437     */
18438    protected void resetResolvedDrawables() {
18439        resetResolvedDrawablesInternal();
18440    }
18441
18442    void resetResolvedDrawablesInternal() {
18443        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
18444    }
18445
18446    /**
18447     * If your view subclass is displaying its own Drawable objects, it should
18448     * override this function and return true for any Drawable it is
18449     * displaying.  This allows animations for those drawables to be
18450     * scheduled.
18451     *
18452     * <p>Be sure to call through to the super class when overriding this
18453     * function.
18454     *
18455     * @param who The Drawable to verify.  Return true if it is one you are
18456     *            displaying, else return the result of calling through to the
18457     *            super class.
18458     *
18459     * @return boolean If true than the Drawable is being displayed in the
18460     *         view; else false and it is not allowed to animate.
18461     *
18462     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
18463     * @see #drawableStateChanged()
18464     */
18465    @CallSuper
18466    protected boolean verifyDrawable(@NonNull Drawable who) {
18467        // Avoid verifying the scroll bar drawable so that we don't end up in
18468        // an invalidation loop. This effectively prevents the scroll bar
18469        // drawable from triggering invalidations and scheduling runnables.
18470        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
18471    }
18472
18473    /**
18474     * This function is called whenever the state of the view changes in such
18475     * a way that it impacts the state of drawables being shown.
18476     * <p>
18477     * If the View has a StateListAnimator, it will also be called to run necessary state
18478     * change animations.
18479     * <p>
18480     * Be sure to call through to the superclass when overriding this function.
18481     *
18482     * @see Drawable#setState(int[])
18483     */
18484    @CallSuper
18485    protected void drawableStateChanged() {
18486        final int[] state = getDrawableState();
18487        boolean changed = false;
18488
18489        final Drawable bg = mBackground;
18490        if (bg != null && bg.isStateful()) {
18491            changed |= bg.setState(state);
18492        }
18493
18494        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18495        if (fg != null && fg.isStateful()) {
18496            changed |= fg.setState(state);
18497        }
18498
18499        if (mScrollCache != null) {
18500            final Drawable scrollBar = mScrollCache.scrollBar;
18501            if (scrollBar != null && scrollBar.isStateful()) {
18502                changed |= scrollBar.setState(state)
18503                        && mScrollCache.state != ScrollabilityCache.OFF;
18504            }
18505        }
18506
18507        if (mStateListAnimator != null) {
18508            mStateListAnimator.setState(state);
18509        }
18510
18511        if (changed) {
18512            invalidate();
18513        }
18514    }
18515
18516    /**
18517     * This function is called whenever the view hotspot changes and needs to
18518     * be propagated to drawables or child views managed by the view.
18519     * <p>
18520     * Dispatching to child views is handled by
18521     * {@link #dispatchDrawableHotspotChanged(float, float)}.
18522     * <p>
18523     * Be sure to call through to the superclass when overriding this function.
18524     *
18525     * @param x hotspot x coordinate
18526     * @param y hotspot y coordinate
18527     */
18528    @CallSuper
18529    public void drawableHotspotChanged(float x, float y) {
18530        if (mBackground != null) {
18531            mBackground.setHotspot(x, y);
18532        }
18533        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18534            mForegroundInfo.mDrawable.setHotspot(x, y);
18535        }
18536
18537        dispatchDrawableHotspotChanged(x, y);
18538    }
18539
18540    /**
18541     * Dispatches drawableHotspotChanged to all of this View's children.
18542     *
18543     * @param x hotspot x coordinate
18544     * @param y hotspot y coordinate
18545     * @see #drawableHotspotChanged(float, float)
18546     */
18547    public void dispatchDrawableHotspotChanged(float x, float y) {
18548    }
18549
18550    /**
18551     * Call this to force a view to update its drawable state. This will cause
18552     * drawableStateChanged to be called on this view. Views that are interested
18553     * in the new state should call getDrawableState.
18554     *
18555     * @see #drawableStateChanged
18556     * @see #getDrawableState
18557     */
18558    public void refreshDrawableState() {
18559        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
18560        drawableStateChanged();
18561
18562        ViewParent parent = mParent;
18563        if (parent != null) {
18564            parent.childDrawableStateChanged(this);
18565        }
18566    }
18567
18568    /**
18569     * Return an array of resource IDs of the drawable states representing the
18570     * current state of the view.
18571     *
18572     * @return The current drawable state
18573     *
18574     * @see Drawable#setState(int[])
18575     * @see #drawableStateChanged()
18576     * @see #onCreateDrawableState(int)
18577     */
18578    public final int[] getDrawableState() {
18579        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
18580            return mDrawableState;
18581        } else {
18582            mDrawableState = onCreateDrawableState(0);
18583            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
18584            return mDrawableState;
18585        }
18586    }
18587
18588    /**
18589     * Generate the new {@link android.graphics.drawable.Drawable} state for
18590     * this view. This is called by the view
18591     * system when the cached Drawable state is determined to be invalid.  To
18592     * retrieve the current state, you should use {@link #getDrawableState}.
18593     *
18594     * @param extraSpace if non-zero, this is the number of extra entries you
18595     * would like in the returned array in which you can place your own
18596     * states.
18597     *
18598     * @return Returns an array holding the current {@link Drawable} state of
18599     * the view.
18600     *
18601     * @see #mergeDrawableStates(int[], int[])
18602     */
18603    protected int[] onCreateDrawableState(int extraSpace) {
18604        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
18605                mParent instanceof View) {
18606            return ((View) mParent).onCreateDrawableState(extraSpace);
18607        }
18608
18609        int[] drawableState;
18610
18611        int privateFlags = mPrivateFlags;
18612
18613        int viewStateIndex = 0;
18614        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
18615        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
18616        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
18617        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
18618        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
18619        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
18620        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
18621                ThreadedRenderer.isAvailable()) {
18622            // This is set if HW acceleration is requested, even if the current
18623            // process doesn't allow it.  This is just to allow app preview
18624            // windows to better match their app.
18625            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
18626        }
18627        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
18628
18629        final int privateFlags2 = mPrivateFlags2;
18630        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
18631            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
18632        }
18633        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
18634            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
18635        }
18636
18637        drawableState = StateSet.get(viewStateIndex);
18638
18639        //noinspection ConstantIfStatement
18640        if (false) {
18641            Log.i("View", "drawableStateIndex=" + viewStateIndex);
18642            Log.i("View", toString()
18643                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
18644                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
18645                    + " fo=" + hasFocus()
18646                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
18647                    + " wf=" + hasWindowFocus()
18648                    + ": " + Arrays.toString(drawableState));
18649        }
18650
18651        if (extraSpace == 0) {
18652            return drawableState;
18653        }
18654
18655        final int[] fullState;
18656        if (drawableState != null) {
18657            fullState = new int[drawableState.length + extraSpace];
18658            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
18659        } else {
18660            fullState = new int[extraSpace];
18661        }
18662
18663        return fullState;
18664    }
18665
18666    /**
18667     * Merge your own state values in <var>additionalState</var> into the base
18668     * state values <var>baseState</var> that were returned by
18669     * {@link #onCreateDrawableState(int)}.
18670     *
18671     * @param baseState The base state values returned by
18672     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
18673     * own additional state values.
18674     *
18675     * @param additionalState The additional state values you would like
18676     * added to <var>baseState</var>; this array is not modified.
18677     *
18678     * @return As a convenience, the <var>baseState</var> array you originally
18679     * passed into the function is returned.
18680     *
18681     * @see #onCreateDrawableState(int)
18682     */
18683    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
18684        final int N = baseState.length;
18685        int i = N - 1;
18686        while (i >= 0 && baseState[i] == 0) {
18687            i--;
18688        }
18689        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
18690        return baseState;
18691    }
18692
18693    /**
18694     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
18695     * on all Drawable objects associated with this view.
18696     * <p>
18697     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
18698     * attached to this view.
18699     */
18700    @CallSuper
18701    public void jumpDrawablesToCurrentState() {
18702        if (mBackground != null) {
18703            mBackground.jumpToCurrentState();
18704        }
18705        if (mStateListAnimator != null) {
18706            mStateListAnimator.jumpToCurrentState();
18707        }
18708        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18709            mForegroundInfo.mDrawable.jumpToCurrentState();
18710        }
18711    }
18712
18713    /**
18714     * Sets the background color for this view.
18715     * @param color the color of the background
18716     */
18717    @RemotableViewMethod
18718    public void setBackgroundColor(@ColorInt int color) {
18719        if (mBackground instanceof ColorDrawable) {
18720            ((ColorDrawable) mBackground.mutate()).setColor(color);
18721            computeOpaqueFlags();
18722            mBackgroundResource = 0;
18723        } else {
18724            setBackground(new ColorDrawable(color));
18725        }
18726    }
18727
18728    /**
18729     * Set the background to a given resource. The resource should refer to
18730     * a Drawable object or 0 to remove the background.
18731     * @param resid The identifier of the resource.
18732     *
18733     * @attr ref android.R.styleable#View_background
18734     */
18735    @RemotableViewMethod
18736    public void setBackgroundResource(@DrawableRes int resid) {
18737        if (resid != 0 && resid == mBackgroundResource) {
18738            return;
18739        }
18740
18741        Drawable d = null;
18742        if (resid != 0) {
18743            d = mContext.getDrawable(resid);
18744        }
18745        setBackground(d);
18746
18747        mBackgroundResource = resid;
18748    }
18749
18750    /**
18751     * Set the background to a given Drawable, or remove the background. If the
18752     * background has padding, this View's padding is set to the background's
18753     * padding. However, when a background is removed, this View's padding isn't
18754     * touched. If setting the padding is desired, please use
18755     * {@link #setPadding(int, int, int, int)}.
18756     *
18757     * @param background The Drawable to use as the background, or null to remove the
18758     *        background
18759     */
18760    public void setBackground(Drawable background) {
18761        //noinspection deprecation
18762        setBackgroundDrawable(background);
18763    }
18764
18765    /**
18766     * @deprecated use {@link #setBackground(Drawable)} instead
18767     */
18768    @Deprecated
18769    public void setBackgroundDrawable(Drawable background) {
18770        computeOpaqueFlags();
18771
18772        if (background == mBackground) {
18773            return;
18774        }
18775
18776        boolean requestLayout = false;
18777
18778        mBackgroundResource = 0;
18779
18780        /*
18781         * Regardless of whether we're setting a new background or not, we want
18782         * to clear the previous drawable. setVisible first while we still have the callback set.
18783         */
18784        if (mBackground != null) {
18785            if (isAttachedToWindow()) {
18786                mBackground.setVisible(false, false);
18787            }
18788            mBackground.setCallback(null);
18789            unscheduleDrawable(mBackground);
18790        }
18791
18792        if (background != null) {
18793            Rect padding = sThreadLocal.get();
18794            if (padding == null) {
18795                padding = new Rect();
18796                sThreadLocal.set(padding);
18797            }
18798            resetResolvedDrawablesInternal();
18799            background.setLayoutDirection(getLayoutDirection());
18800            if (background.getPadding(padding)) {
18801                resetResolvedPaddingInternal();
18802                switch (background.getLayoutDirection()) {
18803                    case LAYOUT_DIRECTION_RTL:
18804                        mUserPaddingLeftInitial = padding.right;
18805                        mUserPaddingRightInitial = padding.left;
18806                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
18807                        break;
18808                    case LAYOUT_DIRECTION_LTR:
18809                    default:
18810                        mUserPaddingLeftInitial = padding.left;
18811                        mUserPaddingRightInitial = padding.right;
18812                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
18813                }
18814                mLeftPaddingDefined = false;
18815                mRightPaddingDefined = false;
18816            }
18817
18818            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
18819            // if it has a different minimum size, we should layout again
18820            if (mBackground == null
18821                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
18822                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
18823                requestLayout = true;
18824            }
18825
18826            // Set mBackground before we set this as the callback and start making other
18827            // background drawable state change calls. In particular, the setVisible call below
18828            // can result in drawables attempting to start animations or otherwise invalidate,
18829            // which requires the view set as the callback (us) to recognize the drawable as
18830            // belonging to it as per verifyDrawable.
18831            mBackground = background;
18832            if (background.isStateful()) {
18833                background.setState(getDrawableState());
18834            }
18835            if (isAttachedToWindow()) {
18836                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18837            }
18838
18839            applyBackgroundTint();
18840
18841            // Set callback last, since the view may still be initializing.
18842            background.setCallback(this);
18843
18844            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18845                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18846                requestLayout = true;
18847            }
18848        } else {
18849            /* Remove the background */
18850            mBackground = null;
18851            if ((mViewFlags & WILL_NOT_DRAW) != 0
18852                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
18853                mPrivateFlags |= PFLAG_SKIP_DRAW;
18854            }
18855
18856            /*
18857             * When the background is set, we try to apply its padding to this
18858             * View. When the background is removed, we don't touch this View's
18859             * padding. This is noted in the Javadocs. Hence, we don't need to
18860             * requestLayout(), the invalidate() below is sufficient.
18861             */
18862
18863            // The old background's minimum size could have affected this
18864            // View's layout, so let's requestLayout
18865            requestLayout = true;
18866        }
18867
18868        computeOpaqueFlags();
18869
18870        if (requestLayout) {
18871            requestLayout();
18872        }
18873
18874        mBackgroundSizeChanged = true;
18875        invalidate(true);
18876        invalidateOutline();
18877    }
18878
18879    /**
18880     * Gets the background drawable
18881     *
18882     * @return The drawable used as the background for this view, if any.
18883     *
18884     * @see #setBackground(Drawable)
18885     *
18886     * @attr ref android.R.styleable#View_background
18887     */
18888    public Drawable getBackground() {
18889        return mBackground;
18890    }
18891
18892    /**
18893     * Applies a tint to the background drawable. Does not modify the current tint
18894     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18895     * <p>
18896     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
18897     * mutate the drawable and apply the specified tint and tint mode using
18898     * {@link Drawable#setTintList(ColorStateList)}.
18899     *
18900     * @param tint the tint to apply, may be {@code null} to clear tint
18901     *
18902     * @attr ref android.R.styleable#View_backgroundTint
18903     * @see #getBackgroundTintList()
18904     * @see Drawable#setTintList(ColorStateList)
18905     */
18906    public void setBackgroundTintList(@Nullable ColorStateList tint) {
18907        if (mBackgroundTint == null) {
18908            mBackgroundTint = new TintInfo();
18909        }
18910        mBackgroundTint.mTintList = tint;
18911        mBackgroundTint.mHasTintList = true;
18912
18913        applyBackgroundTint();
18914    }
18915
18916    /**
18917     * Return the tint applied to the background drawable, if specified.
18918     *
18919     * @return the tint applied to the background drawable
18920     * @attr ref android.R.styleable#View_backgroundTint
18921     * @see #setBackgroundTintList(ColorStateList)
18922     */
18923    @Nullable
18924    public ColorStateList getBackgroundTintList() {
18925        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
18926    }
18927
18928    /**
18929     * Specifies the blending mode used to apply the tint specified by
18930     * {@link #setBackgroundTintList(ColorStateList)}} to the background
18931     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18932     *
18933     * @param tintMode the blending mode used to apply the tint, may be
18934     *                 {@code null} to clear tint
18935     * @attr ref android.R.styleable#View_backgroundTintMode
18936     * @see #getBackgroundTintMode()
18937     * @see Drawable#setTintMode(PorterDuff.Mode)
18938     */
18939    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18940        if (mBackgroundTint == null) {
18941            mBackgroundTint = new TintInfo();
18942        }
18943        mBackgroundTint.mTintMode = tintMode;
18944        mBackgroundTint.mHasTintMode = true;
18945
18946        applyBackgroundTint();
18947    }
18948
18949    /**
18950     * Return the blending mode used to apply the tint to the background
18951     * drawable, if specified.
18952     *
18953     * @return the blending mode used to apply the tint to the background
18954     *         drawable
18955     * @attr ref android.R.styleable#View_backgroundTintMode
18956     * @see #setBackgroundTintMode(PorterDuff.Mode)
18957     */
18958    @Nullable
18959    public PorterDuff.Mode getBackgroundTintMode() {
18960        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
18961    }
18962
18963    private void applyBackgroundTint() {
18964        if (mBackground != null && mBackgroundTint != null) {
18965            final TintInfo tintInfo = mBackgroundTint;
18966            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18967                mBackground = mBackground.mutate();
18968
18969                if (tintInfo.mHasTintList) {
18970                    mBackground.setTintList(tintInfo.mTintList);
18971                }
18972
18973                if (tintInfo.mHasTintMode) {
18974                    mBackground.setTintMode(tintInfo.mTintMode);
18975                }
18976
18977                // The drawable (or one of its children) may not have been
18978                // stateful before applying the tint, so let's try again.
18979                if (mBackground.isStateful()) {
18980                    mBackground.setState(getDrawableState());
18981                }
18982            }
18983        }
18984    }
18985
18986    /**
18987     * Returns the drawable used as the foreground of this View. The
18988     * foreground drawable, if non-null, is always drawn on top of the view's content.
18989     *
18990     * @return a Drawable or null if no foreground was set
18991     *
18992     * @see #onDrawForeground(Canvas)
18993     */
18994    public Drawable getForeground() {
18995        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18996    }
18997
18998    /**
18999     * Supply a Drawable that is to be rendered on top of all of the content in the view.
19000     *
19001     * @param foreground the Drawable to be drawn on top of the children
19002     *
19003     * @attr ref android.R.styleable#View_foreground
19004     */
19005    public void setForeground(Drawable foreground) {
19006        if (mForegroundInfo == null) {
19007            if (foreground == null) {
19008                // Nothing to do.
19009                return;
19010            }
19011            mForegroundInfo = new ForegroundInfo();
19012        }
19013
19014        if (foreground == mForegroundInfo.mDrawable) {
19015            // Nothing to do
19016            return;
19017        }
19018
19019        if (mForegroundInfo.mDrawable != null) {
19020            if (isAttachedToWindow()) {
19021                mForegroundInfo.mDrawable.setVisible(false, false);
19022            }
19023            mForegroundInfo.mDrawable.setCallback(null);
19024            unscheduleDrawable(mForegroundInfo.mDrawable);
19025        }
19026
19027        mForegroundInfo.mDrawable = foreground;
19028        mForegroundInfo.mBoundsChanged = true;
19029        if (foreground != null) {
19030            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19031                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19032            }
19033            foreground.setLayoutDirection(getLayoutDirection());
19034            if (foreground.isStateful()) {
19035                foreground.setState(getDrawableState());
19036            }
19037            applyForegroundTint();
19038            if (isAttachedToWindow()) {
19039                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19040            }
19041            // Set callback last, since the view may still be initializing.
19042            foreground.setCallback(this);
19043        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
19044            mPrivateFlags |= PFLAG_SKIP_DRAW;
19045        }
19046        requestLayout();
19047        invalidate();
19048    }
19049
19050    /**
19051     * Magic bit used to support features of framework-internal window decor implementation details.
19052     * This used to live exclusively in FrameLayout.
19053     *
19054     * @return true if the foreground should draw inside the padding region or false
19055     *         if it should draw inset by the view's padding
19056     * @hide internal use only; only used by FrameLayout and internal screen layouts.
19057     */
19058    public boolean isForegroundInsidePadding() {
19059        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
19060    }
19061
19062    /**
19063     * Describes how the foreground is positioned.
19064     *
19065     * @return foreground gravity.
19066     *
19067     * @see #setForegroundGravity(int)
19068     *
19069     * @attr ref android.R.styleable#View_foregroundGravity
19070     */
19071    public int getForegroundGravity() {
19072        return mForegroundInfo != null ? mForegroundInfo.mGravity
19073                : Gravity.START | Gravity.TOP;
19074    }
19075
19076    /**
19077     * Describes how the foreground is positioned. Defaults to START and TOP.
19078     *
19079     * @param gravity see {@link android.view.Gravity}
19080     *
19081     * @see #getForegroundGravity()
19082     *
19083     * @attr ref android.R.styleable#View_foregroundGravity
19084     */
19085    public void setForegroundGravity(int gravity) {
19086        if (mForegroundInfo == null) {
19087            mForegroundInfo = new ForegroundInfo();
19088        }
19089
19090        if (mForegroundInfo.mGravity != gravity) {
19091            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
19092                gravity |= Gravity.START;
19093            }
19094
19095            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
19096                gravity |= Gravity.TOP;
19097            }
19098
19099            mForegroundInfo.mGravity = gravity;
19100            requestLayout();
19101        }
19102    }
19103
19104    /**
19105     * Applies a tint to the foreground drawable. Does not modify the current tint
19106     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
19107     * <p>
19108     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
19109     * mutate the drawable and apply the specified tint and tint mode using
19110     * {@link Drawable#setTintList(ColorStateList)}.
19111     *
19112     * @param tint the tint to apply, may be {@code null} to clear tint
19113     *
19114     * @attr ref android.R.styleable#View_foregroundTint
19115     * @see #getForegroundTintList()
19116     * @see Drawable#setTintList(ColorStateList)
19117     */
19118    public void setForegroundTintList(@Nullable ColorStateList tint) {
19119        if (mForegroundInfo == null) {
19120            mForegroundInfo = new ForegroundInfo();
19121        }
19122        if (mForegroundInfo.mTintInfo == null) {
19123            mForegroundInfo.mTintInfo = new TintInfo();
19124        }
19125        mForegroundInfo.mTintInfo.mTintList = tint;
19126        mForegroundInfo.mTintInfo.mHasTintList = true;
19127
19128        applyForegroundTint();
19129    }
19130
19131    /**
19132     * Return the tint applied to the foreground drawable, if specified.
19133     *
19134     * @return the tint applied to the foreground drawable
19135     * @attr ref android.R.styleable#View_foregroundTint
19136     * @see #setForegroundTintList(ColorStateList)
19137     */
19138    @Nullable
19139    public ColorStateList getForegroundTintList() {
19140        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
19141                ? mForegroundInfo.mTintInfo.mTintList : null;
19142    }
19143
19144    /**
19145     * Specifies the blending mode used to apply the tint specified by
19146     * {@link #setForegroundTintList(ColorStateList)}} to the background
19147     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
19148     *
19149     * @param tintMode the blending mode used to apply the tint, may be
19150     *                 {@code null} to clear tint
19151     * @attr ref android.R.styleable#View_foregroundTintMode
19152     * @see #getForegroundTintMode()
19153     * @see Drawable#setTintMode(PorterDuff.Mode)
19154     */
19155    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
19156        if (mForegroundInfo == null) {
19157            mForegroundInfo = new ForegroundInfo();
19158        }
19159        if (mForegroundInfo.mTintInfo == null) {
19160            mForegroundInfo.mTintInfo = new TintInfo();
19161        }
19162        mForegroundInfo.mTintInfo.mTintMode = tintMode;
19163        mForegroundInfo.mTintInfo.mHasTintMode = true;
19164
19165        applyForegroundTint();
19166    }
19167
19168    /**
19169     * Return the blending mode used to apply the tint to the foreground
19170     * drawable, if specified.
19171     *
19172     * @return the blending mode used to apply the tint to the foreground
19173     *         drawable
19174     * @attr ref android.R.styleable#View_foregroundTintMode
19175     * @see #setForegroundTintMode(PorterDuff.Mode)
19176     */
19177    @Nullable
19178    public PorterDuff.Mode getForegroundTintMode() {
19179        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
19180                ? mForegroundInfo.mTintInfo.mTintMode : null;
19181    }
19182
19183    private void applyForegroundTint() {
19184        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19185                && mForegroundInfo.mTintInfo != null) {
19186            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
19187            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
19188                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
19189
19190                if (tintInfo.mHasTintList) {
19191                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
19192                }
19193
19194                if (tintInfo.mHasTintMode) {
19195                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
19196                }
19197
19198                // The drawable (or one of its children) may not have been
19199                // stateful before applying the tint, so let's try again.
19200                if (mForegroundInfo.mDrawable.isStateful()) {
19201                    mForegroundInfo.mDrawable.setState(getDrawableState());
19202                }
19203            }
19204        }
19205    }
19206
19207    /**
19208     * Draw any foreground content for this view.
19209     *
19210     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
19211     * drawable or other view-specific decorations. The foreground is drawn on top of the
19212     * primary view content.</p>
19213     *
19214     * @param canvas canvas to draw into
19215     */
19216    public void onDrawForeground(Canvas canvas) {
19217        onDrawScrollIndicators(canvas);
19218        onDrawScrollBars(canvas);
19219
19220        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19221        if (foreground != null) {
19222            if (mForegroundInfo.mBoundsChanged) {
19223                mForegroundInfo.mBoundsChanged = false;
19224                final Rect selfBounds = mForegroundInfo.mSelfBounds;
19225                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
19226
19227                if (mForegroundInfo.mInsidePadding) {
19228                    selfBounds.set(0, 0, getWidth(), getHeight());
19229                } else {
19230                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
19231                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
19232                }
19233
19234                final int ld = getLayoutDirection();
19235                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
19236                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
19237                foreground.setBounds(overlayBounds);
19238            }
19239
19240            foreground.draw(canvas);
19241        }
19242    }
19243
19244    /**
19245     * Sets the padding. The view may add on the space required to display
19246     * the scrollbars, depending on the style and visibility of the scrollbars.
19247     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
19248     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
19249     * from the values set in this call.
19250     *
19251     * @attr ref android.R.styleable#View_padding
19252     * @attr ref android.R.styleable#View_paddingBottom
19253     * @attr ref android.R.styleable#View_paddingLeft
19254     * @attr ref android.R.styleable#View_paddingRight
19255     * @attr ref android.R.styleable#View_paddingTop
19256     * @param left the left padding in pixels
19257     * @param top the top padding in pixels
19258     * @param right the right padding in pixels
19259     * @param bottom the bottom padding in pixels
19260     */
19261    public void setPadding(int left, int top, int right, int bottom) {
19262        resetResolvedPaddingInternal();
19263
19264        mUserPaddingStart = UNDEFINED_PADDING;
19265        mUserPaddingEnd = UNDEFINED_PADDING;
19266
19267        mUserPaddingLeftInitial = left;
19268        mUserPaddingRightInitial = right;
19269
19270        mLeftPaddingDefined = true;
19271        mRightPaddingDefined = true;
19272
19273        internalSetPadding(left, top, right, bottom);
19274    }
19275
19276    /**
19277     * @hide
19278     */
19279    protected void internalSetPadding(int left, int top, int right, int bottom) {
19280        mUserPaddingLeft = left;
19281        mUserPaddingRight = right;
19282        mUserPaddingBottom = bottom;
19283
19284        final int viewFlags = mViewFlags;
19285        boolean changed = false;
19286
19287        // Common case is there are no scroll bars.
19288        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
19289            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
19290                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
19291                        ? 0 : getVerticalScrollbarWidth();
19292                switch (mVerticalScrollbarPosition) {
19293                    case SCROLLBAR_POSITION_DEFAULT:
19294                        if (isLayoutRtl()) {
19295                            left += offset;
19296                        } else {
19297                            right += offset;
19298                        }
19299                        break;
19300                    case SCROLLBAR_POSITION_RIGHT:
19301                        right += offset;
19302                        break;
19303                    case SCROLLBAR_POSITION_LEFT:
19304                        left += offset;
19305                        break;
19306                }
19307            }
19308            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
19309                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
19310                        ? 0 : getHorizontalScrollbarHeight();
19311            }
19312        }
19313
19314        if (mPaddingLeft != left) {
19315            changed = true;
19316            mPaddingLeft = left;
19317        }
19318        if (mPaddingTop != top) {
19319            changed = true;
19320            mPaddingTop = top;
19321        }
19322        if (mPaddingRight != right) {
19323            changed = true;
19324            mPaddingRight = right;
19325        }
19326        if (mPaddingBottom != bottom) {
19327            changed = true;
19328            mPaddingBottom = bottom;
19329        }
19330
19331        if (changed) {
19332            requestLayout();
19333            invalidateOutline();
19334        }
19335    }
19336
19337    /**
19338     * Sets the relative padding. The view may add on the space required to display
19339     * the scrollbars, depending on the style and visibility of the scrollbars.
19340     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
19341     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
19342     * from the values set in this call.
19343     *
19344     * @attr ref android.R.styleable#View_padding
19345     * @attr ref android.R.styleable#View_paddingBottom
19346     * @attr ref android.R.styleable#View_paddingStart
19347     * @attr ref android.R.styleable#View_paddingEnd
19348     * @attr ref android.R.styleable#View_paddingTop
19349     * @param start the start padding in pixels
19350     * @param top the top padding in pixels
19351     * @param end the end padding in pixels
19352     * @param bottom the bottom padding in pixels
19353     */
19354    public void setPaddingRelative(int start, int top, int end, int bottom) {
19355        resetResolvedPaddingInternal();
19356
19357        mUserPaddingStart = start;
19358        mUserPaddingEnd = end;
19359        mLeftPaddingDefined = true;
19360        mRightPaddingDefined = true;
19361
19362        switch(getLayoutDirection()) {
19363            case LAYOUT_DIRECTION_RTL:
19364                mUserPaddingLeftInitial = end;
19365                mUserPaddingRightInitial = start;
19366                internalSetPadding(end, top, start, bottom);
19367                break;
19368            case LAYOUT_DIRECTION_LTR:
19369            default:
19370                mUserPaddingLeftInitial = start;
19371                mUserPaddingRightInitial = end;
19372                internalSetPadding(start, top, end, bottom);
19373        }
19374    }
19375
19376    /**
19377     * Returns the top padding of this view.
19378     *
19379     * @return the top padding in pixels
19380     */
19381    public int getPaddingTop() {
19382        return mPaddingTop;
19383    }
19384
19385    /**
19386     * Returns the bottom padding of this view. If there are inset and enabled
19387     * scrollbars, this value may include the space required to display the
19388     * scrollbars as well.
19389     *
19390     * @return the bottom padding in pixels
19391     */
19392    public int getPaddingBottom() {
19393        return mPaddingBottom;
19394    }
19395
19396    /**
19397     * Returns the left padding of this view. If there are inset and enabled
19398     * scrollbars, this value may include the space required to display the
19399     * scrollbars as well.
19400     *
19401     * @return the left padding in pixels
19402     */
19403    public int getPaddingLeft() {
19404        if (!isPaddingResolved()) {
19405            resolvePadding();
19406        }
19407        return mPaddingLeft;
19408    }
19409
19410    /**
19411     * Returns the start padding of this view depending on its resolved layout direction.
19412     * If there are inset and enabled scrollbars, this value may include the space
19413     * required to display the scrollbars as well.
19414     *
19415     * @return the start padding in pixels
19416     */
19417    public int getPaddingStart() {
19418        if (!isPaddingResolved()) {
19419            resolvePadding();
19420        }
19421        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
19422                mPaddingRight : mPaddingLeft;
19423    }
19424
19425    /**
19426     * Returns the right padding of this view. If there are inset and enabled
19427     * scrollbars, this value may include the space required to display the
19428     * scrollbars as well.
19429     *
19430     * @return the right padding in pixels
19431     */
19432    public int getPaddingRight() {
19433        if (!isPaddingResolved()) {
19434            resolvePadding();
19435        }
19436        return mPaddingRight;
19437    }
19438
19439    /**
19440     * Returns the end padding of this view depending on its resolved layout direction.
19441     * If there are inset and enabled scrollbars, this value may include the space
19442     * required to display the scrollbars as well.
19443     *
19444     * @return the end padding in pixels
19445     */
19446    public int getPaddingEnd() {
19447        if (!isPaddingResolved()) {
19448            resolvePadding();
19449        }
19450        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
19451                mPaddingLeft : mPaddingRight;
19452    }
19453
19454    /**
19455     * Return if the padding has been set through relative values
19456     * {@link #setPaddingRelative(int, int, int, int)} or through
19457     * @attr ref android.R.styleable#View_paddingStart or
19458     * @attr ref android.R.styleable#View_paddingEnd
19459     *
19460     * @return true if the padding is relative or false if it is not.
19461     */
19462    public boolean isPaddingRelative() {
19463        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
19464    }
19465
19466    Insets computeOpticalInsets() {
19467        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
19468    }
19469
19470    /**
19471     * @hide
19472     */
19473    public void resetPaddingToInitialValues() {
19474        if (isRtlCompatibilityMode()) {
19475            mPaddingLeft = mUserPaddingLeftInitial;
19476            mPaddingRight = mUserPaddingRightInitial;
19477            return;
19478        }
19479        if (isLayoutRtl()) {
19480            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
19481            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
19482        } else {
19483            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
19484            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
19485        }
19486    }
19487
19488    /**
19489     * @hide
19490     */
19491    public Insets getOpticalInsets() {
19492        if (mLayoutInsets == null) {
19493            mLayoutInsets = computeOpticalInsets();
19494        }
19495        return mLayoutInsets;
19496    }
19497
19498    /**
19499     * Set this view's optical insets.
19500     *
19501     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
19502     * property. Views that compute their own optical insets should call it as part of measurement.
19503     * This method does not request layout. If you are setting optical insets outside of
19504     * measure/layout itself you will want to call requestLayout() yourself.
19505     * </p>
19506     * @hide
19507     */
19508    public void setOpticalInsets(Insets insets) {
19509        mLayoutInsets = insets;
19510    }
19511
19512    /**
19513     * Changes the selection state of this view. A view can be selected or not.
19514     * Note that selection is not the same as focus. Views are typically
19515     * selected in the context of an AdapterView like ListView or GridView;
19516     * the selected view is the view that is highlighted.
19517     *
19518     * @param selected true if the view must be selected, false otherwise
19519     */
19520    public void setSelected(boolean selected) {
19521        //noinspection DoubleNegation
19522        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
19523            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
19524            if (!selected) resetPressedState();
19525            invalidate(true);
19526            refreshDrawableState();
19527            dispatchSetSelected(selected);
19528            if (selected) {
19529                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
19530            } else {
19531                notifyViewAccessibilityStateChangedIfNeeded(
19532                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
19533            }
19534        }
19535    }
19536
19537    /**
19538     * Dispatch setSelected to all of this View's children.
19539     *
19540     * @see #setSelected(boolean)
19541     *
19542     * @param selected The new selected state
19543     */
19544    protected void dispatchSetSelected(boolean selected) {
19545    }
19546
19547    /**
19548     * Indicates the selection state of this view.
19549     *
19550     * @return true if the view is selected, false otherwise
19551     */
19552    @ViewDebug.ExportedProperty
19553    public boolean isSelected() {
19554        return (mPrivateFlags & PFLAG_SELECTED) != 0;
19555    }
19556
19557    /**
19558     * Changes the activated state of this view. A view can be activated or not.
19559     * Note that activation is not the same as selection.  Selection is
19560     * a transient property, representing the view (hierarchy) the user is
19561     * currently interacting with.  Activation is a longer-term state that the
19562     * user can move views in and out of.  For example, in a list view with
19563     * single or multiple selection enabled, the views in the current selection
19564     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
19565     * here.)  The activated state is propagated down to children of the view it
19566     * is set on.
19567     *
19568     * @param activated true if the view must be activated, false otherwise
19569     */
19570    public void setActivated(boolean activated) {
19571        //noinspection DoubleNegation
19572        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
19573            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
19574            invalidate(true);
19575            refreshDrawableState();
19576            dispatchSetActivated(activated);
19577        }
19578    }
19579
19580    /**
19581     * Dispatch setActivated to all of this View's children.
19582     *
19583     * @see #setActivated(boolean)
19584     *
19585     * @param activated The new activated state
19586     */
19587    protected void dispatchSetActivated(boolean activated) {
19588    }
19589
19590    /**
19591     * Indicates the activation state of this view.
19592     *
19593     * @return true if the view is activated, false otherwise
19594     */
19595    @ViewDebug.ExportedProperty
19596    public boolean isActivated() {
19597        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
19598    }
19599
19600    /**
19601     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
19602     * observer can be used to get notifications when global events, like
19603     * layout, happen.
19604     *
19605     * The returned ViewTreeObserver observer is not guaranteed to remain
19606     * valid for the lifetime of this View. If the caller of this method keeps
19607     * a long-lived reference to ViewTreeObserver, it should always check for
19608     * the return value of {@link ViewTreeObserver#isAlive()}.
19609     *
19610     * @return The ViewTreeObserver for this view's hierarchy.
19611     */
19612    public ViewTreeObserver getViewTreeObserver() {
19613        if (mAttachInfo != null) {
19614            return mAttachInfo.mTreeObserver;
19615        }
19616        if (mFloatingTreeObserver == null) {
19617            mFloatingTreeObserver = new ViewTreeObserver(mContext);
19618        }
19619        return mFloatingTreeObserver;
19620    }
19621
19622    /**
19623     * <p>Finds the topmost view in the current view hierarchy.</p>
19624     *
19625     * @return the topmost view containing this view
19626     */
19627    public View getRootView() {
19628        if (mAttachInfo != null) {
19629            final View v = mAttachInfo.mRootView;
19630            if (v != null) {
19631                return v;
19632            }
19633        }
19634
19635        View parent = this;
19636
19637        while (parent.mParent != null && parent.mParent instanceof View) {
19638            parent = (View) parent.mParent;
19639        }
19640
19641        return parent;
19642    }
19643
19644    /**
19645     * Transforms a motion event from view-local coordinates to on-screen
19646     * coordinates.
19647     *
19648     * @param ev the view-local motion event
19649     * @return false if the transformation could not be applied
19650     * @hide
19651     */
19652    public boolean toGlobalMotionEvent(MotionEvent ev) {
19653        final AttachInfo info = mAttachInfo;
19654        if (info == null) {
19655            return false;
19656        }
19657
19658        final Matrix m = info.mTmpMatrix;
19659        m.set(Matrix.IDENTITY_MATRIX);
19660        transformMatrixToGlobal(m);
19661        ev.transform(m);
19662        return true;
19663    }
19664
19665    /**
19666     * Transforms a motion event from on-screen coordinates to view-local
19667     * coordinates.
19668     *
19669     * @param ev the on-screen motion event
19670     * @return false if the transformation could not be applied
19671     * @hide
19672     */
19673    public boolean toLocalMotionEvent(MotionEvent ev) {
19674        final AttachInfo info = mAttachInfo;
19675        if (info == null) {
19676            return false;
19677        }
19678
19679        final Matrix m = info.mTmpMatrix;
19680        m.set(Matrix.IDENTITY_MATRIX);
19681        transformMatrixToLocal(m);
19682        ev.transform(m);
19683        return true;
19684    }
19685
19686    /**
19687     * Modifies the input matrix such that it maps view-local coordinates to
19688     * on-screen coordinates.
19689     *
19690     * @param m input matrix to modify
19691     * @hide
19692     */
19693    public void transformMatrixToGlobal(Matrix m) {
19694        final ViewParent parent = mParent;
19695        if (parent instanceof View) {
19696            final View vp = (View) parent;
19697            vp.transformMatrixToGlobal(m);
19698            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
19699        } else if (parent instanceof ViewRootImpl) {
19700            final ViewRootImpl vr = (ViewRootImpl) parent;
19701            vr.transformMatrixToGlobal(m);
19702            m.preTranslate(0, -vr.mCurScrollY);
19703        }
19704
19705        m.preTranslate(mLeft, mTop);
19706
19707        if (!hasIdentityMatrix()) {
19708            m.preConcat(getMatrix());
19709        }
19710    }
19711
19712    /**
19713     * Modifies the input matrix such that it maps on-screen coordinates to
19714     * view-local coordinates.
19715     *
19716     * @param m input matrix to modify
19717     * @hide
19718     */
19719    public void transformMatrixToLocal(Matrix m) {
19720        final ViewParent parent = mParent;
19721        if (parent instanceof View) {
19722            final View vp = (View) parent;
19723            vp.transformMatrixToLocal(m);
19724            m.postTranslate(vp.mScrollX, vp.mScrollY);
19725        } else if (parent instanceof ViewRootImpl) {
19726            final ViewRootImpl vr = (ViewRootImpl) parent;
19727            vr.transformMatrixToLocal(m);
19728            m.postTranslate(0, vr.mCurScrollY);
19729        }
19730
19731        m.postTranslate(-mLeft, -mTop);
19732
19733        if (!hasIdentityMatrix()) {
19734            m.postConcat(getInverseMatrix());
19735        }
19736    }
19737
19738    /**
19739     * @hide
19740     */
19741    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
19742            @ViewDebug.IntToString(from = 0, to = "x"),
19743            @ViewDebug.IntToString(from = 1, to = "y")
19744    })
19745    public int[] getLocationOnScreen() {
19746        int[] location = new int[2];
19747        getLocationOnScreen(location);
19748        return location;
19749    }
19750
19751    /**
19752     * <p>Computes the coordinates of this view on the screen. The argument
19753     * must be an array of two integers. After the method returns, the array
19754     * contains the x and y location in that order.</p>
19755     *
19756     * @param outLocation an array of two integers in which to hold the coordinates
19757     */
19758    public void getLocationOnScreen(@Size(2) int[] outLocation) {
19759        getLocationInWindow(outLocation);
19760
19761        final AttachInfo info = mAttachInfo;
19762        if (info != null) {
19763            outLocation[0] += info.mWindowLeft;
19764            outLocation[1] += info.mWindowTop;
19765        }
19766    }
19767
19768    /**
19769     * <p>Computes the coordinates of this view in its window. The argument
19770     * must be an array of two integers. After the method returns, the array
19771     * contains the x and y location in that order.</p>
19772     *
19773     * @param outLocation an array of two integers in which to hold the coordinates
19774     */
19775    public void getLocationInWindow(@Size(2) int[] outLocation) {
19776        if (outLocation == null || outLocation.length < 2) {
19777            throw new IllegalArgumentException("outLocation must be an array of two integers");
19778        }
19779
19780        outLocation[0] = 0;
19781        outLocation[1] = 0;
19782
19783        transformFromViewToWindowSpace(outLocation);
19784    }
19785
19786    /** @hide */
19787    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
19788        if (inOutLocation == null || inOutLocation.length < 2) {
19789            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
19790        }
19791
19792        if (mAttachInfo == null) {
19793            // When the view is not attached to a window, this method does not make sense
19794            inOutLocation[0] = inOutLocation[1] = 0;
19795            return;
19796        }
19797
19798        float position[] = mAttachInfo.mTmpTransformLocation;
19799        position[0] = inOutLocation[0];
19800        position[1] = inOutLocation[1];
19801
19802        if (!hasIdentityMatrix()) {
19803            getMatrix().mapPoints(position);
19804        }
19805
19806        position[0] += mLeft;
19807        position[1] += mTop;
19808
19809        ViewParent viewParent = mParent;
19810        while (viewParent instanceof View) {
19811            final View view = (View) viewParent;
19812
19813            position[0] -= view.mScrollX;
19814            position[1] -= view.mScrollY;
19815
19816            if (!view.hasIdentityMatrix()) {
19817                view.getMatrix().mapPoints(position);
19818            }
19819
19820            position[0] += view.mLeft;
19821            position[1] += view.mTop;
19822
19823            viewParent = view.mParent;
19824         }
19825
19826        if (viewParent instanceof ViewRootImpl) {
19827            // *cough*
19828            final ViewRootImpl vr = (ViewRootImpl) viewParent;
19829            position[1] -= vr.mCurScrollY;
19830        }
19831
19832        inOutLocation[0] = Math.round(position[0]);
19833        inOutLocation[1] = Math.round(position[1]);
19834    }
19835
19836    /**
19837     * {@hide}
19838     * @param id the id of the view to be found
19839     * @return the view of the specified id, null if cannot be found
19840     */
19841    protected View findViewTraversal(@IdRes int id) {
19842        if (id == mID) {
19843            return this;
19844        }
19845        return null;
19846    }
19847
19848    /**
19849     * {@hide}
19850     * @param tag the tag of the view to be found
19851     * @return the view of specified tag, null if cannot be found
19852     */
19853    protected View findViewWithTagTraversal(Object tag) {
19854        if (tag != null && tag.equals(mTag)) {
19855            return this;
19856        }
19857        return null;
19858    }
19859
19860    /**
19861     * {@hide}
19862     * @param predicate The predicate to evaluate.
19863     * @param childToSkip If not null, ignores this child during the recursive traversal.
19864     * @return The first view that matches the predicate or null.
19865     */
19866    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
19867        if (predicate.apply(this)) {
19868            return this;
19869        }
19870        return null;
19871    }
19872
19873    /**
19874     * Look for a child view with the given id.  If this view has the given
19875     * id, return this view.
19876     *
19877     * @param id The id to search for.
19878     * @return The view that has the given id in the hierarchy or null
19879     */
19880    @Nullable
19881    public final View findViewById(@IdRes int id) {
19882        if (id < 0) {
19883            return null;
19884        }
19885        return findViewTraversal(id);
19886    }
19887
19888    /**
19889     * Finds a view by its unuque and stable accessibility id.
19890     *
19891     * @param accessibilityId The searched accessibility id.
19892     * @return The found view.
19893     */
19894    final View findViewByAccessibilityId(int accessibilityId) {
19895        if (accessibilityId < 0) {
19896            return null;
19897        }
19898        View view = findViewByAccessibilityIdTraversal(accessibilityId);
19899        if (view != null) {
19900            return view.includeForAccessibility() ? view : null;
19901        }
19902        return null;
19903    }
19904
19905    /**
19906     * Performs the traversal to find a view by its unuque and stable accessibility id.
19907     *
19908     * <strong>Note:</strong>This method does not stop at the root namespace
19909     * boundary since the user can touch the screen at an arbitrary location
19910     * potentially crossing the root namespace bounday which will send an
19911     * accessibility event to accessibility services and they should be able
19912     * to obtain the event source. Also accessibility ids are guaranteed to be
19913     * unique in the window.
19914     *
19915     * @param accessibilityId The accessibility id.
19916     * @return The found view.
19917     *
19918     * @hide
19919     */
19920    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
19921        if (getAccessibilityViewId() == accessibilityId) {
19922            return this;
19923        }
19924        return null;
19925    }
19926
19927    /**
19928     * Look for a child view with the given tag.  If this view has the given
19929     * tag, return this view.
19930     *
19931     * @param tag The tag to search for, using "tag.equals(getTag())".
19932     * @return The View that has the given tag in the hierarchy or null
19933     */
19934    public final View findViewWithTag(Object tag) {
19935        if (tag == null) {
19936            return null;
19937        }
19938        return findViewWithTagTraversal(tag);
19939    }
19940
19941    /**
19942     * {@hide}
19943     * Look for a child view that matches the specified predicate.
19944     * If this view matches the predicate, return this view.
19945     *
19946     * @param predicate The predicate to evaluate.
19947     * @return The first view that matches the predicate or null.
19948     */
19949    public final View findViewByPredicate(Predicate<View> predicate) {
19950        return findViewByPredicateTraversal(predicate, null);
19951    }
19952
19953    /**
19954     * {@hide}
19955     * Look for a child view that matches the specified predicate,
19956     * starting with the specified view and its descendents and then
19957     * recusively searching the ancestors and siblings of that view
19958     * until this view is reached.
19959     *
19960     * This method is useful in cases where the predicate does not match
19961     * a single unique view (perhaps multiple views use the same id)
19962     * and we are trying to find the view that is "closest" in scope to the
19963     * starting view.
19964     *
19965     * @param start The view to start from.
19966     * @param predicate The predicate to evaluate.
19967     * @return The first view that matches the predicate or null.
19968     */
19969    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
19970        View childToSkip = null;
19971        for (;;) {
19972            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
19973            if (view != null || start == this) {
19974                return view;
19975            }
19976
19977            ViewParent parent = start.getParent();
19978            if (parent == null || !(parent instanceof View)) {
19979                return null;
19980            }
19981
19982            childToSkip = start;
19983            start = (View) parent;
19984        }
19985    }
19986
19987    /**
19988     * Sets the identifier for this view. The identifier does not have to be
19989     * unique in this view's hierarchy. The identifier should be a positive
19990     * number.
19991     *
19992     * @see #NO_ID
19993     * @see #getId()
19994     * @see #findViewById(int)
19995     *
19996     * @param id a number used to identify the view
19997     *
19998     * @attr ref android.R.styleable#View_id
19999     */
20000    public void setId(@IdRes int id) {
20001        mID = id;
20002        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
20003            mID = generateViewId();
20004        }
20005    }
20006
20007    /**
20008     * {@hide}
20009     *
20010     * @param isRoot true if the view belongs to the root namespace, false
20011     *        otherwise
20012     */
20013    public void setIsRootNamespace(boolean isRoot) {
20014        if (isRoot) {
20015            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
20016        } else {
20017            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
20018        }
20019    }
20020
20021    /**
20022     * {@hide}
20023     *
20024     * @return true if the view belongs to the root namespace, false otherwise
20025     */
20026    public boolean isRootNamespace() {
20027        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
20028    }
20029
20030    /**
20031     * Returns this view's identifier.
20032     *
20033     * @return a positive integer used to identify the view or {@link #NO_ID}
20034     *         if the view has no ID
20035     *
20036     * @see #setId(int)
20037     * @see #findViewById(int)
20038     * @attr ref android.R.styleable#View_id
20039     */
20040    @IdRes
20041    @ViewDebug.CapturedViewProperty
20042    public int getId() {
20043        return mID;
20044    }
20045
20046    /**
20047     * Returns this view's tag.
20048     *
20049     * @return the Object stored in this view as a tag, or {@code null} if not
20050     *         set
20051     *
20052     * @see #setTag(Object)
20053     * @see #getTag(int)
20054     */
20055    @ViewDebug.ExportedProperty
20056    public Object getTag() {
20057        return mTag;
20058    }
20059
20060    /**
20061     * Sets the tag associated with this view. A tag can be used to mark
20062     * a view in its hierarchy and does not have to be unique within the
20063     * hierarchy. Tags can also be used to store data within a view without
20064     * resorting to another data structure.
20065     *
20066     * @param tag an Object to tag the view with
20067     *
20068     * @see #getTag()
20069     * @see #setTag(int, Object)
20070     */
20071    public void setTag(final Object tag) {
20072        mTag = tag;
20073    }
20074
20075    /**
20076     * Returns the tag associated with this view and the specified key.
20077     *
20078     * @param key The key identifying the tag
20079     *
20080     * @return the Object stored in this view as a tag, or {@code null} if not
20081     *         set
20082     *
20083     * @see #setTag(int, Object)
20084     * @see #getTag()
20085     */
20086    public Object getTag(int key) {
20087        if (mKeyedTags != null) return mKeyedTags.get(key);
20088        return null;
20089    }
20090
20091    /**
20092     * Sets a tag associated with this view and a key. A tag can be used
20093     * to mark a view in its hierarchy and does not have to be unique within
20094     * the hierarchy. Tags can also be used to store data within a view
20095     * without resorting to another data structure.
20096     *
20097     * The specified key should be an id declared in the resources of the
20098     * application to ensure it is unique (see the <a
20099     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
20100     * Keys identified as belonging to
20101     * the Android framework or not associated with any package will cause
20102     * an {@link IllegalArgumentException} to be thrown.
20103     *
20104     * @param key The key identifying the tag
20105     * @param tag An Object to tag the view with
20106     *
20107     * @throws IllegalArgumentException If they specified key is not valid
20108     *
20109     * @see #setTag(Object)
20110     * @see #getTag(int)
20111     */
20112    public void setTag(int key, final Object tag) {
20113        // If the package id is 0x00 or 0x01, it's either an undefined package
20114        // or a framework id
20115        if ((key >>> 24) < 2) {
20116            throw new IllegalArgumentException("The key must be an application-specific "
20117                    + "resource id.");
20118        }
20119
20120        setKeyedTag(key, tag);
20121    }
20122
20123    /**
20124     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
20125     * framework id.
20126     *
20127     * @hide
20128     */
20129    public void setTagInternal(int key, Object tag) {
20130        if ((key >>> 24) != 0x1) {
20131            throw new IllegalArgumentException("The key must be a framework-specific "
20132                    + "resource id.");
20133        }
20134
20135        setKeyedTag(key, tag);
20136    }
20137
20138    private void setKeyedTag(int key, Object tag) {
20139        if (mKeyedTags == null) {
20140            mKeyedTags = new SparseArray<Object>(2);
20141        }
20142
20143        mKeyedTags.put(key, tag);
20144    }
20145
20146    /**
20147     * Prints information about this view in the log output, with the tag
20148     * {@link #VIEW_LOG_TAG}.
20149     *
20150     * @hide
20151     */
20152    public void debug() {
20153        debug(0);
20154    }
20155
20156    /**
20157     * Prints information about this view in the log output, with the tag
20158     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
20159     * indentation defined by the <code>depth</code>.
20160     *
20161     * @param depth the indentation level
20162     *
20163     * @hide
20164     */
20165    protected void debug(int depth) {
20166        String output = debugIndent(depth - 1);
20167
20168        output += "+ " + this;
20169        int id = getId();
20170        if (id != -1) {
20171            output += " (id=" + id + ")";
20172        }
20173        Object tag = getTag();
20174        if (tag != null) {
20175            output += " (tag=" + tag + ")";
20176        }
20177        Log.d(VIEW_LOG_TAG, output);
20178
20179        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
20180            output = debugIndent(depth) + " FOCUSED";
20181            Log.d(VIEW_LOG_TAG, output);
20182        }
20183
20184        output = debugIndent(depth);
20185        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
20186                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
20187                + "} ";
20188        Log.d(VIEW_LOG_TAG, output);
20189
20190        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
20191                || mPaddingBottom != 0) {
20192            output = debugIndent(depth);
20193            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
20194                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
20195            Log.d(VIEW_LOG_TAG, output);
20196        }
20197
20198        output = debugIndent(depth);
20199        output += "mMeasureWidth=" + mMeasuredWidth +
20200                " mMeasureHeight=" + mMeasuredHeight;
20201        Log.d(VIEW_LOG_TAG, output);
20202
20203        output = debugIndent(depth);
20204        if (mLayoutParams == null) {
20205            output += "BAD! no layout params";
20206        } else {
20207            output = mLayoutParams.debug(output);
20208        }
20209        Log.d(VIEW_LOG_TAG, output);
20210
20211        output = debugIndent(depth);
20212        output += "flags={";
20213        output += View.printFlags(mViewFlags);
20214        output += "}";
20215        Log.d(VIEW_LOG_TAG, output);
20216
20217        output = debugIndent(depth);
20218        output += "privateFlags={";
20219        output += View.printPrivateFlags(mPrivateFlags);
20220        output += "}";
20221        Log.d(VIEW_LOG_TAG, output);
20222    }
20223
20224    /**
20225     * Creates a string of whitespaces used for indentation.
20226     *
20227     * @param depth the indentation level
20228     * @return a String containing (depth * 2 + 3) * 2 white spaces
20229     *
20230     * @hide
20231     */
20232    protected static String debugIndent(int depth) {
20233        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
20234        for (int i = 0; i < (depth * 2) + 3; i++) {
20235            spaces.append(' ').append(' ');
20236        }
20237        return spaces.toString();
20238    }
20239
20240    /**
20241     * <p>Return the offset of the widget's text baseline from the widget's top
20242     * boundary. If this widget does not support baseline alignment, this
20243     * method returns -1. </p>
20244     *
20245     * @return the offset of the baseline within the widget's bounds or -1
20246     *         if baseline alignment is not supported
20247     */
20248    @ViewDebug.ExportedProperty(category = "layout")
20249    public int getBaseline() {
20250        return -1;
20251    }
20252
20253    /**
20254     * Returns whether the view hierarchy is currently undergoing a layout pass. This
20255     * information is useful to avoid situations such as calling {@link #requestLayout()} during
20256     * a layout pass.
20257     *
20258     * @return whether the view hierarchy is currently undergoing a layout pass
20259     */
20260    public boolean isInLayout() {
20261        ViewRootImpl viewRoot = getViewRootImpl();
20262        return (viewRoot != null && viewRoot.isInLayout());
20263    }
20264
20265    /**
20266     * Call this when something has changed which has invalidated the
20267     * layout of this view. This will schedule a layout pass of the view
20268     * tree. This should not be called while the view hierarchy is currently in a layout
20269     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
20270     * end of the current layout pass (and then layout will run again) or after the current
20271     * frame is drawn and the next layout occurs.
20272     *
20273     * <p>Subclasses which override this method should call the superclass method to
20274     * handle possible request-during-layout errors correctly.</p>
20275     */
20276    @CallSuper
20277    public void requestLayout() {
20278        if (mMeasureCache != null) mMeasureCache.clear();
20279
20280        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
20281            // Only trigger request-during-layout logic if this is the view requesting it,
20282            // not the views in its parent hierarchy
20283            ViewRootImpl viewRoot = getViewRootImpl();
20284            if (viewRoot != null && viewRoot.isInLayout()) {
20285                if (!viewRoot.requestLayoutDuringLayout(this)) {
20286                    return;
20287                }
20288            }
20289            mAttachInfo.mViewRequestingLayout = this;
20290        }
20291
20292        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
20293        mPrivateFlags |= PFLAG_INVALIDATED;
20294
20295        if (mParent != null && !mParent.isLayoutRequested()) {
20296            mParent.requestLayout();
20297        }
20298        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
20299            mAttachInfo.mViewRequestingLayout = null;
20300        }
20301    }
20302
20303    /**
20304     * Forces this view to be laid out during the next layout pass.
20305     * This method does not call requestLayout() or forceLayout()
20306     * on the parent.
20307     */
20308    public void forceLayout() {
20309        if (mMeasureCache != null) mMeasureCache.clear();
20310
20311        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
20312        mPrivateFlags |= PFLAG_INVALIDATED;
20313    }
20314
20315    /**
20316     * <p>
20317     * This is called to find out how big a view should be. The parent
20318     * supplies constraint information in the width and height parameters.
20319     * </p>
20320     *
20321     * <p>
20322     * The actual measurement work of a view is performed in
20323     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
20324     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
20325     * </p>
20326     *
20327     *
20328     * @param widthMeasureSpec Horizontal space requirements as imposed by the
20329     *        parent
20330     * @param heightMeasureSpec Vertical space requirements as imposed by the
20331     *        parent
20332     *
20333     * @see #onMeasure(int, int)
20334     */
20335    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
20336        boolean optical = isLayoutModeOptical(this);
20337        if (optical != isLayoutModeOptical(mParent)) {
20338            Insets insets = getOpticalInsets();
20339            int oWidth  = insets.left + insets.right;
20340            int oHeight = insets.top  + insets.bottom;
20341            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
20342            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
20343        }
20344
20345        // Suppress sign extension for the low bytes
20346        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
20347        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
20348
20349        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
20350
20351        // Optimize layout by avoiding an extra EXACTLY pass when the view is
20352        // already measured as the correct size. In API 23 and below, this
20353        // extra pass is required to make LinearLayout re-distribute weight.
20354        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
20355                || heightMeasureSpec != mOldHeightMeasureSpec;
20356        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
20357                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
20358        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
20359                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
20360        final boolean needsLayout = specChanged
20361                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
20362
20363        if (forceLayout || needsLayout) {
20364            // first clears the measured dimension flag
20365            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
20366
20367            resolveRtlPropertiesIfNeeded();
20368
20369            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
20370            if (cacheIndex < 0 || sIgnoreMeasureCache) {
20371                // measure ourselves, this should set the measured dimension flag back
20372                onMeasure(widthMeasureSpec, heightMeasureSpec);
20373                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
20374            } else {
20375                long value = mMeasureCache.valueAt(cacheIndex);
20376                // Casting a long to int drops the high 32 bits, no mask needed
20377                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
20378                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
20379            }
20380
20381            // flag not set, setMeasuredDimension() was not invoked, we raise
20382            // an exception to warn the developer
20383            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
20384                throw new IllegalStateException("View with id " + getId() + ": "
20385                        + getClass().getName() + "#onMeasure() did not set the"
20386                        + " measured dimension by calling"
20387                        + " setMeasuredDimension()");
20388            }
20389
20390            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
20391        }
20392
20393        mOldWidthMeasureSpec = widthMeasureSpec;
20394        mOldHeightMeasureSpec = heightMeasureSpec;
20395
20396        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
20397                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
20398    }
20399
20400    /**
20401     * <p>
20402     * Measure the view and its content to determine the measured width and the
20403     * measured height. This method is invoked by {@link #measure(int, int)} and
20404     * should be overridden by subclasses to provide accurate and efficient
20405     * measurement of their contents.
20406     * </p>
20407     *
20408     * <p>
20409     * <strong>CONTRACT:</strong> When overriding this method, you
20410     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
20411     * measured width and height of this view. Failure to do so will trigger an
20412     * <code>IllegalStateException</code>, thrown by
20413     * {@link #measure(int, int)}. Calling the superclass'
20414     * {@link #onMeasure(int, int)} is a valid use.
20415     * </p>
20416     *
20417     * <p>
20418     * The base class implementation of measure defaults to the background size,
20419     * unless a larger size is allowed by the MeasureSpec. Subclasses should
20420     * override {@link #onMeasure(int, int)} to provide better measurements of
20421     * their content.
20422     * </p>
20423     *
20424     * <p>
20425     * If this method is overridden, it is the subclass's responsibility to make
20426     * sure the measured height and width are at least the view's minimum height
20427     * and width ({@link #getSuggestedMinimumHeight()} and
20428     * {@link #getSuggestedMinimumWidth()}).
20429     * </p>
20430     *
20431     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
20432     *                         The requirements are encoded with
20433     *                         {@link android.view.View.MeasureSpec}.
20434     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
20435     *                         The requirements are encoded with
20436     *                         {@link android.view.View.MeasureSpec}.
20437     *
20438     * @see #getMeasuredWidth()
20439     * @see #getMeasuredHeight()
20440     * @see #setMeasuredDimension(int, int)
20441     * @see #getSuggestedMinimumHeight()
20442     * @see #getSuggestedMinimumWidth()
20443     * @see android.view.View.MeasureSpec#getMode(int)
20444     * @see android.view.View.MeasureSpec#getSize(int)
20445     */
20446    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
20447        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
20448                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
20449    }
20450
20451    /**
20452     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
20453     * measured width and measured height. Failing to do so will trigger an
20454     * exception at measurement time.</p>
20455     *
20456     * @param measuredWidth The measured width of this view.  May be a complex
20457     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20458     * {@link #MEASURED_STATE_TOO_SMALL}.
20459     * @param measuredHeight The measured height of this view.  May be a complex
20460     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20461     * {@link #MEASURED_STATE_TOO_SMALL}.
20462     */
20463    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
20464        boolean optical = isLayoutModeOptical(this);
20465        if (optical != isLayoutModeOptical(mParent)) {
20466            Insets insets = getOpticalInsets();
20467            int opticalWidth  = insets.left + insets.right;
20468            int opticalHeight = insets.top  + insets.bottom;
20469
20470            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
20471            measuredHeight += optical ? opticalHeight : -opticalHeight;
20472        }
20473        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
20474    }
20475
20476    /**
20477     * Sets the measured dimension without extra processing for things like optical bounds.
20478     * Useful for reapplying consistent values that have already been cooked with adjustments
20479     * for optical bounds, etc. such as those from the measurement cache.
20480     *
20481     * @param measuredWidth The measured width of this view.  May be a complex
20482     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20483     * {@link #MEASURED_STATE_TOO_SMALL}.
20484     * @param measuredHeight The measured height of this view.  May be a complex
20485     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20486     * {@link #MEASURED_STATE_TOO_SMALL}.
20487     */
20488    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
20489        mMeasuredWidth = measuredWidth;
20490        mMeasuredHeight = measuredHeight;
20491
20492        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
20493    }
20494
20495    /**
20496     * Merge two states as returned by {@link #getMeasuredState()}.
20497     * @param curState The current state as returned from a view or the result
20498     * of combining multiple views.
20499     * @param newState The new view state to combine.
20500     * @return Returns a new integer reflecting the combination of the two
20501     * states.
20502     */
20503    public static int combineMeasuredStates(int curState, int newState) {
20504        return curState | newState;
20505    }
20506
20507    /**
20508     * Version of {@link #resolveSizeAndState(int, int, int)}
20509     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
20510     */
20511    public static int resolveSize(int size, int measureSpec) {
20512        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
20513    }
20514
20515    /**
20516     * Utility to reconcile a desired size and state, with constraints imposed
20517     * by a MeasureSpec. Will take the desired size, unless a different size
20518     * is imposed by the constraints. The returned value is a compound integer,
20519     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
20520     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
20521     * resulting size is smaller than the size the view wants to be.
20522     *
20523     * @param size How big the view wants to be.
20524     * @param measureSpec Constraints imposed by the parent.
20525     * @param childMeasuredState Size information bit mask for the view's
20526     *                           children.
20527     * @return Size information bit mask as defined by
20528     *         {@link #MEASURED_SIZE_MASK} and
20529     *         {@link #MEASURED_STATE_TOO_SMALL}.
20530     */
20531    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
20532        final int specMode = MeasureSpec.getMode(measureSpec);
20533        final int specSize = MeasureSpec.getSize(measureSpec);
20534        final int result;
20535        switch (specMode) {
20536            case MeasureSpec.AT_MOST:
20537                if (specSize < size) {
20538                    result = specSize | MEASURED_STATE_TOO_SMALL;
20539                } else {
20540                    result = size;
20541                }
20542                break;
20543            case MeasureSpec.EXACTLY:
20544                result = specSize;
20545                break;
20546            case MeasureSpec.UNSPECIFIED:
20547            default:
20548                result = size;
20549        }
20550        return result | (childMeasuredState & MEASURED_STATE_MASK);
20551    }
20552
20553    /**
20554     * Utility to return a default size. Uses the supplied size if the
20555     * MeasureSpec imposed no constraints. Will get larger if allowed
20556     * by the MeasureSpec.
20557     *
20558     * @param size Default size for this view
20559     * @param measureSpec Constraints imposed by the parent
20560     * @return The size this view should be.
20561     */
20562    public static int getDefaultSize(int size, int measureSpec) {
20563        int result = size;
20564        int specMode = MeasureSpec.getMode(measureSpec);
20565        int specSize = MeasureSpec.getSize(measureSpec);
20566
20567        switch (specMode) {
20568        case MeasureSpec.UNSPECIFIED:
20569            result = size;
20570            break;
20571        case MeasureSpec.AT_MOST:
20572        case MeasureSpec.EXACTLY:
20573            result = specSize;
20574            break;
20575        }
20576        return result;
20577    }
20578
20579    /**
20580     * Returns the suggested minimum height that the view should use. This
20581     * returns the maximum of the view's minimum height
20582     * and the background's minimum height
20583     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
20584     * <p>
20585     * When being used in {@link #onMeasure(int, int)}, the caller should still
20586     * ensure the returned height is within the requirements of the parent.
20587     *
20588     * @return The suggested minimum height of the view.
20589     */
20590    protected int getSuggestedMinimumHeight() {
20591        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
20592
20593    }
20594
20595    /**
20596     * Returns the suggested minimum width that the view should use. This
20597     * returns the maximum of the view's minimum width
20598     * and the background's minimum width
20599     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
20600     * <p>
20601     * When being used in {@link #onMeasure(int, int)}, the caller should still
20602     * ensure the returned width is within the requirements of the parent.
20603     *
20604     * @return The suggested minimum width of the view.
20605     */
20606    protected int getSuggestedMinimumWidth() {
20607        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
20608    }
20609
20610    /**
20611     * Returns the minimum height of the view.
20612     *
20613     * @return the minimum height the view will try to be, in pixels
20614     *
20615     * @see #setMinimumHeight(int)
20616     *
20617     * @attr ref android.R.styleable#View_minHeight
20618     */
20619    public int getMinimumHeight() {
20620        return mMinHeight;
20621    }
20622
20623    /**
20624     * Sets the minimum height of the view. It is not guaranteed the view will
20625     * be able to achieve this minimum height (for example, if its parent layout
20626     * constrains it with less available height).
20627     *
20628     * @param minHeight The minimum height the view will try to be, in pixels
20629     *
20630     * @see #getMinimumHeight()
20631     *
20632     * @attr ref android.R.styleable#View_minHeight
20633     */
20634    @RemotableViewMethod
20635    public void setMinimumHeight(int minHeight) {
20636        mMinHeight = minHeight;
20637        requestLayout();
20638    }
20639
20640    /**
20641     * Returns the minimum width of the view.
20642     *
20643     * @return the minimum width the view will try to be, in pixels
20644     *
20645     * @see #setMinimumWidth(int)
20646     *
20647     * @attr ref android.R.styleable#View_minWidth
20648     */
20649    public int getMinimumWidth() {
20650        return mMinWidth;
20651    }
20652
20653    /**
20654     * Sets the minimum width of the view. It is not guaranteed the view will
20655     * be able to achieve this minimum width (for example, if its parent layout
20656     * constrains it with less available width).
20657     *
20658     * @param minWidth The minimum width the view will try to be, in pixels
20659     *
20660     * @see #getMinimumWidth()
20661     *
20662     * @attr ref android.R.styleable#View_minWidth
20663     */
20664    public void setMinimumWidth(int minWidth) {
20665        mMinWidth = minWidth;
20666        requestLayout();
20667
20668    }
20669
20670    /**
20671     * Get the animation currently associated with this view.
20672     *
20673     * @return The animation that is currently playing or
20674     *         scheduled to play for this view.
20675     */
20676    public Animation getAnimation() {
20677        return mCurrentAnimation;
20678    }
20679
20680    /**
20681     * Start the specified animation now.
20682     *
20683     * @param animation the animation to start now
20684     */
20685    public void startAnimation(Animation animation) {
20686        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
20687        setAnimation(animation);
20688        invalidateParentCaches();
20689        invalidate(true);
20690    }
20691
20692    /**
20693     * Cancels any animations for this view.
20694     */
20695    public void clearAnimation() {
20696        if (mCurrentAnimation != null) {
20697            mCurrentAnimation.detach();
20698        }
20699        mCurrentAnimation = null;
20700        invalidateParentIfNeeded();
20701    }
20702
20703    /**
20704     * Sets the next animation to play for this view.
20705     * If you want the animation to play immediately, use
20706     * {@link #startAnimation(android.view.animation.Animation)} instead.
20707     * This method provides allows fine-grained
20708     * control over the start time and invalidation, but you
20709     * must make sure that 1) the animation has a start time set, and
20710     * 2) the view's parent (which controls animations on its children)
20711     * will be invalidated when the animation is supposed to
20712     * start.
20713     *
20714     * @param animation The next animation, or null.
20715     */
20716    public void setAnimation(Animation animation) {
20717        mCurrentAnimation = animation;
20718
20719        if (animation != null) {
20720            // If the screen is off assume the animation start time is now instead of
20721            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
20722            // would cause the animation to start when the screen turns back on
20723            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
20724                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
20725                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
20726            }
20727            animation.reset();
20728        }
20729    }
20730
20731    /**
20732     * Invoked by a parent ViewGroup to notify the start of the animation
20733     * currently associated with this view. If you override this method,
20734     * always call super.onAnimationStart();
20735     *
20736     * @see #setAnimation(android.view.animation.Animation)
20737     * @see #getAnimation()
20738     */
20739    @CallSuper
20740    protected void onAnimationStart() {
20741        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
20742    }
20743
20744    /**
20745     * Invoked by a parent ViewGroup to notify the end of the animation
20746     * currently associated with this view. If you override this method,
20747     * always call super.onAnimationEnd();
20748     *
20749     * @see #setAnimation(android.view.animation.Animation)
20750     * @see #getAnimation()
20751     */
20752    @CallSuper
20753    protected void onAnimationEnd() {
20754        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
20755    }
20756
20757    /**
20758     * Invoked if there is a Transform that involves alpha. Subclass that can
20759     * draw themselves with the specified alpha should return true, and then
20760     * respect that alpha when their onDraw() is called. If this returns false
20761     * then the view may be redirected to draw into an offscreen buffer to
20762     * fulfill the request, which will look fine, but may be slower than if the
20763     * subclass handles it internally. The default implementation returns false.
20764     *
20765     * @param alpha The alpha (0..255) to apply to the view's drawing
20766     * @return true if the view can draw with the specified alpha.
20767     */
20768    protected boolean onSetAlpha(int alpha) {
20769        return false;
20770    }
20771
20772    /**
20773     * This is used by the RootView to perform an optimization when
20774     * the view hierarchy contains one or several SurfaceView.
20775     * SurfaceView is always considered transparent, but its children are not,
20776     * therefore all View objects remove themselves from the global transparent
20777     * region (passed as a parameter to this function).
20778     *
20779     * @param region The transparent region for this ViewAncestor (window).
20780     *
20781     * @return Returns true if the effective visibility of the view at this
20782     * point is opaque, regardless of the transparent region; returns false
20783     * if it is possible for underlying windows to be seen behind the view.
20784     *
20785     * {@hide}
20786     */
20787    public boolean gatherTransparentRegion(Region region) {
20788        final AttachInfo attachInfo = mAttachInfo;
20789        if (region != null && attachInfo != null) {
20790            final int pflags = mPrivateFlags;
20791            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
20792                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
20793                // remove it from the transparent region.
20794                final int[] location = attachInfo.mTransparentLocation;
20795                getLocationInWindow(location);
20796                // When a view has Z value, then it will be better to leave some area below the view
20797                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
20798                // the bottom part needs more offset than the left, top and right parts due to the
20799                // spot light effects.
20800                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
20801                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
20802                        location[0] + mRight - mLeft + shadowOffset,
20803                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
20804            } else {
20805                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
20806                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
20807                    // the background drawable's non-transparent parts from this transparent region.
20808                    applyDrawableToTransparentRegion(mBackground, region);
20809                }
20810                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20811                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
20812                    // Similarly, we remove the foreground drawable's non-transparent parts.
20813                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
20814                }
20815            }
20816        }
20817        return true;
20818    }
20819
20820    /**
20821     * Play a sound effect for this view.
20822     *
20823     * <p>The framework will play sound effects for some built in actions, such as
20824     * clicking, but you may wish to play these effects in your widget,
20825     * for instance, for internal navigation.
20826     *
20827     * <p>The sound effect will only be played if sound effects are enabled by the user, and
20828     * {@link #isSoundEffectsEnabled()} is true.
20829     *
20830     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
20831     */
20832    public void playSoundEffect(int soundConstant) {
20833        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
20834            return;
20835        }
20836        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
20837    }
20838
20839    /**
20840     * BZZZTT!!1!
20841     *
20842     * <p>Provide haptic feedback to the user for this view.
20843     *
20844     * <p>The framework will provide haptic feedback for some built in actions,
20845     * such as long presses, but you may wish to provide feedback for your
20846     * own widget.
20847     *
20848     * <p>The feedback will only be performed if
20849     * {@link #isHapticFeedbackEnabled()} is true.
20850     *
20851     * @param feedbackConstant One of the constants defined in
20852     * {@link HapticFeedbackConstants}
20853     */
20854    public boolean performHapticFeedback(int feedbackConstant) {
20855        return performHapticFeedback(feedbackConstant, 0);
20856    }
20857
20858    /**
20859     * BZZZTT!!1!
20860     *
20861     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
20862     *
20863     * @param feedbackConstant One of the constants defined in
20864     * {@link HapticFeedbackConstants}
20865     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
20866     */
20867    public boolean performHapticFeedback(int feedbackConstant, int flags) {
20868        if (mAttachInfo == null) {
20869            return false;
20870        }
20871        //noinspection SimplifiableIfStatement
20872        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
20873                && !isHapticFeedbackEnabled()) {
20874            return false;
20875        }
20876        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
20877                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
20878    }
20879
20880    /**
20881     * Request that the visibility of the status bar or other screen/window
20882     * decorations be changed.
20883     *
20884     * <p>This method is used to put the over device UI into temporary modes
20885     * where the user's attention is focused more on the application content,
20886     * by dimming or hiding surrounding system affordances.  This is typically
20887     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
20888     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
20889     * to be placed behind the action bar (and with these flags other system
20890     * affordances) so that smooth transitions between hiding and showing them
20891     * can be done.
20892     *
20893     * <p>Two representative examples of the use of system UI visibility is
20894     * implementing a content browsing application (like a magazine reader)
20895     * and a video playing application.
20896     *
20897     * <p>The first code shows a typical implementation of a View in a content
20898     * browsing application.  In this implementation, the application goes
20899     * into a content-oriented mode by hiding the status bar and action bar,
20900     * and putting the navigation elements into lights out mode.  The user can
20901     * then interact with content while in this mode.  Such an application should
20902     * provide an easy way for the user to toggle out of the mode (such as to
20903     * check information in the status bar or access notifications).  In the
20904     * implementation here, this is done simply by tapping on the content.
20905     *
20906     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
20907     *      content}
20908     *
20909     * <p>This second code sample shows a typical implementation of a View
20910     * in a video playing application.  In this situation, while the video is
20911     * playing the application would like to go into a complete full-screen mode,
20912     * to use as much of the display as possible for the video.  When in this state
20913     * the user can not interact with the application; the system intercepts
20914     * touching on the screen to pop the UI out of full screen mode.  See
20915     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
20916     *
20917     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
20918     *      content}
20919     *
20920     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20921     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20922     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20923     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20924     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20925     */
20926    public void setSystemUiVisibility(int visibility) {
20927        if (visibility != mSystemUiVisibility) {
20928            mSystemUiVisibility = visibility;
20929            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20930                mParent.recomputeViewAttributes(this);
20931            }
20932        }
20933    }
20934
20935    /**
20936     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
20937     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20938     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20939     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20940     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20941     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20942     */
20943    public int getSystemUiVisibility() {
20944        return mSystemUiVisibility;
20945    }
20946
20947    /**
20948     * Returns the current system UI visibility that is currently set for
20949     * the entire window.  This is the combination of the
20950     * {@link #setSystemUiVisibility(int)} values supplied by all of the
20951     * views in the window.
20952     */
20953    public int getWindowSystemUiVisibility() {
20954        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
20955    }
20956
20957    /**
20958     * Override to find out when the window's requested system UI visibility
20959     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
20960     * This is different from the callbacks received through
20961     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
20962     * in that this is only telling you about the local request of the window,
20963     * not the actual values applied by the system.
20964     */
20965    public void onWindowSystemUiVisibilityChanged(int visible) {
20966    }
20967
20968    /**
20969     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
20970     * the view hierarchy.
20971     */
20972    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
20973        onWindowSystemUiVisibilityChanged(visible);
20974    }
20975
20976    /**
20977     * Set a listener to receive callbacks when the visibility of the system bar changes.
20978     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
20979     */
20980    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
20981        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
20982        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20983            mParent.recomputeViewAttributes(this);
20984        }
20985    }
20986
20987    /**
20988     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
20989     * the view hierarchy.
20990     */
20991    public void dispatchSystemUiVisibilityChanged(int visibility) {
20992        ListenerInfo li = mListenerInfo;
20993        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
20994            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
20995                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
20996        }
20997    }
20998
20999    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
21000        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
21001        if (val != mSystemUiVisibility) {
21002            setSystemUiVisibility(val);
21003            return true;
21004        }
21005        return false;
21006    }
21007
21008    /** @hide */
21009    public void setDisabledSystemUiVisibility(int flags) {
21010        if (mAttachInfo != null) {
21011            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
21012                mAttachInfo.mDisabledSystemUiVisibility = flags;
21013                if (mParent != null) {
21014                    mParent.recomputeViewAttributes(this);
21015                }
21016            }
21017        }
21018    }
21019
21020    /**
21021     * Creates an image that the system displays during the drag and drop
21022     * operation. This is called a &quot;drag shadow&quot;. The default implementation
21023     * for a DragShadowBuilder based on a View returns an image that has exactly the same
21024     * appearance as the given View. The default also positions the center of the drag shadow
21025     * directly under the touch point. If no View is provided (the constructor with no parameters
21026     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
21027     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
21028     * default is an invisible drag shadow.
21029     * <p>
21030     * You are not required to use the View you provide to the constructor as the basis of the
21031     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
21032     * anything you want as the drag shadow.
21033     * </p>
21034     * <p>
21035     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
21036     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
21037     *  size and position of the drag shadow. It uses this data to construct a
21038     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
21039     *  so that your application can draw the shadow image in the Canvas.
21040     * </p>
21041     *
21042     * <div class="special reference">
21043     * <h3>Developer Guides</h3>
21044     * <p>For a guide to implementing drag and drop features, read the
21045     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21046     * </div>
21047     */
21048    public static class DragShadowBuilder {
21049        private final WeakReference<View> mView;
21050
21051        /**
21052         * Constructs a shadow image builder based on a View. By default, the resulting drag
21053         * shadow will have the same appearance and dimensions as the View, with the touch point
21054         * over the center of the View.
21055         * @param view A View. Any View in scope can be used.
21056         */
21057        public DragShadowBuilder(View view) {
21058            mView = new WeakReference<View>(view);
21059        }
21060
21061        /**
21062         * Construct a shadow builder object with no associated View.  This
21063         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
21064         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
21065         * to supply the drag shadow's dimensions and appearance without
21066         * reference to any View object. If they are not overridden, then the result is an
21067         * invisible drag shadow.
21068         */
21069        public DragShadowBuilder() {
21070            mView = new WeakReference<View>(null);
21071        }
21072
21073        /**
21074         * Returns the View object that had been passed to the
21075         * {@link #View.DragShadowBuilder(View)}
21076         * constructor.  If that View parameter was {@code null} or if the
21077         * {@link #View.DragShadowBuilder()}
21078         * constructor was used to instantiate the builder object, this method will return
21079         * null.
21080         *
21081         * @return The View object associate with this builder object.
21082         */
21083        @SuppressWarnings({"JavadocReference"})
21084        final public View getView() {
21085            return mView.get();
21086        }
21087
21088        /**
21089         * Provides the metrics for the shadow image. These include the dimensions of
21090         * the shadow image, and the point within that shadow that should
21091         * be centered under the touch location while dragging.
21092         * <p>
21093         * The default implementation sets the dimensions of the shadow to be the
21094         * same as the dimensions of the View itself and centers the shadow under
21095         * the touch point.
21096         * </p>
21097         *
21098         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
21099         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
21100         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
21101         * image.
21102         *
21103         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
21104         * shadow image that should be underneath the touch point during the drag and drop
21105         * operation. Your application must set {@link android.graphics.Point#x} to the
21106         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
21107         */
21108        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
21109            final View view = mView.get();
21110            if (view != null) {
21111                outShadowSize.set(view.getWidth(), view.getHeight());
21112                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
21113            } else {
21114                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
21115            }
21116        }
21117
21118        /**
21119         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
21120         * based on the dimensions it received from the
21121         * {@link #onProvideShadowMetrics(Point, Point)} callback.
21122         *
21123         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
21124         */
21125        public void onDrawShadow(Canvas canvas) {
21126            final View view = mView.get();
21127            if (view != null) {
21128                view.draw(canvas);
21129            } else {
21130                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
21131            }
21132        }
21133    }
21134
21135    /**
21136     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
21137     * startDragAndDrop()} for newer platform versions.
21138     */
21139    @Deprecated
21140    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
21141                                   Object myLocalState, int flags) {
21142        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
21143    }
21144
21145    /**
21146     * Starts a drag and drop operation. When your application calls this method, it passes a
21147     * {@link android.view.View.DragShadowBuilder} object to the system. The
21148     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
21149     * to get metrics for the drag shadow, and then calls the object's
21150     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
21151     * <p>
21152     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
21153     *  drag events to all the View objects in your application that are currently visible. It does
21154     *  this either by calling the View object's drag listener (an implementation of
21155     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
21156     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
21157     *  Both are passed a {@link android.view.DragEvent} object that has a
21158     *  {@link android.view.DragEvent#getAction()} value of
21159     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
21160     * </p>
21161     * <p>
21162     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
21163     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
21164     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
21165     * to the View the user selected for dragging.
21166     * </p>
21167     * @param data A {@link android.content.ClipData} object pointing to the data to be
21168     * transferred by the drag and drop operation.
21169     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
21170     * drag shadow.
21171     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
21172     * drop operation. When dispatching drag events to views in the same activity this object
21173     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
21174     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
21175     * will return null).
21176     * <p>
21177     * myLocalState is a lightweight mechanism for the sending information from the dragged View
21178     * to the target Views. For example, it can contain flags that differentiate between a
21179     * a copy operation and a move operation.
21180     * </p>
21181     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
21182     * flags, or any combination of the following:
21183     *     <ul>
21184     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
21185     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
21186     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
21187     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
21188     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
21189     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
21190     *     </ul>
21191     * @return {@code true} if the method completes successfully, or
21192     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
21193     * do a drag, and so no drag operation is in progress.
21194     */
21195    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
21196            Object myLocalState, int flags) {
21197        if (ViewDebug.DEBUG_DRAG) {
21198            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
21199        }
21200        if (mAttachInfo == null) {
21201            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
21202            return false;
21203        }
21204
21205        if (data != null) {
21206            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
21207        }
21208
21209        boolean okay = false;
21210
21211        Point shadowSize = new Point();
21212        Point shadowTouchPoint = new Point();
21213        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
21214
21215        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
21216                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
21217            throw new IllegalStateException("Drag shadow dimensions must not be negative");
21218        }
21219
21220        if (ViewDebug.DEBUG_DRAG) {
21221            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
21222                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
21223        }
21224        if (mAttachInfo.mDragSurface != null) {
21225            mAttachInfo.mDragSurface.release();
21226        }
21227        mAttachInfo.mDragSurface = new Surface();
21228        try {
21229            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
21230                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
21231            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
21232                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
21233            if (mAttachInfo.mDragToken != null) {
21234                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
21235                try {
21236                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
21237                    shadowBuilder.onDrawShadow(canvas);
21238                } finally {
21239                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
21240                }
21241
21242                final ViewRootImpl root = getViewRootImpl();
21243
21244                // Cache the local state object for delivery with DragEvents
21245                root.setLocalDragState(myLocalState);
21246
21247                // repurpose 'shadowSize' for the last touch point
21248                root.getLastTouchPoint(shadowSize);
21249
21250                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
21251                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
21252                        shadowTouchPoint.x, shadowTouchPoint.y, data);
21253                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
21254            }
21255        } catch (Exception e) {
21256            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
21257            mAttachInfo.mDragSurface.destroy();
21258            mAttachInfo.mDragSurface = null;
21259        }
21260
21261        return okay;
21262    }
21263
21264    /**
21265     * Cancels an ongoing drag and drop operation.
21266     * <p>
21267     * A {@link android.view.DragEvent} object with
21268     * {@link android.view.DragEvent#getAction()} value of
21269     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
21270     * {@link android.view.DragEvent#getResult()} value of {@code false}
21271     * will be sent to every
21272     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
21273     * even if they are not currently visible.
21274     * </p>
21275     * <p>
21276     * This method can be called on any View in the same window as the View on which
21277     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
21278     * was called.
21279     * </p>
21280     */
21281    public final void cancelDragAndDrop() {
21282        if (ViewDebug.DEBUG_DRAG) {
21283            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
21284        }
21285        if (mAttachInfo == null) {
21286            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
21287            return;
21288        }
21289        if (mAttachInfo.mDragToken != null) {
21290            try {
21291                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
21292            } catch (Exception e) {
21293                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
21294            }
21295            mAttachInfo.mDragToken = null;
21296        } else {
21297            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
21298        }
21299    }
21300
21301    /**
21302     * Updates the drag shadow for the ongoing drag and drop operation.
21303     *
21304     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
21305     * new drag shadow.
21306     */
21307    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
21308        if (ViewDebug.DEBUG_DRAG) {
21309            Log.d(VIEW_LOG_TAG, "updateDragShadow");
21310        }
21311        if (mAttachInfo == null) {
21312            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
21313            return;
21314        }
21315        if (mAttachInfo.mDragToken != null) {
21316            try {
21317                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
21318                try {
21319                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
21320                    shadowBuilder.onDrawShadow(canvas);
21321                } finally {
21322                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
21323                }
21324            } catch (Exception e) {
21325                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
21326            }
21327        } else {
21328            Log.e(VIEW_LOG_TAG, "No active drag");
21329        }
21330    }
21331
21332    /**
21333     * Starts a move from {startX, startY}, the amount of the movement will be the offset
21334     * between {startX, startY} and the new cursor positon.
21335     * @param startX horizontal coordinate where the move started.
21336     * @param startY vertical coordinate where the move started.
21337     * @return whether moving was started successfully.
21338     * @hide
21339     */
21340    public final boolean startMovingTask(float startX, float startY) {
21341        if (ViewDebug.DEBUG_POSITIONING) {
21342            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
21343        }
21344        try {
21345            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
21346        } catch (RemoteException e) {
21347            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
21348        }
21349        return false;
21350    }
21351
21352    /**
21353     * Handles drag events sent by the system following a call to
21354     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
21355     * startDragAndDrop()}.
21356     *<p>
21357     * When the system calls this method, it passes a
21358     * {@link android.view.DragEvent} object. A call to
21359     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
21360     * in DragEvent. The method uses these to determine what is happening in the drag and drop
21361     * operation.
21362     * @param event The {@link android.view.DragEvent} sent by the system.
21363     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
21364     * in DragEvent, indicating the type of drag event represented by this object.
21365     * @return {@code true} if the method was successful, otherwise {@code false}.
21366     * <p>
21367     *  The method should return {@code true} in response to an action type of
21368     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
21369     *  operation.
21370     * </p>
21371     * <p>
21372     *  The method should also return {@code true} in response to an action type of
21373     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
21374     *  {@code false} if it didn't.
21375     * </p>
21376     * <p>
21377     *  For all other events, the return value is ignored.
21378     * </p>
21379     */
21380    public boolean onDragEvent(DragEvent event) {
21381        return false;
21382    }
21383
21384    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
21385    boolean dispatchDragEnterExitInPreN(DragEvent event) {
21386        return callDragEventHandler(event);
21387    }
21388
21389    /**
21390     * Detects if this View is enabled and has a drag event listener.
21391     * If both are true, then it calls the drag event listener with the
21392     * {@link android.view.DragEvent} it received. If the drag event listener returns
21393     * {@code true}, then dispatchDragEvent() returns {@code true}.
21394     * <p>
21395     * For all other cases, the method calls the
21396     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
21397     * method and returns its result.
21398     * </p>
21399     * <p>
21400     * This ensures that a drag event is always consumed, even if the View does not have a drag
21401     * event listener. However, if the View has a listener and the listener returns true, then
21402     * onDragEvent() is not called.
21403     * </p>
21404     */
21405    public boolean dispatchDragEvent(DragEvent event) {
21406        event.mEventHandlerWasCalled = true;
21407        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
21408            event.mAction == DragEvent.ACTION_DROP) {
21409            // About to deliver an event with coordinates to this view. Notify that now this view
21410            // has drag focus. This will send exit/enter events as needed.
21411            getViewRootImpl().setDragFocus(this, event);
21412        }
21413        return callDragEventHandler(event);
21414    }
21415
21416    final boolean callDragEventHandler(DragEvent event) {
21417        final boolean result;
21418
21419        ListenerInfo li = mListenerInfo;
21420        //noinspection SimplifiableIfStatement
21421        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
21422                && li.mOnDragListener.onDrag(this, event)) {
21423            result = true;
21424        } else {
21425            result = onDragEvent(event);
21426        }
21427
21428        switch (event.mAction) {
21429            case DragEvent.ACTION_DRAG_ENTERED: {
21430                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
21431                refreshDrawableState();
21432            } break;
21433            case DragEvent.ACTION_DRAG_EXITED: {
21434                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
21435                refreshDrawableState();
21436            } break;
21437            case DragEvent.ACTION_DRAG_ENDED: {
21438                mPrivateFlags2 &= ~View.DRAG_MASK;
21439                refreshDrawableState();
21440            } break;
21441        }
21442
21443        return result;
21444    }
21445
21446    boolean canAcceptDrag() {
21447        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
21448    }
21449
21450    /**
21451     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
21452     * it is ever exposed at all.
21453     * @hide
21454     */
21455    public void onCloseSystemDialogs(String reason) {
21456    }
21457
21458    /**
21459     * Given a Drawable whose bounds have been set to draw into this view,
21460     * update a Region being computed for
21461     * {@link #gatherTransparentRegion(android.graphics.Region)} so
21462     * that any non-transparent parts of the Drawable are removed from the
21463     * given transparent region.
21464     *
21465     * @param dr The Drawable whose transparency is to be applied to the region.
21466     * @param region A Region holding the current transparency information,
21467     * where any parts of the region that are set are considered to be
21468     * transparent.  On return, this region will be modified to have the
21469     * transparency information reduced by the corresponding parts of the
21470     * Drawable that are not transparent.
21471     * {@hide}
21472     */
21473    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
21474        if (DBG) {
21475            Log.i("View", "Getting transparent region for: " + this);
21476        }
21477        final Region r = dr.getTransparentRegion();
21478        final Rect db = dr.getBounds();
21479        final AttachInfo attachInfo = mAttachInfo;
21480        if (r != null && attachInfo != null) {
21481            final int w = getRight()-getLeft();
21482            final int h = getBottom()-getTop();
21483            if (db.left > 0) {
21484                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
21485                r.op(0, 0, db.left, h, Region.Op.UNION);
21486            }
21487            if (db.right < w) {
21488                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
21489                r.op(db.right, 0, w, h, Region.Op.UNION);
21490            }
21491            if (db.top > 0) {
21492                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
21493                r.op(0, 0, w, db.top, Region.Op.UNION);
21494            }
21495            if (db.bottom < h) {
21496                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
21497                r.op(0, db.bottom, w, h, Region.Op.UNION);
21498            }
21499            final int[] location = attachInfo.mTransparentLocation;
21500            getLocationInWindow(location);
21501            r.translate(location[0], location[1]);
21502            region.op(r, Region.Op.INTERSECT);
21503        } else {
21504            region.op(db, Region.Op.DIFFERENCE);
21505        }
21506    }
21507
21508    private void checkForLongClick(int delayOffset, float x, float y) {
21509        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
21510            mHasPerformedLongPress = false;
21511
21512            if (mPendingCheckForLongPress == null) {
21513                mPendingCheckForLongPress = new CheckForLongPress();
21514            }
21515            mPendingCheckForLongPress.setAnchor(x, y);
21516            mPendingCheckForLongPress.rememberWindowAttachCount();
21517            mPendingCheckForLongPress.rememberPressedState();
21518            postDelayed(mPendingCheckForLongPress,
21519                    ViewConfiguration.getLongPressTimeout() - delayOffset);
21520        }
21521    }
21522
21523    /**
21524     * Inflate a view from an XML resource.  This convenience method wraps the {@link
21525     * LayoutInflater} class, which provides a full range of options for view inflation.
21526     *
21527     * @param context The Context object for your activity or application.
21528     * @param resource The resource ID to inflate
21529     * @param root A view group that will be the parent.  Used to properly inflate the
21530     * layout_* parameters.
21531     * @see LayoutInflater
21532     */
21533    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
21534        LayoutInflater factory = LayoutInflater.from(context);
21535        return factory.inflate(resource, root);
21536    }
21537
21538    /**
21539     * Scroll the view with standard behavior for scrolling beyond the normal
21540     * content boundaries. Views that call this method should override
21541     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
21542     * results of an over-scroll operation.
21543     *
21544     * Views can use this method to handle any touch or fling-based scrolling.
21545     *
21546     * @param deltaX Change in X in pixels
21547     * @param deltaY Change in Y in pixels
21548     * @param scrollX Current X scroll value in pixels before applying deltaX
21549     * @param scrollY Current Y scroll value in pixels before applying deltaY
21550     * @param scrollRangeX Maximum content scroll range along the X axis
21551     * @param scrollRangeY Maximum content scroll range along the Y axis
21552     * @param maxOverScrollX Number of pixels to overscroll by in either direction
21553     *          along the X axis.
21554     * @param maxOverScrollY Number of pixels to overscroll by in either direction
21555     *          along the Y axis.
21556     * @param isTouchEvent true if this scroll operation is the result of a touch event.
21557     * @return true if scrolling was clamped to an over-scroll boundary along either
21558     *          axis, false otherwise.
21559     */
21560    @SuppressWarnings({"UnusedParameters"})
21561    protected boolean overScrollBy(int deltaX, int deltaY,
21562            int scrollX, int scrollY,
21563            int scrollRangeX, int scrollRangeY,
21564            int maxOverScrollX, int maxOverScrollY,
21565            boolean isTouchEvent) {
21566        final int overScrollMode = mOverScrollMode;
21567        final boolean canScrollHorizontal =
21568                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
21569        final boolean canScrollVertical =
21570                computeVerticalScrollRange() > computeVerticalScrollExtent();
21571        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
21572                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
21573        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
21574                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
21575
21576        int newScrollX = scrollX + deltaX;
21577        if (!overScrollHorizontal) {
21578            maxOverScrollX = 0;
21579        }
21580
21581        int newScrollY = scrollY + deltaY;
21582        if (!overScrollVertical) {
21583            maxOverScrollY = 0;
21584        }
21585
21586        // Clamp values if at the limits and record
21587        final int left = -maxOverScrollX;
21588        final int right = maxOverScrollX + scrollRangeX;
21589        final int top = -maxOverScrollY;
21590        final int bottom = maxOverScrollY + scrollRangeY;
21591
21592        boolean clampedX = false;
21593        if (newScrollX > right) {
21594            newScrollX = right;
21595            clampedX = true;
21596        } else if (newScrollX < left) {
21597            newScrollX = left;
21598            clampedX = true;
21599        }
21600
21601        boolean clampedY = false;
21602        if (newScrollY > bottom) {
21603            newScrollY = bottom;
21604            clampedY = true;
21605        } else if (newScrollY < top) {
21606            newScrollY = top;
21607            clampedY = true;
21608        }
21609
21610        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
21611
21612        return clampedX || clampedY;
21613    }
21614
21615    /**
21616     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
21617     * respond to the results of an over-scroll operation.
21618     *
21619     * @param scrollX New X scroll value in pixels
21620     * @param scrollY New Y scroll value in pixels
21621     * @param clampedX True if scrollX was clamped to an over-scroll boundary
21622     * @param clampedY True if scrollY was clamped to an over-scroll boundary
21623     */
21624    protected void onOverScrolled(int scrollX, int scrollY,
21625            boolean clampedX, boolean clampedY) {
21626        // Intentionally empty.
21627    }
21628
21629    /**
21630     * Returns the over-scroll mode for this view. The result will be
21631     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21632     * (allow over-scrolling only if the view content is larger than the container),
21633     * or {@link #OVER_SCROLL_NEVER}.
21634     *
21635     * @return This view's over-scroll mode.
21636     */
21637    public int getOverScrollMode() {
21638        return mOverScrollMode;
21639    }
21640
21641    /**
21642     * Set the over-scroll mode for this view. Valid over-scroll modes are
21643     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21644     * (allow over-scrolling only if the view content is larger than the container),
21645     * or {@link #OVER_SCROLL_NEVER}.
21646     *
21647     * Setting the over-scroll mode of a view will have an effect only if the
21648     * view is capable of scrolling.
21649     *
21650     * @param overScrollMode The new over-scroll mode for this view.
21651     */
21652    public void setOverScrollMode(int overScrollMode) {
21653        if (overScrollMode != OVER_SCROLL_ALWAYS &&
21654                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
21655                overScrollMode != OVER_SCROLL_NEVER) {
21656            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
21657        }
21658        mOverScrollMode = overScrollMode;
21659    }
21660
21661    /**
21662     * Enable or disable nested scrolling for this view.
21663     *
21664     * <p>If this property is set to true the view will be permitted to initiate nested
21665     * scrolling operations with a compatible parent view in the current hierarchy. If this
21666     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
21667     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
21668     * the nested scroll.</p>
21669     *
21670     * @param enabled true to enable nested scrolling, false to disable
21671     *
21672     * @see #isNestedScrollingEnabled()
21673     */
21674    public void setNestedScrollingEnabled(boolean enabled) {
21675        if (enabled) {
21676            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
21677        } else {
21678            stopNestedScroll();
21679            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
21680        }
21681    }
21682
21683    /**
21684     * Returns true if nested scrolling is enabled for this view.
21685     *
21686     * <p>If nested scrolling is enabled and this View class implementation supports it,
21687     * this view will act as a nested scrolling child view when applicable, forwarding data
21688     * about the scroll operation in progress to a compatible and cooperating nested scrolling
21689     * parent.</p>
21690     *
21691     * @return true if nested scrolling is enabled
21692     *
21693     * @see #setNestedScrollingEnabled(boolean)
21694     */
21695    public boolean isNestedScrollingEnabled() {
21696        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
21697                PFLAG3_NESTED_SCROLLING_ENABLED;
21698    }
21699
21700    /**
21701     * Begin a nestable scroll operation along the given axes.
21702     *
21703     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
21704     *
21705     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
21706     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
21707     * In the case of touch scrolling the nested scroll will be terminated automatically in
21708     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
21709     * In the event of programmatic scrolling the caller must explicitly call
21710     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
21711     *
21712     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
21713     * If it returns false the caller may ignore the rest of this contract until the next scroll.
21714     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
21715     *
21716     * <p>At each incremental step of the scroll the caller should invoke
21717     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
21718     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
21719     * parent at least partially consumed the scroll and the caller should adjust the amount it
21720     * scrolls by.</p>
21721     *
21722     * <p>After applying the remainder of the scroll delta the caller should invoke
21723     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
21724     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
21725     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
21726     * </p>
21727     *
21728     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
21729     *             {@link #SCROLL_AXIS_VERTICAL}.
21730     * @return true if a cooperative parent was found and nested scrolling has been enabled for
21731     *         the current gesture.
21732     *
21733     * @see #stopNestedScroll()
21734     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21735     * @see #dispatchNestedScroll(int, int, int, int, int[])
21736     */
21737    public boolean startNestedScroll(int axes) {
21738        if (hasNestedScrollingParent()) {
21739            // Already in progress
21740            return true;
21741        }
21742        if (isNestedScrollingEnabled()) {
21743            ViewParent p = getParent();
21744            View child = this;
21745            while (p != null) {
21746                try {
21747                    if (p.onStartNestedScroll(child, this, axes)) {
21748                        mNestedScrollingParent = p;
21749                        p.onNestedScrollAccepted(child, this, axes);
21750                        return true;
21751                    }
21752                } catch (AbstractMethodError e) {
21753                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
21754                            "method onStartNestedScroll", e);
21755                    // Allow the search upward to continue
21756                }
21757                if (p instanceof View) {
21758                    child = (View) p;
21759                }
21760                p = p.getParent();
21761            }
21762        }
21763        return false;
21764    }
21765
21766    /**
21767     * Stop a nested scroll in progress.
21768     *
21769     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
21770     *
21771     * @see #startNestedScroll(int)
21772     */
21773    public void stopNestedScroll() {
21774        if (mNestedScrollingParent != null) {
21775            mNestedScrollingParent.onStopNestedScroll(this);
21776            mNestedScrollingParent = null;
21777        }
21778    }
21779
21780    /**
21781     * Returns true if this view has a nested scrolling parent.
21782     *
21783     * <p>The presence of a nested scrolling parent indicates that this view has initiated
21784     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
21785     *
21786     * @return whether this view has a nested scrolling parent
21787     */
21788    public boolean hasNestedScrollingParent() {
21789        return mNestedScrollingParent != null;
21790    }
21791
21792    /**
21793     * Dispatch one step of a nested scroll in progress.
21794     *
21795     * <p>Implementations of views that support nested scrolling should call this to report
21796     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
21797     * is not currently in progress or nested scrolling is not
21798     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
21799     *
21800     * <p>Compatible View implementations should also call
21801     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
21802     * consuming a component of the scroll event themselves.</p>
21803     *
21804     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
21805     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
21806     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
21807     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
21808     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21809     *                       in local view coordinates of this view from before this operation
21810     *                       to after it completes. View implementations may use this to adjust
21811     *                       expected input coordinate tracking.
21812     * @return true if the event was dispatched, false if it could not be dispatched.
21813     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21814     */
21815    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
21816            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
21817        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21818            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
21819                int startX = 0;
21820                int startY = 0;
21821                if (offsetInWindow != null) {
21822                    getLocationInWindow(offsetInWindow);
21823                    startX = offsetInWindow[0];
21824                    startY = offsetInWindow[1];
21825                }
21826
21827                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
21828                        dxUnconsumed, dyUnconsumed);
21829
21830                if (offsetInWindow != null) {
21831                    getLocationInWindow(offsetInWindow);
21832                    offsetInWindow[0] -= startX;
21833                    offsetInWindow[1] -= startY;
21834                }
21835                return true;
21836            } else if (offsetInWindow != null) {
21837                // No motion, no dispatch. Keep offsetInWindow up to date.
21838                offsetInWindow[0] = 0;
21839                offsetInWindow[1] = 0;
21840            }
21841        }
21842        return false;
21843    }
21844
21845    /**
21846     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
21847     *
21848     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
21849     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
21850     * scrolling operation to consume some or all of the scroll operation before the child view
21851     * consumes it.</p>
21852     *
21853     * @param dx Horizontal scroll distance in pixels
21854     * @param dy Vertical scroll distance in pixels
21855     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
21856     *                 and consumed[1] the consumed dy.
21857     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21858     *                       in local view coordinates of this view from before this operation
21859     *                       to after it completes. View implementations may use this to adjust
21860     *                       expected input coordinate tracking.
21861     * @return true if the parent consumed some or all of the scroll delta
21862     * @see #dispatchNestedScroll(int, int, int, int, int[])
21863     */
21864    public boolean dispatchNestedPreScroll(int dx, int dy,
21865            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
21866        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21867            if (dx != 0 || dy != 0) {
21868                int startX = 0;
21869                int startY = 0;
21870                if (offsetInWindow != null) {
21871                    getLocationInWindow(offsetInWindow);
21872                    startX = offsetInWindow[0];
21873                    startY = offsetInWindow[1];
21874                }
21875
21876                if (consumed == null) {
21877                    if (mTempNestedScrollConsumed == null) {
21878                        mTempNestedScrollConsumed = new int[2];
21879                    }
21880                    consumed = mTempNestedScrollConsumed;
21881                }
21882                consumed[0] = 0;
21883                consumed[1] = 0;
21884                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
21885
21886                if (offsetInWindow != null) {
21887                    getLocationInWindow(offsetInWindow);
21888                    offsetInWindow[0] -= startX;
21889                    offsetInWindow[1] -= startY;
21890                }
21891                return consumed[0] != 0 || consumed[1] != 0;
21892            } else if (offsetInWindow != null) {
21893                offsetInWindow[0] = 0;
21894                offsetInWindow[1] = 0;
21895            }
21896        }
21897        return false;
21898    }
21899
21900    /**
21901     * Dispatch a fling to a nested scrolling parent.
21902     *
21903     * <p>This method should be used to indicate that a nested scrolling child has detected
21904     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
21905     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
21906     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
21907     * along a scrollable axis.</p>
21908     *
21909     * <p>If a nested scrolling child view would normally fling but it is at the edge of
21910     * its own content, it can use this method to delegate the fling to its nested scrolling
21911     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
21912     *
21913     * @param velocityX Horizontal fling velocity in pixels per second
21914     * @param velocityY Vertical fling velocity in pixels per second
21915     * @param consumed true if the child consumed the fling, false otherwise
21916     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
21917     */
21918    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
21919        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21920            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
21921        }
21922        return false;
21923    }
21924
21925    /**
21926     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
21927     *
21928     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
21929     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
21930     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
21931     * before the child view consumes it. If this method returns <code>true</code>, a nested
21932     * parent view consumed the fling and this view should not scroll as a result.</p>
21933     *
21934     * <p>For a better user experience, only one view in a nested scrolling chain should consume
21935     * the fling at a time. If a parent view consumed the fling this method will return false.
21936     * Custom view implementations should account for this in two ways:</p>
21937     *
21938     * <ul>
21939     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
21940     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
21941     *     position regardless.</li>
21942     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
21943     *     even to settle back to a valid idle position.</li>
21944     * </ul>
21945     *
21946     * <p>Views should also not offer fling velocities to nested parent views along an axis
21947     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
21948     * should not offer a horizontal fling velocity to its parents since scrolling along that
21949     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
21950     *
21951     * @param velocityX Horizontal fling velocity in pixels per second
21952     * @param velocityY Vertical fling velocity in pixels per second
21953     * @return true if a nested scrolling parent consumed the fling
21954     */
21955    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
21956        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21957            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
21958        }
21959        return false;
21960    }
21961
21962    /**
21963     * Gets a scale factor that determines the distance the view should scroll
21964     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
21965     * @return The vertical scroll scale factor.
21966     * @hide
21967     */
21968    protected float getVerticalScrollFactor() {
21969        if (mVerticalScrollFactor == 0) {
21970            TypedValue outValue = new TypedValue();
21971            if (!mContext.getTheme().resolveAttribute(
21972                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
21973                throw new IllegalStateException(
21974                        "Expected theme to define listPreferredItemHeight.");
21975            }
21976            mVerticalScrollFactor = outValue.getDimension(
21977                    mContext.getResources().getDisplayMetrics());
21978        }
21979        return mVerticalScrollFactor;
21980    }
21981
21982    /**
21983     * Gets a scale factor that determines the distance the view should scroll
21984     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
21985     * @return The horizontal scroll scale factor.
21986     * @hide
21987     */
21988    protected float getHorizontalScrollFactor() {
21989        // TODO: Should use something else.
21990        return getVerticalScrollFactor();
21991    }
21992
21993    /**
21994     * Return the value specifying the text direction or policy that was set with
21995     * {@link #setTextDirection(int)}.
21996     *
21997     * @return the defined text direction. It can be one of:
21998     *
21999     * {@link #TEXT_DIRECTION_INHERIT},
22000     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22001     * {@link #TEXT_DIRECTION_ANY_RTL},
22002     * {@link #TEXT_DIRECTION_LTR},
22003     * {@link #TEXT_DIRECTION_RTL},
22004     * {@link #TEXT_DIRECTION_LOCALE},
22005     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22006     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
22007     *
22008     * @attr ref android.R.styleable#View_textDirection
22009     *
22010     * @hide
22011     */
22012    @ViewDebug.ExportedProperty(category = "text", mapping = {
22013            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
22014            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
22015            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
22016            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
22017            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
22018            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
22019            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
22020            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
22021    })
22022    public int getRawTextDirection() {
22023        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
22024    }
22025
22026    /**
22027     * Set the text direction.
22028     *
22029     * @param textDirection the direction to set. Should be one of:
22030     *
22031     * {@link #TEXT_DIRECTION_INHERIT},
22032     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22033     * {@link #TEXT_DIRECTION_ANY_RTL},
22034     * {@link #TEXT_DIRECTION_LTR},
22035     * {@link #TEXT_DIRECTION_RTL},
22036     * {@link #TEXT_DIRECTION_LOCALE}
22037     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22038     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
22039     *
22040     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
22041     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
22042     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
22043     *
22044     * @attr ref android.R.styleable#View_textDirection
22045     */
22046    public void setTextDirection(int textDirection) {
22047        if (getRawTextDirection() != textDirection) {
22048            // Reset the current text direction and the resolved one
22049            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
22050            resetResolvedTextDirection();
22051            // Set the new text direction
22052            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
22053            // Do resolution
22054            resolveTextDirection();
22055            // Notify change
22056            onRtlPropertiesChanged(getLayoutDirection());
22057            // Refresh
22058            requestLayout();
22059            invalidate(true);
22060        }
22061    }
22062
22063    /**
22064     * Return the resolved text direction.
22065     *
22066     * @return the resolved text direction. Returns one of:
22067     *
22068     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22069     * {@link #TEXT_DIRECTION_ANY_RTL},
22070     * {@link #TEXT_DIRECTION_LTR},
22071     * {@link #TEXT_DIRECTION_RTL},
22072     * {@link #TEXT_DIRECTION_LOCALE},
22073     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22074     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
22075     *
22076     * @attr ref android.R.styleable#View_textDirection
22077     */
22078    @ViewDebug.ExportedProperty(category = "text", mapping = {
22079            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
22080            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
22081            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
22082            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
22083            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
22084            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
22085            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
22086            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
22087    })
22088    public int getTextDirection() {
22089        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
22090    }
22091
22092    /**
22093     * Resolve the text direction.
22094     *
22095     * @return true if resolution has been done, false otherwise.
22096     *
22097     * @hide
22098     */
22099    public boolean resolveTextDirection() {
22100        // Reset any previous text direction resolution
22101        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
22102
22103        if (hasRtlSupport()) {
22104            // Set resolved text direction flag depending on text direction flag
22105            final int textDirection = getRawTextDirection();
22106            switch(textDirection) {
22107                case TEXT_DIRECTION_INHERIT:
22108                    if (!canResolveTextDirection()) {
22109                        // We cannot do the resolution if there is no parent, so use the default one
22110                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22111                        // Resolution will need to happen again later
22112                        return false;
22113                    }
22114
22115                    // Parent has not yet resolved, so we still return the default
22116                    try {
22117                        if (!mParent.isTextDirectionResolved()) {
22118                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22119                            // Resolution will need to happen again later
22120                            return false;
22121                        }
22122                    } catch (AbstractMethodError e) {
22123                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22124                                " does not fully implement ViewParent", e);
22125                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
22126                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22127                        return true;
22128                    }
22129
22130                    // Set current resolved direction to the same value as the parent's one
22131                    int parentResolvedDirection;
22132                    try {
22133                        parentResolvedDirection = mParent.getTextDirection();
22134                    } catch (AbstractMethodError e) {
22135                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22136                                " does not fully implement ViewParent", e);
22137                        parentResolvedDirection = TEXT_DIRECTION_LTR;
22138                    }
22139                    switch (parentResolvedDirection) {
22140                        case TEXT_DIRECTION_FIRST_STRONG:
22141                        case TEXT_DIRECTION_ANY_RTL:
22142                        case TEXT_DIRECTION_LTR:
22143                        case TEXT_DIRECTION_RTL:
22144                        case TEXT_DIRECTION_LOCALE:
22145                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
22146                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
22147                            mPrivateFlags2 |=
22148                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
22149                            break;
22150                        default:
22151                            // Default resolved direction is "first strong" heuristic
22152                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22153                    }
22154                    break;
22155                case TEXT_DIRECTION_FIRST_STRONG:
22156                case TEXT_DIRECTION_ANY_RTL:
22157                case TEXT_DIRECTION_LTR:
22158                case TEXT_DIRECTION_RTL:
22159                case TEXT_DIRECTION_LOCALE:
22160                case TEXT_DIRECTION_FIRST_STRONG_LTR:
22161                case TEXT_DIRECTION_FIRST_STRONG_RTL:
22162                    // Resolved direction is the same as text direction
22163                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
22164                    break;
22165                default:
22166                    // Default resolved direction is "first strong" heuristic
22167                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22168            }
22169        } else {
22170            // Default resolved direction is "first strong" heuristic
22171            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22172        }
22173
22174        // Set to resolved
22175        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
22176        return true;
22177    }
22178
22179    /**
22180     * Check if text direction resolution can be done.
22181     *
22182     * @return true if text direction resolution can be done otherwise return false.
22183     */
22184    public boolean canResolveTextDirection() {
22185        switch (getRawTextDirection()) {
22186            case TEXT_DIRECTION_INHERIT:
22187                if (mParent != null) {
22188                    try {
22189                        return mParent.canResolveTextDirection();
22190                    } catch (AbstractMethodError e) {
22191                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22192                                " does not fully implement ViewParent", e);
22193                    }
22194                }
22195                return false;
22196
22197            default:
22198                return true;
22199        }
22200    }
22201
22202    /**
22203     * Reset resolved text direction. Text direction will be resolved during a call to
22204     * {@link #onMeasure(int, int)}.
22205     *
22206     * @hide
22207     */
22208    public void resetResolvedTextDirection() {
22209        // Reset any previous text direction resolution
22210        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
22211        // Set to default value
22212        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22213    }
22214
22215    /**
22216     * @return true if text direction is inherited.
22217     *
22218     * @hide
22219     */
22220    public boolean isTextDirectionInherited() {
22221        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
22222    }
22223
22224    /**
22225     * @return true if text direction is resolved.
22226     */
22227    public boolean isTextDirectionResolved() {
22228        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
22229    }
22230
22231    /**
22232     * Return the value specifying the text alignment or policy that was set with
22233     * {@link #setTextAlignment(int)}.
22234     *
22235     * @return the defined text alignment. It can be one of:
22236     *
22237     * {@link #TEXT_ALIGNMENT_INHERIT},
22238     * {@link #TEXT_ALIGNMENT_GRAVITY},
22239     * {@link #TEXT_ALIGNMENT_CENTER},
22240     * {@link #TEXT_ALIGNMENT_TEXT_START},
22241     * {@link #TEXT_ALIGNMENT_TEXT_END},
22242     * {@link #TEXT_ALIGNMENT_VIEW_START},
22243     * {@link #TEXT_ALIGNMENT_VIEW_END}
22244     *
22245     * @attr ref android.R.styleable#View_textAlignment
22246     *
22247     * @hide
22248     */
22249    @ViewDebug.ExportedProperty(category = "text", mapping = {
22250            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
22251            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
22252            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
22253            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
22254            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
22255            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
22256            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
22257    })
22258    @TextAlignment
22259    public int getRawTextAlignment() {
22260        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
22261    }
22262
22263    /**
22264     * Set the text alignment.
22265     *
22266     * @param textAlignment The text alignment to set. Should be one of
22267     *
22268     * {@link #TEXT_ALIGNMENT_INHERIT},
22269     * {@link #TEXT_ALIGNMENT_GRAVITY},
22270     * {@link #TEXT_ALIGNMENT_CENTER},
22271     * {@link #TEXT_ALIGNMENT_TEXT_START},
22272     * {@link #TEXT_ALIGNMENT_TEXT_END},
22273     * {@link #TEXT_ALIGNMENT_VIEW_START},
22274     * {@link #TEXT_ALIGNMENT_VIEW_END}
22275     *
22276     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
22277     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
22278     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
22279     *
22280     * @attr ref android.R.styleable#View_textAlignment
22281     */
22282    public void setTextAlignment(@TextAlignment int textAlignment) {
22283        if (textAlignment != getRawTextAlignment()) {
22284            // Reset the current and resolved text alignment
22285            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
22286            resetResolvedTextAlignment();
22287            // Set the new text alignment
22288            mPrivateFlags2 |=
22289                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
22290            // Do resolution
22291            resolveTextAlignment();
22292            // Notify change
22293            onRtlPropertiesChanged(getLayoutDirection());
22294            // Refresh
22295            requestLayout();
22296            invalidate(true);
22297        }
22298    }
22299
22300    /**
22301     * Return the resolved text alignment.
22302     *
22303     * @return the resolved text alignment. Returns one of:
22304     *
22305     * {@link #TEXT_ALIGNMENT_GRAVITY},
22306     * {@link #TEXT_ALIGNMENT_CENTER},
22307     * {@link #TEXT_ALIGNMENT_TEXT_START},
22308     * {@link #TEXT_ALIGNMENT_TEXT_END},
22309     * {@link #TEXT_ALIGNMENT_VIEW_START},
22310     * {@link #TEXT_ALIGNMENT_VIEW_END}
22311     *
22312     * @attr ref android.R.styleable#View_textAlignment
22313     */
22314    @ViewDebug.ExportedProperty(category = "text", mapping = {
22315            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
22316            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
22317            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
22318            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
22319            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
22320            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
22321            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
22322    })
22323    @TextAlignment
22324    public int getTextAlignment() {
22325        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
22326                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
22327    }
22328
22329    /**
22330     * Resolve the text alignment.
22331     *
22332     * @return true if resolution has been done, false otherwise.
22333     *
22334     * @hide
22335     */
22336    public boolean resolveTextAlignment() {
22337        // Reset any previous text alignment resolution
22338        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
22339
22340        if (hasRtlSupport()) {
22341            // Set resolved text alignment flag depending on text alignment flag
22342            final int textAlignment = getRawTextAlignment();
22343            switch (textAlignment) {
22344                case TEXT_ALIGNMENT_INHERIT:
22345                    // Check if we can resolve the text alignment
22346                    if (!canResolveTextAlignment()) {
22347                        // We cannot do the resolution if there is no parent so use the default
22348                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22349                        // Resolution will need to happen again later
22350                        return false;
22351                    }
22352
22353                    // Parent has not yet resolved, so we still return the default
22354                    try {
22355                        if (!mParent.isTextAlignmentResolved()) {
22356                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22357                            // Resolution will need to happen again later
22358                            return false;
22359                        }
22360                    } catch (AbstractMethodError e) {
22361                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22362                                " does not fully implement ViewParent", e);
22363                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
22364                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22365                        return true;
22366                    }
22367
22368                    int parentResolvedTextAlignment;
22369                    try {
22370                        parentResolvedTextAlignment = mParent.getTextAlignment();
22371                    } catch (AbstractMethodError e) {
22372                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22373                                " does not fully implement ViewParent", e);
22374                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
22375                    }
22376                    switch (parentResolvedTextAlignment) {
22377                        case TEXT_ALIGNMENT_GRAVITY:
22378                        case TEXT_ALIGNMENT_TEXT_START:
22379                        case TEXT_ALIGNMENT_TEXT_END:
22380                        case TEXT_ALIGNMENT_CENTER:
22381                        case TEXT_ALIGNMENT_VIEW_START:
22382                        case TEXT_ALIGNMENT_VIEW_END:
22383                            // Resolved text alignment is the same as the parent resolved
22384                            // text alignment
22385                            mPrivateFlags2 |=
22386                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
22387                            break;
22388                        default:
22389                            // Use default resolved text alignment
22390                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22391                    }
22392                    break;
22393                case TEXT_ALIGNMENT_GRAVITY:
22394                case TEXT_ALIGNMENT_TEXT_START:
22395                case TEXT_ALIGNMENT_TEXT_END:
22396                case TEXT_ALIGNMENT_CENTER:
22397                case TEXT_ALIGNMENT_VIEW_START:
22398                case TEXT_ALIGNMENT_VIEW_END:
22399                    // Resolved text alignment is the same as text alignment
22400                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
22401                    break;
22402                default:
22403                    // Use default resolved text alignment
22404                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22405            }
22406        } else {
22407            // Use default resolved text alignment
22408            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22409        }
22410
22411        // Set the resolved
22412        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
22413        return true;
22414    }
22415
22416    /**
22417     * Check if text alignment resolution can be done.
22418     *
22419     * @return true if text alignment resolution can be done otherwise return false.
22420     */
22421    public boolean canResolveTextAlignment() {
22422        switch (getRawTextAlignment()) {
22423            case TEXT_DIRECTION_INHERIT:
22424                if (mParent != null) {
22425                    try {
22426                        return mParent.canResolveTextAlignment();
22427                    } catch (AbstractMethodError e) {
22428                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22429                                " does not fully implement ViewParent", e);
22430                    }
22431                }
22432                return false;
22433
22434            default:
22435                return true;
22436        }
22437    }
22438
22439    /**
22440     * Reset resolved text alignment. Text alignment will be resolved during a call to
22441     * {@link #onMeasure(int, int)}.
22442     *
22443     * @hide
22444     */
22445    public void resetResolvedTextAlignment() {
22446        // Reset any previous text alignment resolution
22447        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
22448        // Set to default
22449        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22450    }
22451
22452    /**
22453     * @return true if text alignment is inherited.
22454     *
22455     * @hide
22456     */
22457    public boolean isTextAlignmentInherited() {
22458        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
22459    }
22460
22461    /**
22462     * @return true if text alignment is resolved.
22463     */
22464    public boolean isTextAlignmentResolved() {
22465        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
22466    }
22467
22468    /**
22469     * Generate a value suitable for use in {@link #setId(int)}.
22470     * This value will not collide with ID values generated at build time by aapt for R.id.
22471     *
22472     * @return a generated ID value
22473     */
22474    public static int generateViewId() {
22475        for (;;) {
22476            final int result = sNextGeneratedId.get();
22477            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
22478            int newValue = result + 1;
22479            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
22480            if (sNextGeneratedId.compareAndSet(result, newValue)) {
22481                return result;
22482            }
22483        }
22484    }
22485
22486    /**
22487     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
22488     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
22489     *                           a normal View or a ViewGroup with
22490     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
22491     * @hide
22492     */
22493    public void captureTransitioningViews(List<View> transitioningViews) {
22494        if (getVisibility() == View.VISIBLE) {
22495            transitioningViews.add(this);
22496        }
22497    }
22498
22499    /**
22500     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
22501     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
22502     * @hide
22503     */
22504    public void findNamedViews(Map<String, View> namedElements) {
22505        if (getVisibility() == VISIBLE || mGhostView != null) {
22506            String transitionName = getTransitionName();
22507            if (transitionName != null) {
22508                namedElements.put(transitionName, this);
22509            }
22510        }
22511    }
22512
22513    /**
22514     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
22515     * The default implementation does not care the location or event types, but some subclasses
22516     * may use it (such as WebViews).
22517     * @param event The MotionEvent from a mouse
22518     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
22519     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
22520     * @see PointerIcon
22521     */
22522    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
22523        final float x = event.getX(pointerIndex);
22524        final float y = event.getY(pointerIndex);
22525        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
22526            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
22527        }
22528        return mPointerIcon;
22529    }
22530
22531    /**
22532     * Set the pointer icon for the current view.
22533     * Passing {@code null} will restore the pointer icon to its default value.
22534     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
22535     */
22536    public void setPointerIcon(PointerIcon pointerIcon) {
22537        mPointerIcon = pointerIcon;
22538        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
22539            return;
22540        }
22541        try {
22542            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
22543        } catch (RemoteException e) {
22544        }
22545    }
22546
22547    /**
22548     * Gets the pointer icon for the current view.
22549     */
22550    public PointerIcon getPointerIcon() {
22551        return mPointerIcon;
22552    }
22553
22554    //
22555    // Properties
22556    //
22557    /**
22558     * A Property wrapper around the <code>alpha</code> functionality handled by the
22559     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
22560     */
22561    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
22562        @Override
22563        public void setValue(View object, float value) {
22564            object.setAlpha(value);
22565        }
22566
22567        @Override
22568        public Float get(View object) {
22569            return object.getAlpha();
22570        }
22571    };
22572
22573    /**
22574     * A Property wrapper around the <code>translationX</code> functionality handled by the
22575     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
22576     */
22577    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
22578        @Override
22579        public void setValue(View object, float value) {
22580            object.setTranslationX(value);
22581        }
22582
22583                @Override
22584        public Float get(View object) {
22585            return object.getTranslationX();
22586        }
22587    };
22588
22589    /**
22590     * A Property wrapper around the <code>translationY</code> functionality handled by the
22591     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
22592     */
22593    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
22594        @Override
22595        public void setValue(View object, float value) {
22596            object.setTranslationY(value);
22597        }
22598
22599        @Override
22600        public Float get(View object) {
22601            return object.getTranslationY();
22602        }
22603    };
22604
22605    /**
22606     * A Property wrapper around the <code>translationZ</code> functionality handled by the
22607     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
22608     */
22609    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
22610        @Override
22611        public void setValue(View object, float value) {
22612            object.setTranslationZ(value);
22613        }
22614
22615        @Override
22616        public Float get(View object) {
22617            return object.getTranslationZ();
22618        }
22619    };
22620
22621    /**
22622     * A Property wrapper around the <code>x</code> functionality handled by the
22623     * {@link View#setX(float)} and {@link View#getX()} methods.
22624     */
22625    public static final Property<View, Float> X = new FloatProperty<View>("x") {
22626        @Override
22627        public void setValue(View object, float value) {
22628            object.setX(value);
22629        }
22630
22631        @Override
22632        public Float get(View object) {
22633            return object.getX();
22634        }
22635    };
22636
22637    /**
22638     * A Property wrapper around the <code>y</code> functionality handled by the
22639     * {@link View#setY(float)} and {@link View#getY()} methods.
22640     */
22641    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
22642        @Override
22643        public void setValue(View object, float value) {
22644            object.setY(value);
22645        }
22646
22647        @Override
22648        public Float get(View object) {
22649            return object.getY();
22650        }
22651    };
22652
22653    /**
22654     * A Property wrapper around the <code>z</code> functionality handled by the
22655     * {@link View#setZ(float)} and {@link View#getZ()} methods.
22656     */
22657    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
22658        @Override
22659        public void setValue(View object, float value) {
22660            object.setZ(value);
22661        }
22662
22663        @Override
22664        public Float get(View object) {
22665            return object.getZ();
22666        }
22667    };
22668
22669    /**
22670     * A Property wrapper around the <code>rotation</code> functionality handled by the
22671     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
22672     */
22673    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
22674        @Override
22675        public void setValue(View object, float value) {
22676            object.setRotation(value);
22677        }
22678
22679        @Override
22680        public Float get(View object) {
22681            return object.getRotation();
22682        }
22683    };
22684
22685    /**
22686     * A Property wrapper around the <code>rotationX</code> functionality handled by the
22687     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
22688     */
22689    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
22690        @Override
22691        public void setValue(View object, float value) {
22692            object.setRotationX(value);
22693        }
22694
22695        @Override
22696        public Float get(View object) {
22697            return object.getRotationX();
22698        }
22699    };
22700
22701    /**
22702     * A Property wrapper around the <code>rotationY</code> functionality handled by the
22703     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
22704     */
22705    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
22706        @Override
22707        public void setValue(View object, float value) {
22708            object.setRotationY(value);
22709        }
22710
22711        @Override
22712        public Float get(View object) {
22713            return object.getRotationY();
22714        }
22715    };
22716
22717    /**
22718     * A Property wrapper around the <code>scaleX</code> functionality handled by the
22719     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
22720     */
22721    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
22722        @Override
22723        public void setValue(View object, float value) {
22724            object.setScaleX(value);
22725        }
22726
22727        @Override
22728        public Float get(View object) {
22729            return object.getScaleX();
22730        }
22731    };
22732
22733    /**
22734     * A Property wrapper around the <code>scaleY</code> functionality handled by the
22735     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
22736     */
22737    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
22738        @Override
22739        public void setValue(View object, float value) {
22740            object.setScaleY(value);
22741        }
22742
22743        @Override
22744        public Float get(View object) {
22745            return object.getScaleY();
22746        }
22747    };
22748
22749    /**
22750     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
22751     * Each MeasureSpec represents a requirement for either the width or the height.
22752     * A MeasureSpec is comprised of a size and a mode. There are three possible
22753     * modes:
22754     * <dl>
22755     * <dt>UNSPECIFIED</dt>
22756     * <dd>
22757     * The parent has not imposed any constraint on the child. It can be whatever size
22758     * it wants.
22759     * </dd>
22760     *
22761     * <dt>EXACTLY</dt>
22762     * <dd>
22763     * The parent has determined an exact size for the child. The child is going to be
22764     * given those bounds regardless of how big it wants to be.
22765     * </dd>
22766     *
22767     * <dt>AT_MOST</dt>
22768     * <dd>
22769     * The child can be as large as it wants up to the specified size.
22770     * </dd>
22771     * </dl>
22772     *
22773     * MeasureSpecs are implemented as ints to reduce object allocation. This class
22774     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
22775     */
22776    public static class MeasureSpec {
22777        private static final int MODE_SHIFT = 30;
22778        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
22779
22780        /** @hide */
22781        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
22782        @Retention(RetentionPolicy.SOURCE)
22783        public @interface MeasureSpecMode {}
22784
22785        /**
22786         * Measure specification mode: The parent has not imposed any constraint
22787         * on the child. It can be whatever size it wants.
22788         */
22789        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
22790
22791        /**
22792         * Measure specification mode: The parent has determined an exact size
22793         * for the child. The child is going to be given those bounds regardless
22794         * of how big it wants to be.
22795         */
22796        public static final int EXACTLY     = 1 << MODE_SHIFT;
22797
22798        /**
22799         * Measure specification mode: The child can be as large as it wants up
22800         * to the specified size.
22801         */
22802        public static final int AT_MOST     = 2 << MODE_SHIFT;
22803
22804        /**
22805         * Creates a measure specification based on the supplied size and mode.
22806         *
22807         * The mode must always be one of the following:
22808         * <ul>
22809         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
22810         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
22811         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
22812         * </ul>
22813         *
22814         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
22815         * implementation was such that the order of arguments did not matter
22816         * and overflow in either value could impact the resulting MeasureSpec.
22817         * {@link android.widget.RelativeLayout} was affected by this bug.
22818         * Apps targeting API levels greater than 17 will get the fixed, more strict
22819         * behavior.</p>
22820         *
22821         * @param size the size of the measure specification
22822         * @param mode the mode of the measure specification
22823         * @return the measure specification based on size and mode
22824         */
22825        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
22826                                          @MeasureSpecMode int mode) {
22827            if (sUseBrokenMakeMeasureSpec) {
22828                return size + mode;
22829            } else {
22830                return (size & ~MODE_MASK) | (mode & MODE_MASK);
22831            }
22832        }
22833
22834        /**
22835         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
22836         * will automatically get a size of 0. Older apps expect this.
22837         *
22838         * @hide internal use only for compatibility with system widgets and older apps
22839         */
22840        public static int makeSafeMeasureSpec(int size, int mode) {
22841            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
22842                return 0;
22843            }
22844            return makeMeasureSpec(size, mode);
22845        }
22846
22847        /**
22848         * Extracts the mode from the supplied measure specification.
22849         *
22850         * @param measureSpec the measure specification to extract the mode from
22851         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
22852         *         {@link android.view.View.MeasureSpec#AT_MOST} or
22853         *         {@link android.view.View.MeasureSpec#EXACTLY}
22854         */
22855        @MeasureSpecMode
22856        public static int getMode(int measureSpec) {
22857            //noinspection ResourceType
22858            return (measureSpec & MODE_MASK);
22859        }
22860
22861        /**
22862         * Extracts the size from the supplied measure specification.
22863         *
22864         * @param measureSpec the measure specification to extract the size from
22865         * @return the size in pixels defined in the supplied measure specification
22866         */
22867        public static int getSize(int measureSpec) {
22868            return (measureSpec & ~MODE_MASK);
22869        }
22870
22871        static int adjust(int measureSpec, int delta) {
22872            final int mode = getMode(measureSpec);
22873            int size = getSize(measureSpec);
22874            if (mode == UNSPECIFIED) {
22875                // No need to adjust size for UNSPECIFIED mode.
22876                return makeMeasureSpec(size, UNSPECIFIED);
22877            }
22878            size += delta;
22879            if (size < 0) {
22880                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
22881                        ") spec: " + toString(measureSpec) + " delta: " + delta);
22882                size = 0;
22883            }
22884            return makeMeasureSpec(size, mode);
22885        }
22886
22887        /**
22888         * Returns a String representation of the specified measure
22889         * specification.
22890         *
22891         * @param measureSpec the measure specification to convert to a String
22892         * @return a String with the following format: "MeasureSpec: MODE SIZE"
22893         */
22894        public static String toString(int measureSpec) {
22895            int mode = getMode(measureSpec);
22896            int size = getSize(measureSpec);
22897
22898            StringBuilder sb = new StringBuilder("MeasureSpec: ");
22899
22900            if (mode == UNSPECIFIED)
22901                sb.append("UNSPECIFIED ");
22902            else if (mode == EXACTLY)
22903                sb.append("EXACTLY ");
22904            else if (mode == AT_MOST)
22905                sb.append("AT_MOST ");
22906            else
22907                sb.append(mode).append(" ");
22908
22909            sb.append(size);
22910            return sb.toString();
22911        }
22912    }
22913
22914    private final class CheckForLongPress implements Runnable {
22915        private int mOriginalWindowAttachCount;
22916        private float mX;
22917        private float mY;
22918        private boolean mOriginalPressedState;
22919
22920        @Override
22921        public void run() {
22922            if ((mOriginalPressedState == isPressed()) && (mParent != null)
22923                    && mOriginalWindowAttachCount == mWindowAttachCount) {
22924                if (performLongClick(mX, mY)) {
22925                    mHasPerformedLongPress = true;
22926                }
22927            }
22928        }
22929
22930        public void setAnchor(float x, float y) {
22931            mX = x;
22932            mY = y;
22933        }
22934
22935        public void rememberWindowAttachCount() {
22936            mOriginalWindowAttachCount = mWindowAttachCount;
22937        }
22938
22939        public void rememberPressedState() {
22940            mOriginalPressedState = isPressed();
22941        }
22942    }
22943
22944    private final class CheckForTap implements Runnable {
22945        public float x;
22946        public float y;
22947
22948        @Override
22949        public void run() {
22950            mPrivateFlags &= ~PFLAG_PREPRESSED;
22951            setPressed(true, x, y);
22952            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
22953        }
22954    }
22955
22956    private final class PerformClick implements Runnable {
22957        @Override
22958        public void run() {
22959            performClick();
22960        }
22961    }
22962
22963    /**
22964     * This method returns a ViewPropertyAnimator object, which can be used to animate
22965     * specific properties on this View.
22966     *
22967     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
22968     */
22969    public ViewPropertyAnimator animate() {
22970        if (mAnimator == null) {
22971            mAnimator = new ViewPropertyAnimator(this);
22972        }
22973        return mAnimator;
22974    }
22975
22976    /**
22977     * Sets the name of the View to be used to identify Views in Transitions.
22978     * Names should be unique in the View hierarchy.
22979     *
22980     * @param transitionName The name of the View to uniquely identify it for Transitions.
22981     */
22982    public final void setTransitionName(String transitionName) {
22983        mTransitionName = transitionName;
22984    }
22985
22986    /**
22987     * Returns the name of the View to be used to identify Views in Transitions.
22988     * Names should be unique in the View hierarchy.
22989     *
22990     * <p>This returns null if the View has not been given a name.</p>
22991     *
22992     * @return The name used of the View to be used to identify Views in Transitions or null
22993     * if no name has been given.
22994     */
22995    @ViewDebug.ExportedProperty
22996    public String getTransitionName() {
22997        return mTransitionName;
22998    }
22999
23000    /**
23001     * @hide
23002     */
23003    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
23004        // Do nothing.
23005    }
23006
23007    /**
23008     * Interface definition for a callback to be invoked when a hardware key event is
23009     * dispatched to this view. The callback will be invoked before the key event is
23010     * given to the view. This is only useful for hardware keyboards; a software input
23011     * method has no obligation to trigger this listener.
23012     */
23013    public interface OnKeyListener {
23014        /**
23015         * Called when a hardware key is dispatched to a view. This allows listeners to
23016         * get a chance to respond before the target view.
23017         * <p>Key presses in software keyboards will generally NOT trigger this method,
23018         * although some may elect to do so in some situations. Do not assume a
23019         * software input method has to be key-based; even if it is, it may use key presses
23020         * in a different way than you expect, so there is no way to reliably catch soft
23021         * input key presses.
23022         *
23023         * @param v The view the key has been dispatched to.
23024         * @param keyCode The code for the physical key that was pressed
23025         * @param event The KeyEvent object containing full information about
23026         *        the event.
23027         * @return True if the listener has consumed the event, false otherwise.
23028         */
23029        boolean onKey(View v, int keyCode, KeyEvent event);
23030    }
23031
23032    /**
23033     * Interface definition for a callback to be invoked when a touch event is
23034     * dispatched to this view. The callback will be invoked before the touch
23035     * event is given to the view.
23036     */
23037    public interface OnTouchListener {
23038        /**
23039         * Called when a touch event is dispatched to a view. This allows listeners to
23040         * get a chance to respond before the target view.
23041         *
23042         * @param v The view the touch event has been dispatched to.
23043         * @param event The MotionEvent object containing full information about
23044         *        the event.
23045         * @return True if the listener has consumed the event, false otherwise.
23046         */
23047        boolean onTouch(View v, MotionEvent event);
23048    }
23049
23050    /**
23051     * Interface definition for a callback to be invoked when a hover event is
23052     * dispatched to this view. The callback will be invoked before the hover
23053     * event is given to the view.
23054     */
23055    public interface OnHoverListener {
23056        /**
23057         * Called when a hover event is dispatched to a view. This allows listeners to
23058         * get a chance to respond before the target view.
23059         *
23060         * @param v The view the hover event has been dispatched to.
23061         * @param event The MotionEvent object containing full information about
23062         *        the event.
23063         * @return True if the listener has consumed the event, false otherwise.
23064         */
23065        boolean onHover(View v, MotionEvent event);
23066    }
23067
23068    /**
23069     * Interface definition for a callback to be invoked when a generic motion event is
23070     * dispatched to this view. The callback will be invoked before the generic motion
23071     * event is given to the view.
23072     */
23073    public interface OnGenericMotionListener {
23074        /**
23075         * Called when a generic motion event is dispatched to a view. This allows listeners to
23076         * get a chance to respond before the target view.
23077         *
23078         * @param v The view the generic motion event has been dispatched to.
23079         * @param event The MotionEvent object containing full information about
23080         *        the event.
23081         * @return True if the listener has consumed the event, false otherwise.
23082         */
23083        boolean onGenericMotion(View v, MotionEvent event);
23084    }
23085
23086    /**
23087     * Interface definition for a callback to be invoked when a view has been clicked and held.
23088     */
23089    public interface OnLongClickListener {
23090        /**
23091         * Called when a view has been clicked and held.
23092         *
23093         * @param v The view that was clicked and held.
23094         *
23095         * @return true if the callback consumed the long click, false otherwise.
23096         */
23097        boolean onLongClick(View v);
23098    }
23099
23100    /**
23101     * Interface definition for a callback to be invoked when a drag is being dispatched
23102     * to this view.  The callback will be invoked before the hosting view's own
23103     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
23104     * onDrag(event) behavior, it should return 'false' from this callback.
23105     *
23106     * <div class="special reference">
23107     * <h3>Developer Guides</h3>
23108     * <p>For a guide to implementing drag and drop features, read the
23109     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
23110     * </div>
23111     */
23112    public interface OnDragListener {
23113        /**
23114         * Called when a drag event is dispatched to a view. This allows listeners
23115         * to get a chance to override base View behavior.
23116         *
23117         * @param v The View that received the drag event.
23118         * @param event The {@link android.view.DragEvent} object for the drag event.
23119         * @return {@code true} if the drag event was handled successfully, or {@code false}
23120         * if the drag event was not handled. Note that {@code false} will trigger the View
23121         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
23122         */
23123        boolean onDrag(View v, DragEvent event);
23124    }
23125
23126    /**
23127     * Interface definition for a callback to be invoked when the focus state of
23128     * a view changed.
23129     */
23130    public interface OnFocusChangeListener {
23131        /**
23132         * Called when the focus state of a view has changed.
23133         *
23134         * @param v The view whose state has changed.
23135         * @param hasFocus The new focus state of v.
23136         */
23137        void onFocusChange(View v, boolean hasFocus);
23138    }
23139
23140    /**
23141     * Interface definition for a callback to be invoked when a view is clicked.
23142     */
23143    public interface OnClickListener {
23144        /**
23145         * Called when a view has been clicked.
23146         *
23147         * @param v The view that was clicked.
23148         */
23149        void onClick(View v);
23150    }
23151
23152    /**
23153     * Interface definition for a callback to be invoked when a view is context clicked.
23154     */
23155    public interface OnContextClickListener {
23156        /**
23157         * Called when a view is context clicked.
23158         *
23159         * @param v The view that has been context clicked.
23160         * @return true if the callback consumed the context click, false otherwise.
23161         */
23162        boolean onContextClick(View v);
23163    }
23164
23165    /**
23166     * Interface definition for a callback to be invoked when the context menu
23167     * for this view is being built.
23168     */
23169    public interface OnCreateContextMenuListener {
23170        /**
23171         * Called when the context menu for this view is being built. It is not
23172         * safe to hold onto the menu after this method returns.
23173         *
23174         * @param menu The context menu that is being built
23175         * @param v The view for which the context menu is being built
23176         * @param menuInfo Extra information about the item for which the
23177         *            context menu should be shown. This information will vary
23178         *            depending on the class of v.
23179         */
23180        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
23181    }
23182
23183    /**
23184     * Interface definition for a callback to be invoked when the status bar changes
23185     * visibility.  This reports <strong>global</strong> changes to the system UI
23186     * state, not what the application is requesting.
23187     *
23188     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
23189     */
23190    public interface OnSystemUiVisibilityChangeListener {
23191        /**
23192         * Called when the status bar changes visibility because of a call to
23193         * {@link View#setSystemUiVisibility(int)}.
23194         *
23195         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
23196         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
23197         * This tells you the <strong>global</strong> state of these UI visibility
23198         * flags, not what your app is currently applying.
23199         */
23200        public void onSystemUiVisibilityChange(int visibility);
23201    }
23202
23203    /**
23204     * Interface definition for a callback to be invoked when this view is attached
23205     * or detached from its window.
23206     */
23207    public interface OnAttachStateChangeListener {
23208        /**
23209         * Called when the view is attached to a window.
23210         * @param v The view that was attached
23211         */
23212        public void onViewAttachedToWindow(View v);
23213        /**
23214         * Called when the view is detached from a window.
23215         * @param v The view that was detached
23216         */
23217        public void onViewDetachedFromWindow(View v);
23218    }
23219
23220    /**
23221     * Listener for applying window insets on a view in a custom way.
23222     *
23223     * <p>Apps may choose to implement this interface if they want to apply custom policy
23224     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
23225     * is set, its
23226     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
23227     * method will be called instead of the View's own
23228     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
23229     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
23230     * the View's normal behavior as part of its own.</p>
23231     */
23232    public interface OnApplyWindowInsetsListener {
23233        /**
23234         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
23235         * on a View, this listener method will be called instead of the view's own
23236         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
23237         *
23238         * @param v The view applying window insets
23239         * @param insets The insets to apply
23240         * @return The insets supplied, minus any insets that were consumed
23241         */
23242        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
23243    }
23244
23245    private final class UnsetPressedState implements Runnable {
23246        @Override
23247        public void run() {
23248            setPressed(false);
23249        }
23250    }
23251
23252    /**
23253     * Base class for derived classes that want to save and restore their own
23254     * state in {@link android.view.View#onSaveInstanceState()}.
23255     */
23256    public static class BaseSavedState extends AbsSavedState {
23257        String mStartActivityRequestWhoSaved;
23258
23259        /**
23260         * Constructor used when reading from a parcel. Reads the state of the superclass.
23261         *
23262         * @param source parcel to read from
23263         */
23264        public BaseSavedState(Parcel source) {
23265            this(source, null);
23266        }
23267
23268        /**
23269         * Constructor used when reading from a parcel using a given class loader.
23270         * Reads the state of the superclass.
23271         *
23272         * @param source parcel to read from
23273         * @param loader ClassLoader to use for reading
23274         */
23275        public BaseSavedState(Parcel source, ClassLoader loader) {
23276            super(source, loader);
23277            mStartActivityRequestWhoSaved = source.readString();
23278        }
23279
23280        /**
23281         * Constructor called by derived classes when creating their SavedState objects
23282         *
23283         * @param superState The state of the superclass of this view
23284         */
23285        public BaseSavedState(Parcelable superState) {
23286            super(superState);
23287        }
23288
23289        @Override
23290        public void writeToParcel(Parcel out, int flags) {
23291            super.writeToParcel(out, flags);
23292            out.writeString(mStartActivityRequestWhoSaved);
23293        }
23294
23295        public static final Parcelable.Creator<BaseSavedState> CREATOR
23296                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
23297            @Override
23298            public BaseSavedState createFromParcel(Parcel in) {
23299                return new BaseSavedState(in);
23300            }
23301
23302            @Override
23303            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
23304                return new BaseSavedState(in, loader);
23305            }
23306
23307            @Override
23308            public BaseSavedState[] newArray(int size) {
23309                return new BaseSavedState[size];
23310            }
23311        };
23312    }
23313
23314    /**
23315     * A set of information given to a view when it is attached to its parent
23316     * window.
23317     */
23318    final static class AttachInfo {
23319        interface Callbacks {
23320            void playSoundEffect(int effectId);
23321            boolean performHapticFeedback(int effectId, boolean always);
23322        }
23323
23324        /**
23325         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
23326         * to a Handler. This class contains the target (View) to invalidate and
23327         * the coordinates of the dirty rectangle.
23328         *
23329         * For performance purposes, this class also implements a pool of up to
23330         * POOL_LIMIT objects that get reused. This reduces memory allocations
23331         * whenever possible.
23332         */
23333        static class InvalidateInfo {
23334            private static final int POOL_LIMIT = 10;
23335
23336            private static final SynchronizedPool<InvalidateInfo> sPool =
23337                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
23338
23339            View target;
23340
23341            int left;
23342            int top;
23343            int right;
23344            int bottom;
23345
23346            public static InvalidateInfo obtain() {
23347                InvalidateInfo instance = sPool.acquire();
23348                return (instance != null) ? instance : new InvalidateInfo();
23349            }
23350
23351            public void recycle() {
23352                target = null;
23353                sPool.release(this);
23354            }
23355        }
23356
23357        final IWindowSession mSession;
23358
23359        final IWindow mWindow;
23360
23361        final IBinder mWindowToken;
23362
23363        final Display mDisplay;
23364
23365        final Callbacks mRootCallbacks;
23366
23367        IWindowId mIWindowId;
23368        WindowId mWindowId;
23369
23370        /**
23371         * The top view of the hierarchy.
23372         */
23373        View mRootView;
23374
23375        IBinder mPanelParentWindowToken;
23376
23377        boolean mHardwareAccelerated;
23378        boolean mHardwareAccelerationRequested;
23379        ThreadedRenderer mThreadedRenderer;
23380        List<RenderNode> mPendingAnimatingRenderNodes;
23381
23382        /**
23383         * The state of the display to which the window is attached, as reported
23384         * by {@link Display#getState()}.  Note that the display state constants
23385         * declared by {@link Display} do not exactly line up with the screen state
23386         * constants declared by {@link View} (there are more display states than
23387         * screen states).
23388         */
23389        int mDisplayState = Display.STATE_UNKNOWN;
23390
23391        /**
23392         * Scale factor used by the compatibility mode
23393         */
23394        float mApplicationScale;
23395
23396        /**
23397         * Indicates whether the application is in compatibility mode
23398         */
23399        boolean mScalingRequired;
23400
23401        /**
23402         * Left position of this view's window
23403         */
23404        int mWindowLeft;
23405
23406        /**
23407         * Top position of this view's window
23408         */
23409        int mWindowTop;
23410
23411        /**
23412         * Indicates whether views need to use 32-bit drawing caches
23413         */
23414        boolean mUse32BitDrawingCache;
23415
23416        /**
23417         * For windows that are full-screen but using insets to layout inside
23418         * of the screen areas, these are the current insets to appear inside
23419         * the overscan area of the display.
23420         */
23421        final Rect mOverscanInsets = new Rect();
23422
23423        /**
23424         * For windows that are full-screen but using insets to layout inside
23425         * of the screen decorations, these are the current insets for the
23426         * content of the window.
23427         */
23428        final Rect mContentInsets = new Rect();
23429
23430        /**
23431         * For windows that are full-screen but using insets to layout inside
23432         * of the screen decorations, these are the current insets for the
23433         * actual visible parts of the window.
23434         */
23435        final Rect mVisibleInsets = new Rect();
23436
23437        /**
23438         * For windows that are full-screen but using insets to layout inside
23439         * of the screen decorations, these are the current insets for the
23440         * stable system windows.
23441         */
23442        final Rect mStableInsets = new Rect();
23443
23444        /**
23445         * For windows that include areas that are not covered by real surface these are the outsets
23446         * for real surface.
23447         */
23448        final Rect mOutsets = new Rect();
23449
23450        /**
23451         * In multi-window we force show the navigation bar. Because we don't want that the surface
23452         * size changes in this mode, we instead have a flag whether the navigation bar size should
23453         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
23454         */
23455        boolean mAlwaysConsumeNavBar;
23456
23457        /**
23458         * The internal insets given by this window.  This value is
23459         * supplied by the client (through
23460         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
23461         * be given to the window manager when changed to be used in laying
23462         * out windows behind it.
23463         */
23464        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
23465                = new ViewTreeObserver.InternalInsetsInfo();
23466
23467        /**
23468         * Set to true when mGivenInternalInsets is non-empty.
23469         */
23470        boolean mHasNonEmptyGivenInternalInsets;
23471
23472        /**
23473         * All views in the window's hierarchy that serve as scroll containers,
23474         * used to determine if the window can be resized or must be panned
23475         * to adjust for a soft input area.
23476         */
23477        final ArrayList<View> mScrollContainers = new ArrayList<View>();
23478
23479        final KeyEvent.DispatcherState mKeyDispatchState
23480                = new KeyEvent.DispatcherState();
23481
23482        /**
23483         * Indicates whether the view's window currently has the focus.
23484         */
23485        boolean mHasWindowFocus;
23486
23487        /**
23488         * The current visibility of the window.
23489         */
23490        int mWindowVisibility;
23491
23492        /**
23493         * Indicates the time at which drawing started to occur.
23494         */
23495        long mDrawingTime;
23496
23497        /**
23498         * Indicates whether or not ignoring the DIRTY_MASK flags.
23499         */
23500        boolean mIgnoreDirtyState;
23501
23502        /**
23503         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
23504         * to avoid clearing that flag prematurely.
23505         */
23506        boolean mSetIgnoreDirtyState = false;
23507
23508        /**
23509         * Indicates whether the view's window is currently in touch mode.
23510         */
23511        boolean mInTouchMode;
23512
23513        /**
23514         * Indicates whether the view has requested unbuffered input dispatching for the current
23515         * event stream.
23516         */
23517        boolean mUnbufferedDispatchRequested;
23518
23519        /**
23520         * Indicates that ViewAncestor should trigger a global layout change
23521         * the next time it performs a traversal
23522         */
23523        boolean mRecomputeGlobalAttributes;
23524
23525        /**
23526         * Always report new attributes at next traversal.
23527         */
23528        boolean mForceReportNewAttributes;
23529
23530        /**
23531         * Set during a traveral if any views want to keep the screen on.
23532         */
23533        boolean mKeepScreenOn;
23534
23535        /**
23536         * Set during a traveral if the light center needs to be updated.
23537         */
23538        boolean mNeedsUpdateLightCenter;
23539
23540        /**
23541         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
23542         */
23543        int mSystemUiVisibility;
23544
23545        /**
23546         * Hack to force certain system UI visibility flags to be cleared.
23547         */
23548        int mDisabledSystemUiVisibility;
23549
23550        /**
23551         * Last global system UI visibility reported by the window manager.
23552         */
23553        int mGlobalSystemUiVisibility = -1;
23554
23555        /**
23556         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
23557         * attached.
23558         */
23559        boolean mHasSystemUiListeners;
23560
23561        /**
23562         * Set if the window has requested to extend into the overscan region
23563         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
23564         */
23565        boolean mOverscanRequested;
23566
23567        /**
23568         * Set if the visibility of any views has changed.
23569         */
23570        boolean mViewVisibilityChanged;
23571
23572        /**
23573         * Set to true if a view has been scrolled.
23574         */
23575        boolean mViewScrollChanged;
23576
23577        /**
23578         * Set to true if high contrast mode enabled
23579         */
23580        boolean mHighContrastText;
23581
23582        /**
23583         * Set to true if a pointer event is currently being handled.
23584         */
23585        boolean mHandlingPointerEvent;
23586
23587        /**
23588         * Global to the view hierarchy used as a temporary for dealing with
23589         * x/y points in the transparent region computations.
23590         */
23591        final int[] mTransparentLocation = new int[2];
23592
23593        /**
23594         * Global to the view hierarchy used as a temporary for dealing with
23595         * x/y points in the ViewGroup.invalidateChild implementation.
23596         */
23597        final int[] mInvalidateChildLocation = new int[2];
23598
23599        /**
23600         * Global to the view hierarchy used as a temporary for dealing with
23601         * computing absolute on-screen location.
23602         */
23603        final int[] mTmpLocation = new int[2];
23604
23605        /**
23606         * Global to the view hierarchy used as a temporary for dealing with
23607         * x/y location when view is transformed.
23608         */
23609        final float[] mTmpTransformLocation = new float[2];
23610
23611        /**
23612         * The view tree observer used to dispatch global events like
23613         * layout, pre-draw, touch mode change, etc.
23614         */
23615        final ViewTreeObserver mTreeObserver;
23616
23617        /**
23618         * A Canvas used by the view hierarchy to perform bitmap caching.
23619         */
23620        Canvas mCanvas;
23621
23622        /**
23623         * The view root impl.
23624         */
23625        final ViewRootImpl mViewRootImpl;
23626
23627        /**
23628         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
23629         * handler can be used to pump events in the UI events queue.
23630         */
23631        final Handler mHandler;
23632
23633        /**
23634         * Temporary for use in computing invalidate rectangles while
23635         * calling up the hierarchy.
23636         */
23637        final Rect mTmpInvalRect = new Rect();
23638
23639        /**
23640         * Temporary for use in computing hit areas with transformed views
23641         */
23642        final RectF mTmpTransformRect = new RectF();
23643
23644        /**
23645         * Temporary for use in computing hit areas with transformed views
23646         */
23647        final RectF mTmpTransformRect1 = new RectF();
23648
23649        /**
23650         * Temporary list of rectanges.
23651         */
23652        final List<RectF> mTmpRectList = new ArrayList<>();
23653
23654        /**
23655         * Temporary for use in transforming invalidation rect
23656         */
23657        final Matrix mTmpMatrix = new Matrix();
23658
23659        /**
23660         * Temporary for use in transforming invalidation rect
23661         */
23662        final Transformation mTmpTransformation = new Transformation();
23663
23664        /**
23665         * Temporary for use in querying outlines from OutlineProviders
23666         */
23667        final Outline mTmpOutline = new Outline();
23668
23669        /**
23670         * Temporary list for use in collecting focusable descendents of a view.
23671         */
23672        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
23673
23674        /**
23675         * The id of the window for accessibility purposes.
23676         */
23677        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
23678
23679        /**
23680         * Flags related to accessibility processing.
23681         *
23682         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
23683         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
23684         */
23685        int mAccessibilityFetchFlags;
23686
23687        /**
23688         * The drawable for highlighting accessibility focus.
23689         */
23690        Drawable mAccessibilityFocusDrawable;
23691
23692        /**
23693         * Show where the margins, bounds and layout bounds are for each view.
23694         */
23695        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
23696
23697        /**
23698         * Point used to compute visible regions.
23699         */
23700        final Point mPoint = new Point();
23701
23702        /**
23703         * Used to track which View originated a requestLayout() call, used when
23704         * requestLayout() is called during layout.
23705         */
23706        View mViewRequestingLayout;
23707
23708        /**
23709         * Used to track views that need (at least) a partial relayout at their current size
23710         * during the next traversal.
23711         */
23712        List<View> mPartialLayoutViews = new ArrayList<>();
23713
23714        /**
23715         * Swapped with mPartialLayoutViews during layout to avoid concurrent
23716         * modification. Lazily assigned during ViewRootImpl layout.
23717         */
23718        List<View> mEmptyPartialLayoutViews;
23719
23720        /**
23721         * Used to track the identity of the current drag operation.
23722         */
23723        IBinder mDragToken;
23724
23725        /**
23726         * The drag shadow surface for the current drag operation.
23727         */
23728        public Surface mDragSurface;
23729
23730
23731        /**
23732         * The view that currently has a tooltip displayed.
23733         */
23734        View mTooltipHost;
23735
23736        /**
23737         * Creates a new set of attachment information with the specified
23738         * events handler and thread.
23739         *
23740         * @param handler the events handler the view must use
23741         */
23742        AttachInfo(IWindowSession session, IWindow window, Display display,
23743                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
23744                Context context) {
23745            mSession = session;
23746            mWindow = window;
23747            mWindowToken = window.asBinder();
23748            mDisplay = display;
23749            mViewRootImpl = viewRootImpl;
23750            mHandler = handler;
23751            mRootCallbacks = effectPlayer;
23752            mTreeObserver = new ViewTreeObserver(context);
23753        }
23754    }
23755
23756    /**
23757     * <p>ScrollabilityCache holds various fields used by a View when scrolling
23758     * is supported. This avoids keeping too many unused fields in most
23759     * instances of View.</p>
23760     */
23761    private static class ScrollabilityCache implements Runnable {
23762
23763        /**
23764         * Scrollbars are not visible
23765         */
23766        public static final int OFF = 0;
23767
23768        /**
23769         * Scrollbars are visible
23770         */
23771        public static final int ON = 1;
23772
23773        /**
23774         * Scrollbars are fading away
23775         */
23776        public static final int FADING = 2;
23777
23778        public boolean fadeScrollBars;
23779
23780        public int fadingEdgeLength;
23781        public int scrollBarDefaultDelayBeforeFade;
23782        public int scrollBarFadeDuration;
23783
23784        public int scrollBarSize;
23785        public ScrollBarDrawable scrollBar;
23786        public float[] interpolatorValues;
23787        public View host;
23788
23789        public final Paint paint;
23790        public final Matrix matrix;
23791        public Shader shader;
23792
23793        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
23794
23795        private static final float[] OPAQUE = { 255 };
23796        private static final float[] TRANSPARENT = { 0.0f };
23797
23798        /**
23799         * When fading should start. This time moves into the future every time
23800         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
23801         */
23802        public long fadeStartTime;
23803
23804
23805        /**
23806         * The current state of the scrollbars: ON, OFF, or FADING
23807         */
23808        public int state = OFF;
23809
23810        private int mLastColor;
23811
23812        public final Rect mScrollBarBounds = new Rect();
23813
23814        public static final int NOT_DRAGGING = 0;
23815        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
23816        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
23817        public int mScrollBarDraggingState = NOT_DRAGGING;
23818
23819        public float mScrollBarDraggingPos = 0;
23820
23821        public ScrollabilityCache(ViewConfiguration configuration, View host) {
23822            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
23823            scrollBarSize = configuration.getScaledScrollBarSize();
23824            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
23825            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
23826
23827            paint = new Paint();
23828            matrix = new Matrix();
23829            // use use a height of 1, and then wack the matrix each time we
23830            // actually use it.
23831            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23832            paint.setShader(shader);
23833            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23834
23835            this.host = host;
23836        }
23837
23838        public void setFadeColor(int color) {
23839            if (color != mLastColor) {
23840                mLastColor = color;
23841
23842                if (color != 0) {
23843                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
23844                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
23845                    paint.setShader(shader);
23846                    // Restore the default transfer mode (src_over)
23847                    paint.setXfermode(null);
23848                } else {
23849                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23850                    paint.setShader(shader);
23851                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23852                }
23853            }
23854        }
23855
23856        public void run() {
23857            long now = AnimationUtils.currentAnimationTimeMillis();
23858            if (now >= fadeStartTime) {
23859
23860                // the animation fades the scrollbars out by changing
23861                // the opacity (alpha) from fully opaque to fully
23862                // transparent
23863                int nextFrame = (int) now;
23864                int framesCount = 0;
23865
23866                Interpolator interpolator = scrollBarInterpolator;
23867
23868                // Start opaque
23869                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
23870
23871                // End transparent
23872                nextFrame += scrollBarFadeDuration;
23873                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
23874
23875                state = FADING;
23876
23877                // Kick off the fade animation
23878                host.invalidate(true);
23879            }
23880        }
23881    }
23882
23883    /**
23884     * Resuable callback for sending
23885     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
23886     */
23887    private class SendViewScrolledAccessibilityEvent implements Runnable {
23888        public volatile boolean mIsPending;
23889
23890        public void run() {
23891            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
23892            mIsPending = false;
23893        }
23894    }
23895
23896    /**
23897     * <p>
23898     * This class represents a delegate that can be registered in a {@link View}
23899     * to enhance accessibility support via composition rather via inheritance.
23900     * It is specifically targeted to widget developers that extend basic View
23901     * classes i.e. classes in package android.view, that would like their
23902     * applications to be backwards compatible.
23903     * </p>
23904     * <div class="special reference">
23905     * <h3>Developer Guides</h3>
23906     * <p>For more information about making applications accessible, read the
23907     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
23908     * developer guide.</p>
23909     * </div>
23910     * <p>
23911     * A scenario in which a developer would like to use an accessibility delegate
23912     * is overriding a method introduced in a later API version than the minimal API
23913     * version supported by the application. For example, the method
23914     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
23915     * in API version 4 when the accessibility APIs were first introduced. If a
23916     * developer would like his application to run on API version 4 devices (assuming
23917     * all other APIs used by the application are version 4 or lower) and take advantage
23918     * of this method, instead of overriding the method which would break the application's
23919     * backwards compatibility, he can override the corresponding method in this
23920     * delegate and register the delegate in the target View if the API version of
23921     * the system is high enough, i.e. the API version is the same as or higher than the API
23922     * version that introduced
23923     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
23924     * </p>
23925     * <p>
23926     * Here is an example implementation:
23927     * </p>
23928     * <code><pre><p>
23929     * if (Build.VERSION.SDK_INT >= 14) {
23930     *     // If the API version is equal of higher than the version in
23931     *     // which onInitializeAccessibilityNodeInfo was introduced we
23932     *     // register a delegate with a customized implementation.
23933     *     View view = findViewById(R.id.view_id);
23934     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
23935     *         public void onInitializeAccessibilityNodeInfo(View host,
23936     *                 AccessibilityNodeInfo info) {
23937     *             // Let the default implementation populate the info.
23938     *             super.onInitializeAccessibilityNodeInfo(host, info);
23939     *             // Set some other information.
23940     *             info.setEnabled(host.isEnabled());
23941     *         }
23942     *     });
23943     * }
23944     * </code></pre></p>
23945     * <p>
23946     * This delegate contains methods that correspond to the accessibility methods
23947     * in View. If a delegate has been specified the implementation in View hands
23948     * off handling to the corresponding method in this delegate. The default
23949     * implementation the delegate methods behaves exactly as the corresponding
23950     * method in View for the case of no accessibility delegate been set. Hence,
23951     * to customize the behavior of a View method, clients can override only the
23952     * corresponding delegate method without altering the behavior of the rest
23953     * accessibility related methods of the host view.
23954     * </p>
23955     * <p>
23956     * <strong>Note:</strong> On platform versions prior to
23957     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
23958     * views in the {@code android.widget.*} package are called <i>before</i>
23959     * host methods. This prevents certain properties such as class name from
23960     * being modified by overriding
23961     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
23962     * as any changes will be overwritten by the host class.
23963     * <p>
23964     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
23965     * methods are called <i>after</i> host methods, which all properties to be
23966     * modified without being overwritten by the host class.
23967     */
23968    public static class AccessibilityDelegate {
23969
23970        /**
23971         * Sends an accessibility event of the given type. If accessibility is not
23972         * enabled this method has no effect.
23973         * <p>
23974         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
23975         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
23976         * been set.
23977         * </p>
23978         *
23979         * @param host The View hosting the delegate.
23980         * @param eventType The type of the event to send.
23981         *
23982         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
23983         */
23984        public void sendAccessibilityEvent(View host, int eventType) {
23985            host.sendAccessibilityEventInternal(eventType);
23986        }
23987
23988        /**
23989         * Performs the specified accessibility action on the view. For
23990         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
23991         * <p>
23992         * The default implementation behaves as
23993         * {@link View#performAccessibilityAction(int, Bundle)
23994         *  View#performAccessibilityAction(int, Bundle)} for the case of
23995         *  no accessibility delegate been set.
23996         * </p>
23997         *
23998         * @param action The action to perform.
23999         * @return Whether the action was performed.
24000         *
24001         * @see View#performAccessibilityAction(int, Bundle)
24002         *      View#performAccessibilityAction(int, Bundle)
24003         */
24004        public boolean performAccessibilityAction(View host, int action, Bundle args) {
24005            return host.performAccessibilityActionInternal(action, args);
24006        }
24007
24008        /**
24009         * Sends an accessibility event. This method behaves exactly as
24010         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
24011         * empty {@link AccessibilityEvent} and does not perform a check whether
24012         * accessibility is enabled.
24013         * <p>
24014         * The default implementation behaves as
24015         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
24016         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
24017         * the case of no accessibility delegate been set.
24018         * </p>
24019         *
24020         * @param host The View hosting the delegate.
24021         * @param event The event to send.
24022         *
24023         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
24024         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
24025         */
24026        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
24027            host.sendAccessibilityEventUncheckedInternal(event);
24028        }
24029
24030        /**
24031         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
24032         * to its children for adding their text content to the event.
24033         * <p>
24034         * The default implementation behaves as
24035         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
24036         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
24037         * the case of no accessibility delegate been set.
24038         * </p>
24039         *
24040         * @param host The View hosting the delegate.
24041         * @param event The event.
24042         * @return True if the event population was completed.
24043         *
24044         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
24045         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
24046         */
24047        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
24048            return host.dispatchPopulateAccessibilityEventInternal(event);
24049        }
24050
24051        /**
24052         * Gives a chance to the host View to populate the accessibility event with its
24053         * text content.
24054         * <p>
24055         * The default implementation behaves as
24056         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
24057         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
24058         * the case of no accessibility delegate been set.
24059         * </p>
24060         *
24061         * @param host The View hosting the delegate.
24062         * @param event The accessibility event which to populate.
24063         *
24064         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
24065         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
24066         */
24067        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
24068            host.onPopulateAccessibilityEventInternal(event);
24069        }
24070
24071        /**
24072         * Initializes an {@link AccessibilityEvent} with information about the
24073         * the host View which is the event source.
24074         * <p>
24075         * The default implementation behaves as
24076         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
24077         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
24078         * the case of no accessibility delegate been set.
24079         * </p>
24080         *
24081         * @param host The View hosting the delegate.
24082         * @param event The event to initialize.
24083         *
24084         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
24085         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
24086         */
24087        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
24088            host.onInitializeAccessibilityEventInternal(event);
24089        }
24090
24091        /**
24092         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
24093         * <p>
24094         * The default implementation behaves as
24095         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
24096         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
24097         * the case of no accessibility delegate been set.
24098         * </p>
24099         *
24100         * @param host The View hosting the delegate.
24101         * @param info The instance to initialize.
24102         *
24103         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
24104         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
24105         */
24106        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
24107            host.onInitializeAccessibilityNodeInfoInternal(info);
24108        }
24109
24110        /**
24111         * Called when a child of the host View has requested sending an
24112         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
24113         * to augment the event.
24114         * <p>
24115         * The default implementation behaves as
24116         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
24117         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
24118         * the case of no accessibility delegate been set.
24119         * </p>
24120         *
24121         * @param host The View hosting the delegate.
24122         * @param child The child which requests sending the event.
24123         * @param event The event to be sent.
24124         * @return True if the event should be sent
24125         *
24126         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
24127         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
24128         */
24129        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
24130                AccessibilityEvent event) {
24131            return host.onRequestSendAccessibilityEventInternal(child, event);
24132        }
24133
24134        /**
24135         * Gets the provider for managing a virtual view hierarchy rooted at this View
24136         * and reported to {@link android.accessibilityservice.AccessibilityService}s
24137         * that explore the window content.
24138         * <p>
24139         * The default implementation behaves as
24140         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
24141         * the case of no accessibility delegate been set.
24142         * </p>
24143         *
24144         * @return The provider.
24145         *
24146         * @see AccessibilityNodeProvider
24147         */
24148        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
24149            return null;
24150        }
24151
24152        /**
24153         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
24154         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
24155         * This method is responsible for obtaining an accessibility node info from a
24156         * pool of reusable instances and calling
24157         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
24158         * view to initialize the former.
24159         * <p>
24160         * <strong>Note:</strong> The client is responsible for recycling the obtained
24161         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
24162         * creation.
24163         * </p>
24164         * <p>
24165         * The default implementation behaves as
24166         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
24167         * the case of no accessibility delegate been set.
24168         * </p>
24169         * @return A populated {@link AccessibilityNodeInfo}.
24170         *
24171         * @see AccessibilityNodeInfo
24172         *
24173         * @hide
24174         */
24175        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
24176            return host.createAccessibilityNodeInfoInternal();
24177        }
24178    }
24179
24180    private class MatchIdPredicate implements Predicate<View> {
24181        public int mId;
24182
24183        @Override
24184        public boolean apply(View view) {
24185            return (view.mID == mId);
24186        }
24187    }
24188
24189    private class MatchLabelForPredicate implements Predicate<View> {
24190        private int mLabeledId;
24191
24192        @Override
24193        public boolean apply(View view) {
24194            return (view.mLabelForId == mLabeledId);
24195        }
24196    }
24197
24198    private class SendViewStateChangedAccessibilityEvent implements Runnable {
24199        private int mChangeTypes = 0;
24200        private boolean mPosted;
24201        private boolean mPostedWithDelay;
24202        private long mLastEventTimeMillis;
24203
24204        @Override
24205        public void run() {
24206            mPosted = false;
24207            mPostedWithDelay = false;
24208            mLastEventTimeMillis = SystemClock.uptimeMillis();
24209            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
24210                final AccessibilityEvent event = AccessibilityEvent.obtain();
24211                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
24212                event.setContentChangeTypes(mChangeTypes);
24213                sendAccessibilityEventUnchecked(event);
24214            }
24215            mChangeTypes = 0;
24216        }
24217
24218        public void runOrPost(int changeType) {
24219            mChangeTypes |= changeType;
24220
24221            // If this is a live region or the child of a live region, collect
24222            // all events from this frame and send them on the next frame.
24223            if (inLiveRegion()) {
24224                // If we're already posted with a delay, remove that.
24225                if (mPostedWithDelay) {
24226                    removeCallbacks(this);
24227                    mPostedWithDelay = false;
24228                }
24229                // Only post if we're not already posted.
24230                if (!mPosted) {
24231                    post(this);
24232                    mPosted = true;
24233                }
24234                return;
24235            }
24236
24237            if (mPosted) {
24238                return;
24239            }
24240
24241            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
24242            final long minEventIntevalMillis =
24243                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
24244            if (timeSinceLastMillis >= minEventIntevalMillis) {
24245                removeCallbacks(this);
24246                run();
24247            } else {
24248                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
24249                mPostedWithDelay = true;
24250            }
24251        }
24252    }
24253
24254    private boolean inLiveRegion() {
24255        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
24256            return true;
24257        }
24258
24259        ViewParent parent = getParent();
24260        while (parent instanceof View) {
24261            if (((View) parent).getAccessibilityLiveRegion()
24262                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
24263                return true;
24264            }
24265            parent = parent.getParent();
24266        }
24267
24268        return false;
24269    }
24270
24271    /**
24272     * Dump all private flags in readable format, useful for documentation and
24273     * sanity checking.
24274     */
24275    private static void dumpFlags() {
24276        final HashMap<String, String> found = Maps.newHashMap();
24277        try {
24278            for (Field field : View.class.getDeclaredFields()) {
24279                final int modifiers = field.getModifiers();
24280                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
24281                    if (field.getType().equals(int.class)) {
24282                        final int value = field.getInt(null);
24283                        dumpFlag(found, field.getName(), value);
24284                    } else if (field.getType().equals(int[].class)) {
24285                        final int[] values = (int[]) field.get(null);
24286                        for (int i = 0; i < values.length; i++) {
24287                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
24288                        }
24289                    }
24290                }
24291            }
24292        } catch (IllegalAccessException e) {
24293            throw new RuntimeException(e);
24294        }
24295
24296        final ArrayList<String> keys = Lists.newArrayList();
24297        keys.addAll(found.keySet());
24298        Collections.sort(keys);
24299        for (String key : keys) {
24300            Log.d(VIEW_LOG_TAG, found.get(key));
24301        }
24302    }
24303
24304    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
24305        // Sort flags by prefix, then by bits, always keeping unique keys
24306        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
24307        final int prefix = name.indexOf('_');
24308        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
24309        final String output = bits + " " + name;
24310        found.put(key, output);
24311    }
24312
24313    /** {@hide} */
24314    public void encode(@NonNull ViewHierarchyEncoder stream) {
24315        stream.beginObject(this);
24316        encodeProperties(stream);
24317        stream.endObject();
24318    }
24319
24320    /** {@hide} */
24321    @CallSuper
24322    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
24323        Object resolveId = ViewDebug.resolveId(getContext(), mID);
24324        if (resolveId instanceof String) {
24325            stream.addProperty("id", (String) resolveId);
24326        } else {
24327            stream.addProperty("id", mID);
24328        }
24329
24330        stream.addProperty("misc:transformation.alpha",
24331                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
24332        stream.addProperty("misc:transitionName", getTransitionName());
24333
24334        // layout
24335        stream.addProperty("layout:left", mLeft);
24336        stream.addProperty("layout:right", mRight);
24337        stream.addProperty("layout:top", mTop);
24338        stream.addProperty("layout:bottom", mBottom);
24339        stream.addProperty("layout:width", getWidth());
24340        stream.addProperty("layout:height", getHeight());
24341        stream.addProperty("layout:layoutDirection", getLayoutDirection());
24342        stream.addProperty("layout:layoutRtl", isLayoutRtl());
24343        stream.addProperty("layout:hasTransientState", hasTransientState());
24344        stream.addProperty("layout:baseline", getBaseline());
24345
24346        // layout params
24347        ViewGroup.LayoutParams layoutParams = getLayoutParams();
24348        if (layoutParams != null) {
24349            stream.addPropertyKey("layoutParams");
24350            layoutParams.encode(stream);
24351        }
24352
24353        // scrolling
24354        stream.addProperty("scrolling:scrollX", mScrollX);
24355        stream.addProperty("scrolling:scrollY", mScrollY);
24356
24357        // padding
24358        stream.addProperty("padding:paddingLeft", mPaddingLeft);
24359        stream.addProperty("padding:paddingRight", mPaddingRight);
24360        stream.addProperty("padding:paddingTop", mPaddingTop);
24361        stream.addProperty("padding:paddingBottom", mPaddingBottom);
24362        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
24363        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
24364        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
24365        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
24366        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
24367
24368        // measurement
24369        stream.addProperty("measurement:minHeight", mMinHeight);
24370        stream.addProperty("measurement:minWidth", mMinWidth);
24371        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
24372        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
24373
24374        // drawing
24375        stream.addProperty("drawing:elevation", getElevation());
24376        stream.addProperty("drawing:translationX", getTranslationX());
24377        stream.addProperty("drawing:translationY", getTranslationY());
24378        stream.addProperty("drawing:translationZ", getTranslationZ());
24379        stream.addProperty("drawing:rotation", getRotation());
24380        stream.addProperty("drawing:rotationX", getRotationX());
24381        stream.addProperty("drawing:rotationY", getRotationY());
24382        stream.addProperty("drawing:scaleX", getScaleX());
24383        stream.addProperty("drawing:scaleY", getScaleY());
24384        stream.addProperty("drawing:pivotX", getPivotX());
24385        stream.addProperty("drawing:pivotY", getPivotY());
24386        stream.addProperty("drawing:opaque", isOpaque());
24387        stream.addProperty("drawing:alpha", getAlpha());
24388        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
24389        stream.addProperty("drawing:shadow", hasShadow());
24390        stream.addProperty("drawing:solidColor", getSolidColor());
24391        stream.addProperty("drawing:layerType", mLayerType);
24392        stream.addProperty("drawing:willNotDraw", willNotDraw());
24393        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
24394        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
24395        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
24396        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
24397
24398        // focus
24399        stream.addProperty("focus:hasFocus", hasFocus());
24400        stream.addProperty("focus:isFocused", isFocused());
24401        stream.addProperty("focus:isFocusable", isFocusable());
24402        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
24403
24404        stream.addProperty("misc:clickable", isClickable());
24405        stream.addProperty("misc:pressed", isPressed());
24406        stream.addProperty("misc:selected", isSelected());
24407        stream.addProperty("misc:touchMode", isInTouchMode());
24408        stream.addProperty("misc:hovered", isHovered());
24409        stream.addProperty("misc:activated", isActivated());
24410
24411        stream.addProperty("misc:visibility", getVisibility());
24412        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
24413        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
24414
24415        stream.addProperty("misc:enabled", isEnabled());
24416        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
24417        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
24418
24419        // theme attributes
24420        Resources.Theme theme = getContext().getTheme();
24421        if (theme != null) {
24422            stream.addPropertyKey("theme");
24423            theme.encode(stream);
24424        }
24425
24426        // view attribute information
24427        int n = mAttributes != null ? mAttributes.length : 0;
24428        stream.addProperty("meta:__attrCount__", n/2);
24429        for (int i = 0; i < n; i += 2) {
24430            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
24431        }
24432
24433        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
24434
24435        // text
24436        stream.addProperty("text:textDirection", getTextDirection());
24437        stream.addProperty("text:textAlignment", getTextAlignment());
24438
24439        // accessibility
24440        CharSequence contentDescription = getContentDescription();
24441        stream.addProperty("accessibility:contentDescription",
24442                contentDescription == null ? "" : contentDescription.toString());
24443        stream.addProperty("accessibility:labelFor", getLabelFor());
24444        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
24445    }
24446
24447    /**
24448     * Determine if this view is rendered on a round wearable device and is the main view
24449     * on the screen.
24450     */
24451    private boolean shouldDrawRoundScrollbar() {
24452        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
24453            return false;
24454        }
24455
24456        final View rootView = getRootView();
24457        final WindowInsets insets = getRootWindowInsets();
24458
24459        int height = getHeight();
24460        int width = getWidth();
24461        int displayHeight = rootView.getHeight();
24462        int displayWidth = rootView.getWidth();
24463
24464        if (height != displayHeight || width != displayWidth) {
24465            return false;
24466        }
24467
24468        getLocationOnScreen(mAttachInfo.mTmpLocation);
24469        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
24470                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
24471    }
24472
24473    /**
24474     * Sets the tooltip text which will be displayed in a small popup next to the view.
24475     * <p>
24476     * The tooltip will be displayed:
24477     * <li>On long click, unless is not handled otherwise (by OnLongClickListener or a context
24478     * menu). </li>
24479     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
24480     *
24481     * @param tooltip the tooltip text, or null if no tooltip is required
24482     */
24483    public final void setTooltip(@Nullable CharSequence tooltip) {
24484        if (TextUtils.isEmpty(tooltip)) {
24485            setFlags(0, TOOLTIP);
24486            hideTooltip();
24487            mTooltipInfo = null;
24488        } else {
24489            setFlags(TOOLTIP, TOOLTIP);
24490            if (mTooltipInfo == null) {
24491                mTooltipInfo = new TooltipInfo();
24492                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
24493                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
24494            }
24495            mTooltipInfo.mTooltip = tooltip;
24496            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
24497                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltip);
24498            }
24499        }
24500    }
24501
24502    /**
24503     * Returns the view's tooltip text.
24504     *
24505     * @return the tooltip text
24506     */
24507    @Nullable
24508    public final CharSequence getTooltip() {
24509        return mTooltipInfo != null ? mTooltipInfo.mTooltip : null;
24510    }
24511
24512    private boolean showTooltip(int x, int y, boolean fromLongClick) {
24513        if (mAttachInfo == null) {
24514            return false;
24515        }
24516        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
24517            return false;
24518        }
24519        final CharSequence tooltipText = getTooltip();
24520        if (TextUtils.isEmpty(tooltipText)) {
24521            return false;
24522        }
24523        hideTooltip();
24524        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
24525        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
24526        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
24527        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, tooltipText);
24528        mAttachInfo.mTooltipHost = this;
24529        return true;
24530    }
24531
24532    void hideTooltip() {
24533        if (mTooltipInfo == null) {
24534            return;
24535        }
24536        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
24537        if (mTooltipInfo.mTooltipPopup == null) {
24538            return;
24539        }
24540        mTooltipInfo.mTooltipPopup.hide();
24541        mTooltipInfo.mTooltipPopup = null;
24542        mTooltipInfo.mTooltipFromLongClick = false;
24543        if (mAttachInfo != null) {
24544            mAttachInfo.mTooltipHost = null;
24545        }
24546    }
24547
24548    private boolean showLongClickTooltip(int x, int y) {
24549        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
24550        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
24551        return showTooltip(x, y, true);
24552    }
24553
24554    private void showHoverTooltip() {
24555        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
24556    }
24557
24558    boolean dispatchTooltipHoverEvent(MotionEvent event) {
24559        if (mTooltipInfo == null) {
24560            return false;
24561        }
24562        switch(event.getAction()) {
24563            case MotionEvent.ACTION_HOVER_MOVE:
24564                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
24565                    break;
24566                }
24567                if (!mTooltipInfo.mTooltipFromLongClick) {
24568                    if (mTooltipInfo.mTooltipPopup == null) {
24569                        // Schedule showing the tooltip after a timeout.
24570                        mTooltipInfo.mAnchorX = (int) event.getX();
24571                        mTooltipInfo.mAnchorY = (int) event.getY();
24572                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
24573                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
24574                                ViewConfiguration.getHoverTooltipShowTimeout());
24575                    }
24576
24577                    // Hide hover-triggered tooltip after a period of inactivity.
24578                    // Match the timeout used by NativeInputManager to hide the mouse pointer
24579                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
24580                    final int timeout;
24581                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
24582                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
24583                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
24584                    } else {
24585                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
24586                    }
24587                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
24588                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
24589                }
24590                return true;
24591
24592            case MotionEvent.ACTION_HOVER_EXIT:
24593                if (!mTooltipInfo.mTooltipFromLongClick) {
24594                    hideTooltip();
24595                }
24596                break;
24597        }
24598        return false;
24599    }
24600
24601    void handleTooltipKey(KeyEvent event) {
24602        switch (event.getAction()) {
24603            case KeyEvent.ACTION_DOWN:
24604                if (event.getRepeatCount() == 0) {
24605                    hideTooltip();
24606                }
24607                break;
24608
24609            case KeyEvent.ACTION_UP:
24610                handleTooltipUp();
24611                break;
24612        }
24613    }
24614
24615    private void handleTooltipUp() {
24616        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
24617            return;
24618        }
24619        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
24620        postDelayed(mTooltipInfo.mHideTooltipRunnable,
24621                ViewConfiguration.getLongPressTooltipHideTimeout());
24622    }
24623
24624    /**
24625     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
24626     * is not showing.
24627     * @hide
24628     */
24629    @TestApi
24630    public View getTooltipView() {
24631        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
24632            return null;
24633        }
24634        return mTooltipInfo.mTooltipPopup.getContentView();
24635    }
24636}
24637