View.java revision 8102d91377367b9cd63d221da8354436815e7679
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    /**
1252     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1253     * item.
1254     */
1255    public static final int FOCUS_BACKWARD = 0x00000001;
1256
1257    /**
1258     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1259     * item.
1260     */
1261    public static final int FOCUS_FORWARD = 0x00000002;
1262
1263    /**
1264     * Use with {@link #focusSearch(int)}. Move focus to the left.
1265     */
1266    public static final int FOCUS_LEFT = 0x00000011;
1267
1268    /**
1269     * Use with {@link #focusSearch(int)}. Move focus up.
1270     */
1271    public static final int FOCUS_UP = 0x00000021;
1272
1273    /**
1274     * Use with {@link #focusSearch(int)}. Move focus to the right.
1275     */
1276    public static final int FOCUS_RIGHT = 0x00000042;
1277
1278    /**
1279     * Use with {@link #focusSearch(int)}. Move focus down.
1280     */
1281    public static final int FOCUS_DOWN = 0x00000082;
1282
1283    /**
1284     * Bits of {@link #getMeasuredWidthAndState()} and
1285     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1286     */
1287    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1288
1289    /**
1290     * Bits of {@link #getMeasuredWidthAndState()} and
1291     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1292     */
1293    public static final int MEASURED_STATE_MASK = 0xff000000;
1294
1295    /**
1296     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1297     * for functions that combine both width and height into a single int,
1298     * such as {@link #getMeasuredState()} and the childState argument of
1299     * {@link #resolveSizeAndState(int, int, int)}.
1300     */
1301    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1302
1303    /**
1304     * Bit of {@link #getMeasuredWidthAndState()} and
1305     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1306     * is smaller that the space the view would like to have.
1307     */
1308    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1309
1310    /**
1311     * Base View state sets
1312     */
1313    // Singles
1314    /**
1315     * Indicates the view has no states set. States are used with
1316     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1317     * view depending on its state.
1318     *
1319     * @see android.graphics.drawable.Drawable
1320     * @see #getDrawableState()
1321     */
1322    protected static final int[] EMPTY_STATE_SET;
1323    /**
1324     * Indicates the view is enabled. States are used with
1325     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1326     * view depending on its state.
1327     *
1328     * @see android.graphics.drawable.Drawable
1329     * @see #getDrawableState()
1330     */
1331    protected static final int[] ENABLED_STATE_SET;
1332    /**
1333     * Indicates the view is focused. States are used with
1334     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1335     * view depending on its state.
1336     *
1337     * @see android.graphics.drawable.Drawable
1338     * @see #getDrawableState()
1339     */
1340    protected static final int[] FOCUSED_STATE_SET;
1341    /**
1342     * Indicates the view is selected. States are used with
1343     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1344     * view depending on its state.
1345     *
1346     * @see android.graphics.drawable.Drawable
1347     * @see #getDrawableState()
1348     */
1349    protected static final int[] SELECTED_STATE_SET;
1350    /**
1351     * Indicates the view is pressed. States are used with
1352     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1353     * view depending on its state.
1354     *
1355     * @see android.graphics.drawable.Drawable
1356     * @see #getDrawableState()
1357     */
1358    protected static final int[] PRESSED_STATE_SET;
1359    /**
1360     * Indicates the view's window has focus. States are used with
1361     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1362     * view depending on its state.
1363     *
1364     * @see android.graphics.drawable.Drawable
1365     * @see #getDrawableState()
1366     */
1367    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1368    // Doubles
1369    /**
1370     * Indicates the view is enabled and has the focus.
1371     *
1372     * @see #ENABLED_STATE_SET
1373     * @see #FOCUSED_STATE_SET
1374     */
1375    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1376    /**
1377     * Indicates the view is enabled and selected.
1378     *
1379     * @see #ENABLED_STATE_SET
1380     * @see #SELECTED_STATE_SET
1381     */
1382    protected static final int[] ENABLED_SELECTED_STATE_SET;
1383    /**
1384     * Indicates the view is enabled and that its window has focus.
1385     *
1386     * @see #ENABLED_STATE_SET
1387     * @see #WINDOW_FOCUSED_STATE_SET
1388     */
1389    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1390    /**
1391     * Indicates the view is focused and selected.
1392     *
1393     * @see #FOCUSED_STATE_SET
1394     * @see #SELECTED_STATE_SET
1395     */
1396    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1397    /**
1398     * Indicates the view has the focus and that its window has the focus.
1399     *
1400     * @see #FOCUSED_STATE_SET
1401     * @see #WINDOW_FOCUSED_STATE_SET
1402     */
1403    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1404    /**
1405     * Indicates the view is selected and that its window has the focus.
1406     *
1407     * @see #SELECTED_STATE_SET
1408     * @see #WINDOW_FOCUSED_STATE_SET
1409     */
1410    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1411    // Triples
1412    /**
1413     * Indicates the view is enabled, focused and selected.
1414     *
1415     * @see #ENABLED_STATE_SET
1416     * @see #FOCUSED_STATE_SET
1417     * @see #SELECTED_STATE_SET
1418     */
1419    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1420    /**
1421     * Indicates the view is enabled, focused and its window has the focus.
1422     *
1423     * @see #ENABLED_STATE_SET
1424     * @see #FOCUSED_STATE_SET
1425     * @see #WINDOW_FOCUSED_STATE_SET
1426     */
1427    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1428    /**
1429     * Indicates the view is enabled, selected and its window has the focus.
1430     *
1431     * @see #ENABLED_STATE_SET
1432     * @see #SELECTED_STATE_SET
1433     * @see #WINDOW_FOCUSED_STATE_SET
1434     */
1435    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1436    /**
1437     * Indicates the view is focused, selected and its window has the focus.
1438     *
1439     * @see #FOCUSED_STATE_SET
1440     * @see #SELECTED_STATE_SET
1441     * @see #WINDOW_FOCUSED_STATE_SET
1442     */
1443    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1444    /**
1445     * Indicates the view is enabled, focused, selected and its window
1446     * has the focus.
1447     *
1448     * @see #ENABLED_STATE_SET
1449     * @see #FOCUSED_STATE_SET
1450     * @see #SELECTED_STATE_SET
1451     * @see #WINDOW_FOCUSED_STATE_SET
1452     */
1453    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1454    /**
1455     * Indicates the view is pressed and its window has the focus.
1456     *
1457     * @see #PRESSED_STATE_SET
1458     * @see #WINDOW_FOCUSED_STATE_SET
1459     */
1460    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1461    /**
1462     * Indicates the view is pressed and selected.
1463     *
1464     * @see #PRESSED_STATE_SET
1465     * @see #SELECTED_STATE_SET
1466     */
1467    protected static final int[] PRESSED_SELECTED_STATE_SET;
1468    /**
1469     * Indicates the view is pressed, selected and its window has the focus.
1470     *
1471     * @see #PRESSED_STATE_SET
1472     * @see #SELECTED_STATE_SET
1473     * @see #WINDOW_FOCUSED_STATE_SET
1474     */
1475    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1476    /**
1477     * Indicates the view is pressed and focused.
1478     *
1479     * @see #PRESSED_STATE_SET
1480     * @see #FOCUSED_STATE_SET
1481     */
1482    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1483    /**
1484     * Indicates the view is pressed, focused and its window has the focus.
1485     *
1486     * @see #PRESSED_STATE_SET
1487     * @see #FOCUSED_STATE_SET
1488     * @see #WINDOW_FOCUSED_STATE_SET
1489     */
1490    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1491    /**
1492     * Indicates the view is pressed, focused and selected.
1493     *
1494     * @see #PRESSED_STATE_SET
1495     * @see #SELECTED_STATE_SET
1496     * @see #FOCUSED_STATE_SET
1497     */
1498    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1499    /**
1500     * Indicates the view is pressed, focused, selected and its window has the focus.
1501     *
1502     * @see #PRESSED_STATE_SET
1503     * @see #FOCUSED_STATE_SET
1504     * @see #SELECTED_STATE_SET
1505     * @see #WINDOW_FOCUSED_STATE_SET
1506     */
1507    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1508    /**
1509     * Indicates the view is pressed and enabled.
1510     *
1511     * @see #PRESSED_STATE_SET
1512     * @see #ENABLED_STATE_SET
1513     */
1514    protected static final int[] PRESSED_ENABLED_STATE_SET;
1515    /**
1516     * Indicates the view is pressed, enabled and its window has the focus.
1517     *
1518     * @see #PRESSED_STATE_SET
1519     * @see #ENABLED_STATE_SET
1520     * @see #WINDOW_FOCUSED_STATE_SET
1521     */
1522    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1523    /**
1524     * Indicates the view is pressed, enabled and selected.
1525     *
1526     * @see #PRESSED_STATE_SET
1527     * @see #ENABLED_STATE_SET
1528     * @see #SELECTED_STATE_SET
1529     */
1530    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1531    /**
1532     * Indicates the view is pressed, enabled, selected and its window has the
1533     * focus.
1534     *
1535     * @see #PRESSED_STATE_SET
1536     * @see #ENABLED_STATE_SET
1537     * @see #SELECTED_STATE_SET
1538     * @see #WINDOW_FOCUSED_STATE_SET
1539     */
1540    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1541    /**
1542     * Indicates the view is pressed, enabled and focused.
1543     *
1544     * @see #PRESSED_STATE_SET
1545     * @see #ENABLED_STATE_SET
1546     * @see #FOCUSED_STATE_SET
1547     */
1548    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1549    /**
1550     * Indicates the view is pressed, enabled, focused and its window has the
1551     * focus.
1552     *
1553     * @see #PRESSED_STATE_SET
1554     * @see #ENABLED_STATE_SET
1555     * @see #FOCUSED_STATE_SET
1556     * @see #WINDOW_FOCUSED_STATE_SET
1557     */
1558    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1559    /**
1560     * Indicates the view is pressed, enabled, focused and selected.
1561     *
1562     * @see #PRESSED_STATE_SET
1563     * @see #ENABLED_STATE_SET
1564     * @see #SELECTED_STATE_SET
1565     * @see #FOCUSED_STATE_SET
1566     */
1567    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1568    /**
1569     * Indicates the view is pressed, enabled, focused, selected and its window
1570     * has the focus.
1571     *
1572     * @see #PRESSED_STATE_SET
1573     * @see #ENABLED_STATE_SET
1574     * @see #SELECTED_STATE_SET
1575     * @see #FOCUSED_STATE_SET
1576     * @see #WINDOW_FOCUSED_STATE_SET
1577     */
1578    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1579
1580    static {
1581        EMPTY_STATE_SET = StateSet.get(0);
1582
1583        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1584
1585        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1586        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1587                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1588
1589        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1590        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1591                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1592        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1593                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1594        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1595                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1596                        | StateSet.VIEW_STATE_FOCUSED);
1597
1598        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1599        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1600                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1601        ENABLED_SELECTED_STATE_SET = StateSet.get(
1602                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1603        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1604                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1605                        | StateSet.VIEW_STATE_ENABLED);
1606        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1607                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1608        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1609                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1610                        | StateSet.VIEW_STATE_ENABLED);
1611        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1612                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1613                        | StateSet.VIEW_STATE_ENABLED);
1614        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1615                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1616                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1617
1618        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1619        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1620                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1621        PRESSED_SELECTED_STATE_SET = StateSet.get(
1622                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1623        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1624                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1625                        | StateSet.VIEW_STATE_PRESSED);
1626        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1627                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1628        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1629                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1630                        | StateSet.VIEW_STATE_PRESSED);
1631        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1632                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1633                        | StateSet.VIEW_STATE_PRESSED);
1634        PRESSED_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_PRESSED);
1637        PRESSED_ENABLED_STATE_SET = StateSet.get(
1638                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1639        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1640                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1641                        | StateSet.VIEW_STATE_PRESSED);
1642        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1643                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1644                        | StateSet.VIEW_STATE_PRESSED);
1645        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1646                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1647                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1648        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1649                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1650                        | StateSet.VIEW_STATE_PRESSED);
1651        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1652                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1653                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1654        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1655                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1656                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1657        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1658                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1659                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1660                        | StateSet.VIEW_STATE_PRESSED);
1661    }
1662
1663    /**
1664     * Accessibility event types that are dispatched for text population.
1665     */
1666    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1667            AccessibilityEvent.TYPE_VIEW_CLICKED
1668            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1669            | AccessibilityEvent.TYPE_VIEW_SELECTED
1670            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1671            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1672            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1673            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1674            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1675            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1676            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1677            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1678
1679    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
1680
1681    static final int DEBUG_CORNERS_SIZE_DIP = 8;
1682
1683    /**
1684     * Temporary Rect currently for use in setBackground().  This will probably
1685     * be extended in the future to hold our own class with more than just
1686     * a Rect. :)
1687     */
1688    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1689
1690    /**
1691     * Map used to store views' tags.
1692     */
1693    private SparseArray<Object> mKeyedTags;
1694
1695    /**
1696     * The next available accessibility id.
1697     */
1698    private static int sNextAccessibilityViewId;
1699
1700    /**
1701     * The animation currently associated with this view.
1702     * @hide
1703     */
1704    protected Animation mCurrentAnimation = null;
1705
1706    /**
1707     * Width as measured during measure pass.
1708     * {@hide}
1709     */
1710    @ViewDebug.ExportedProperty(category = "measurement")
1711    int mMeasuredWidth;
1712
1713    /**
1714     * Height as measured during measure pass.
1715     * {@hide}
1716     */
1717    @ViewDebug.ExportedProperty(category = "measurement")
1718    int mMeasuredHeight;
1719
1720    /**
1721     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1722     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1723     * its display list. This flag, used only when hw accelerated, allows us to clear the
1724     * flag while retaining this information until it's needed (at getDisplayList() time and
1725     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1726     *
1727     * {@hide}
1728     */
1729    boolean mRecreateDisplayList = false;
1730
1731    /**
1732     * The view's identifier.
1733     * {@hide}
1734     *
1735     * @see #setId(int)
1736     * @see #getId()
1737     */
1738    @IdRes
1739    @ViewDebug.ExportedProperty(resolveId = true)
1740    int mID = NO_ID;
1741
1742    /**
1743     * The stable ID of this view for accessibility purposes.
1744     */
1745    int mAccessibilityViewId = NO_ID;
1746
1747    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1748
1749    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1750
1751    /**
1752     * The view's tag.
1753     * {@hide}
1754     *
1755     * @see #setTag(Object)
1756     * @see #getTag()
1757     */
1758    protected Object mTag = null;
1759
1760    // for mPrivateFlags:
1761    /** {@hide} */
1762    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1763    /** {@hide} */
1764    static final int PFLAG_FOCUSED                     = 0x00000002;
1765    /** {@hide} */
1766    static final int PFLAG_SELECTED                    = 0x00000004;
1767    /** {@hide} */
1768    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1769    /** {@hide} */
1770    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1771    /** {@hide} */
1772    static final int PFLAG_DRAWN                       = 0x00000020;
1773    /**
1774     * When this flag is set, this view is running an animation on behalf of its
1775     * children and should therefore not cancel invalidate requests, even if they
1776     * lie outside of this view's bounds.
1777     *
1778     * {@hide}
1779     */
1780    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1781    /** {@hide} */
1782    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1783    /** {@hide} */
1784    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1785    /** {@hide} */
1786    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1787    /** {@hide} */
1788    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1789    /** {@hide} */
1790    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1791    /** {@hide} */
1792    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1793
1794    private static final int PFLAG_PRESSED             = 0x00004000;
1795
1796    /** {@hide} */
1797    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1798    /**
1799     * Flag used to indicate that this view should be drawn once more (and only once
1800     * more) after its animation has completed.
1801     * {@hide}
1802     */
1803    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1804
1805    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1806
1807    /**
1808     * Indicates that the View returned true when onSetAlpha() was called and that
1809     * the alpha must be restored.
1810     * {@hide}
1811     */
1812    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1813
1814    /**
1815     * Set by {@link #setScrollContainer(boolean)}.
1816     */
1817    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1818
1819    /**
1820     * Set by {@link #setScrollContainer(boolean)}.
1821     */
1822    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1823
1824    /**
1825     * View flag indicating whether this view was invalidated (fully or partially.)
1826     *
1827     * @hide
1828     */
1829    static final int PFLAG_DIRTY                       = 0x00200000;
1830
1831    /**
1832     * View flag indicating whether this view was invalidated by an opaque
1833     * invalidate request.
1834     *
1835     * @hide
1836     */
1837    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1838
1839    /**
1840     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1841     *
1842     * @hide
1843     */
1844    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1845
1846    /**
1847     * Indicates whether the background is opaque.
1848     *
1849     * @hide
1850     */
1851    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1852
1853    /**
1854     * Indicates whether the scrollbars are opaque.
1855     *
1856     * @hide
1857     */
1858    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1859
1860    /**
1861     * Indicates whether the view is opaque.
1862     *
1863     * @hide
1864     */
1865    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1866
1867    /**
1868     * Indicates a prepressed state;
1869     * the short time between ACTION_DOWN and recognizing
1870     * a 'real' press. Prepressed is used to recognize quick taps
1871     * even when they are shorter than ViewConfiguration.getTapTimeout().
1872     *
1873     * @hide
1874     */
1875    private static final int PFLAG_PREPRESSED          = 0x02000000;
1876
1877    /**
1878     * Indicates whether the view is temporarily detached.
1879     *
1880     * @hide
1881     */
1882    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1883
1884    /**
1885     * Indicates that we should awaken scroll bars once attached
1886     *
1887     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1888     * during window attachment and it is no longer needed. Feel free to repurpose it.
1889     *
1890     * @hide
1891     */
1892    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1893
1894    /**
1895     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1896     * @hide
1897     */
1898    private static final int PFLAG_HOVERED             = 0x10000000;
1899
1900    /**
1901     * no longer needed, should be reused
1902     */
1903    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1904
1905    /** {@hide} */
1906    static final int PFLAG_ACTIVATED                   = 0x40000000;
1907
1908    /**
1909     * Indicates that this view was specifically invalidated, not just dirtied because some
1910     * child view was invalidated. The flag is used to determine when we need to recreate
1911     * a view's display list (as opposed to just returning a reference to its existing
1912     * display list).
1913     *
1914     * @hide
1915     */
1916    static final int PFLAG_INVALIDATED                 = 0x80000000;
1917
1918    /**
1919     * Masks for mPrivateFlags2, as generated by dumpFlags():
1920     *
1921     * |-------|-------|-------|-------|
1922     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1923     *                                1  PFLAG2_DRAG_HOVERED
1924     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1925     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1926     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1927     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1928     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1929     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1930     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1931     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1932     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1933     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1934     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1935     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1936     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1937     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1938     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1939     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1940     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1941     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1942     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1943     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1944     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1945     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1946     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1947     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1948     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1949     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1950     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1951     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1952     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1953     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1954     *    1                              PFLAG2_PADDING_RESOLVED
1955     *   1                               PFLAG2_DRAWABLE_RESOLVED
1956     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1957     * |-------|-------|-------|-------|
1958     */
1959
1960    /**
1961     * Indicates that this view has reported that it can accept the current drag's content.
1962     * Cleared when the drag operation concludes.
1963     * @hide
1964     */
1965    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1966
1967    /**
1968     * Indicates that this view is currently directly under the drag location in a
1969     * drag-and-drop operation involving content that it can accept.  Cleared when
1970     * the drag exits the view, or when the drag operation concludes.
1971     * @hide
1972     */
1973    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1974
1975    /** @hide */
1976    @IntDef({
1977        LAYOUT_DIRECTION_LTR,
1978        LAYOUT_DIRECTION_RTL,
1979        LAYOUT_DIRECTION_INHERIT,
1980        LAYOUT_DIRECTION_LOCALE
1981    })
1982    @Retention(RetentionPolicy.SOURCE)
1983    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1984    public @interface LayoutDir {}
1985
1986    /** @hide */
1987    @IntDef({
1988        LAYOUT_DIRECTION_LTR,
1989        LAYOUT_DIRECTION_RTL
1990    })
1991    @Retention(RetentionPolicy.SOURCE)
1992    public @interface ResolvedLayoutDir {}
1993
1994    /**
1995     * A flag to indicate that the layout direction of this view has not been defined yet.
1996     * @hide
1997     */
1998    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1999
2000    /**
2001     * Horizontal layout direction of this view is from Left to Right.
2002     * Use with {@link #setLayoutDirection}.
2003     */
2004    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2005
2006    /**
2007     * Horizontal layout direction of this view is from Right to Left.
2008     * Use with {@link #setLayoutDirection}.
2009     */
2010    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2011
2012    /**
2013     * Horizontal layout direction of this view is inherited from its parent.
2014     * Use with {@link #setLayoutDirection}.
2015     */
2016    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2017
2018    /**
2019     * Horizontal layout direction of this view is from deduced from the default language
2020     * script for the locale. Use with {@link #setLayoutDirection}.
2021     */
2022    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2023
2024    /**
2025     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2026     * @hide
2027     */
2028    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2029
2030    /**
2031     * Mask for use with private flags indicating bits used for horizontal layout direction.
2032     * @hide
2033     */
2034    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2035
2036    /**
2037     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2038     * right-to-left direction.
2039     * @hide
2040     */
2041    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2042
2043    /**
2044     * Indicates whether the view horizontal layout direction has been resolved.
2045     * @hide
2046     */
2047    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2048
2049    /**
2050     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2051     * @hide
2052     */
2053    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2054            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2055
2056    /*
2057     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2058     * flag value.
2059     * @hide
2060     */
2061    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2062            LAYOUT_DIRECTION_LTR,
2063            LAYOUT_DIRECTION_RTL,
2064            LAYOUT_DIRECTION_INHERIT,
2065            LAYOUT_DIRECTION_LOCALE
2066    };
2067
2068    /**
2069     * Default horizontal layout direction.
2070     */
2071    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2072
2073    /**
2074     * Default horizontal layout direction.
2075     * @hide
2076     */
2077    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2078
2079    /**
2080     * Text direction is inherited through {@link ViewGroup}
2081     */
2082    public static final int TEXT_DIRECTION_INHERIT = 0;
2083
2084    /**
2085     * Text direction is using "first strong algorithm". The first strong directional character
2086     * determines the paragraph direction. If there is no strong directional character, the
2087     * paragraph direction is the view's resolved layout direction.
2088     */
2089    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2090
2091    /**
2092     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2093     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2094     * If there are neither, the paragraph direction is the view's resolved layout direction.
2095     */
2096    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2097
2098    /**
2099     * Text direction is forced to LTR.
2100     */
2101    public static final int TEXT_DIRECTION_LTR = 3;
2102
2103    /**
2104     * Text direction is forced to RTL.
2105     */
2106    public static final int TEXT_DIRECTION_RTL = 4;
2107
2108    /**
2109     * Text direction is coming from the system Locale.
2110     */
2111    public static final int TEXT_DIRECTION_LOCALE = 5;
2112
2113    /**
2114     * Text direction is using "first strong algorithm". The first strong directional character
2115     * determines the paragraph direction. If there is no strong directional character, the
2116     * paragraph direction is LTR.
2117     */
2118    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2119
2120    /**
2121     * Text direction is using "first strong algorithm". The first strong directional character
2122     * determines the paragraph direction. If there is no strong directional character, the
2123     * paragraph direction is RTL.
2124     */
2125    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2126
2127    /**
2128     * Default text direction is inherited
2129     */
2130    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2131
2132    /**
2133     * Default resolved text direction
2134     * @hide
2135     */
2136    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2137
2138    /**
2139     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2140     * @hide
2141     */
2142    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2143
2144    /**
2145     * Mask for use with private flags indicating bits used for text direction.
2146     * @hide
2147     */
2148    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2149            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2150
2151    /**
2152     * Array of text direction flags for mapping attribute "textDirection" to correct
2153     * flag value.
2154     * @hide
2155     */
2156    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2157            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2158            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2159            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2160            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2161            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2162            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2163            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2164            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2165    };
2166
2167    /**
2168     * Indicates whether the view text direction has been resolved.
2169     * @hide
2170     */
2171    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2172            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2173
2174    /**
2175     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2176     * @hide
2177     */
2178    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2179
2180    /**
2181     * Mask for use with private flags indicating bits used for resolved text direction.
2182     * @hide
2183     */
2184    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2185            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2186
2187    /**
2188     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2189     * @hide
2190     */
2191    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2192            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2193
2194    /** @hide */
2195    @IntDef({
2196        TEXT_ALIGNMENT_INHERIT,
2197        TEXT_ALIGNMENT_GRAVITY,
2198        TEXT_ALIGNMENT_CENTER,
2199        TEXT_ALIGNMENT_TEXT_START,
2200        TEXT_ALIGNMENT_TEXT_END,
2201        TEXT_ALIGNMENT_VIEW_START,
2202        TEXT_ALIGNMENT_VIEW_END
2203    })
2204    @Retention(RetentionPolicy.SOURCE)
2205    public @interface TextAlignment {}
2206
2207    /**
2208     * Default text alignment. The text alignment of this View is inherited from its parent.
2209     * Use with {@link #setTextAlignment(int)}
2210     */
2211    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2212
2213    /**
2214     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2215     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2216     *
2217     * Use with {@link #setTextAlignment(int)}
2218     */
2219    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2220
2221    /**
2222     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2223     *
2224     * Use with {@link #setTextAlignment(int)}
2225     */
2226    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2227
2228    /**
2229     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2230     *
2231     * Use with {@link #setTextAlignment(int)}
2232     */
2233    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2234
2235    /**
2236     * Center the paragraph, e.g. ALIGN_CENTER.
2237     *
2238     * Use with {@link #setTextAlignment(int)}
2239     */
2240    public static final int TEXT_ALIGNMENT_CENTER = 4;
2241
2242    /**
2243     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2244     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2245     *
2246     * Use with {@link #setTextAlignment(int)}
2247     */
2248    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2249
2250    /**
2251     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2252     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2253     *
2254     * Use with {@link #setTextAlignment(int)}
2255     */
2256    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2257
2258    /**
2259     * Default text alignment is inherited
2260     */
2261    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2262
2263    /**
2264     * Default resolved text alignment
2265     * @hide
2266     */
2267    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2268
2269    /**
2270      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2271      * @hide
2272      */
2273    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2274
2275    /**
2276      * Mask for use with private flags indicating bits used for text alignment.
2277      * @hide
2278      */
2279    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2280
2281    /**
2282     * Array of text direction flags for mapping attribute "textAlignment" to correct
2283     * flag value.
2284     * @hide
2285     */
2286    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2287            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2288            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2289            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2290            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2291            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2292            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2293            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2294    };
2295
2296    /**
2297     * Indicates whether the view text alignment has been resolved.
2298     * @hide
2299     */
2300    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2301
2302    /**
2303     * Bit shift to get the resolved text alignment.
2304     * @hide
2305     */
2306    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2307
2308    /**
2309     * Mask for use with private flags indicating bits used for text alignment.
2310     * @hide
2311     */
2312    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2313            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2314
2315    /**
2316     * Indicates whether if the view text alignment has been resolved to gravity
2317     */
2318    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2319            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2320
2321    // Accessiblity constants for mPrivateFlags2
2322
2323    /**
2324     * Shift for the bits in {@link #mPrivateFlags2} related to the
2325     * "importantForAccessibility" attribute.
2326     */
2327    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2328
2329    /**
2330     * Automatically determine whether a view is important for accessibility.
2331     */
2332    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2333
2334    /**
2335     * The view is important for accessibility.
2336     */
2337    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2338
2339    /**
2340     * The view is not important for accessibility.
2341     */
2342    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2343
2344    /**
2345     * The view is not important for accessibility, nor are any of its
2346     * descendant views.
2347     */
2348    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2349
2350    /**
2351     * The default whether the view is important for accessibility.
2352     */
2353    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2354
2355    /**
2356     * Mask for obtaining the bits which specify how to determine
2357     * whether a view is important for accessibility.
2358     */
2359    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2360        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2361        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2362        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2363
2364    /**
2365     * Shift for the bits in {@link #mPrivateFlags2} related to the
2366     * "accessibilityLiveRegion" attribute.
2367     */
2368    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2369
2370    /**
2371     * Live region mode specifying that accessibility services should not
2372     * automatically announce changes to this view. This is the default live
2373     * region mode for most views.
2374     * <p>
2375     * Use with {@link #setAccessibilityLiveRegion(int)}.
2376     */
2377    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2378
2379    /**
2380     * Live region mode specifying that accessibility services should announce
2381     * changes to this view.
2382     * <p>
2383     * Use with {@link #setAccessibilityLiveRegion(int)}.
2384     */
2385    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2386
2387    /**
2388     * Live region mode specifying that accessibility services should interrupt
2389     * ongoing speech to immediately announce changes to this view.
2390     * <p>
2391     * Use with {@link #setAccessibilityLiveRegion(int)}.
2392     */
2393    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2394
2395    /**
2396     * The default whether the view is important for accessibility.
2397     */
2398    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2399
2400    /**
2401     * Mask for obtaining the bits which specify a view's accessibility live
2402     * region mode.
2403     */
2404    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2405            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2406            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2407
2408    /**
2409     * Flag indicating whether a view has accessibility focus.
2410     */
2411    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2412
2413    /**
2414     * Flag whether the accessibility state of the subtree rooted at this view changed.
2415     */
2416    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2417
2418    /**
2419     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2420     * is used to check whether later changes to the view's transform should invalidate the
2421     * view to force the quickReject test to run again.
2422     */
2423    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2424
2425    /**
2426     * Flag indicating that start/end padding has been resolved into left/right padding
2427     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2428     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2429     * during measurement. In some special cases this is required such as when an adapter-based
2430     * view measures prospective children without attaching them to a window.
2431     */
2432    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2433
2434    /**
2435     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2436     */
2437    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2438
2439    /**
2440     * Indicates that the view is tracking some sort of transient state
2441     * that the app should not need to be aware of, but that the framework
2442     * should take special care to preserve.
2443     */
2444    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2445
2446    /**
2447     * Group of bits indicating that RTL properties resolution is done.
2448     */
2449    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2450            PFLAG2_TEXT_DIRECTION_RESOLVED |
2451            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2452            PFLAG2_PADDING_RESOLVED |
2453            PFLAG2_DRAWABLE_RESOLVED;
2454
2455    // There are a couple of flags left in mPrivateFlags2
2456
2457    /* End of masks for mPrivateFlags2 */
2458
2459    /**
2460     * Masks for mPrivateFlags3, as generated by dumpFlags():
2461     *
2462     * |-------|-------|-------|-------|
2463     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2464     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2465     *                               1   PFLAG3_IS_LAID_OUT
2466     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2467     *                             1     PFLAG3_CALLED_SUPER
2468     *                            1      PFLAG3_APPLYING_INSETS
2469     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2470     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2471     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2472     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2473     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2474     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2475     *                     1             PFLAG3_SCROLL_INDICATOR_START
2476     *                    1              PFLAG3_SCROLL_INDICATOR_END
2477     *                   1               PFLAG3_ASSIST_BLOCKED
2478     *                  1                PFLAG3_CLUSTER
2479     *                 1                 PFLAG3_SECTION
2480     *           xxxxxx                  * NO LONGER NEEDED, SHOULD BE REUSED *
2481     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2482     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2483     *        1                          PFLAG3_TEMPORARY_DETACH
2484     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2485     * |-------|-------|-------|-------|
2486     */
2487
2488    /**
2489     * Flag indicating that view has a transform animation set on it. This is used to track whether
2490     * an animation is cleared between successive frames, in order to tell the associated
2491     * DisplayList to clear its animation matrix.
2492     */
2493    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2494
2495    /**
2496     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2497     * animation is cleared between successive frames, in order to tell the associated
2498     * DisplayList to restore its alpha value.
2499     */
2500    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2501
2502    /**
2503     * Flag indicating that the view has been through at least one layout since it
2504     * was last attached to a window.
2505     */
2506    static final int PFLAG3_IS_LAID_OUT = 0x4;
2507
2508    /**
2509     * Flag indicating that a call to measure() was skipped and should be done
2510     * instead when layout() is invoked.
2511     */
2512    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2513
2514    /**
2515     * Flag indicating that an overridden method correctly called down to
2516     * the superclass implementation as required by the API spec.
2517     */
2518    static final int PFLAG3_CALLED_SUPER = 0x10;
2519
2520    /**
2521     * Flag indicating that we're in the process of applying window insets.
2522     */
2523    static final int PFLAG3_APPLYING_INSETS = 0x20;
2524
2525    /**
2526     * Flag indicating that we're in the process of fitting system windows using the old method.
2527     */
2528    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2529
2530    /**
2531     * Flag indicating that nested scrolling is enabled for this view.
2532     * The view will optionally cooperate with views up its parent chain to allow for
2533     * integrated nested scrolling along the same axis.
2534     */
2535    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2536
2537    /**
2538     * Flag indicating that the bottom scroll indicator should be displayed
2539     * when this view can scroll up.
2540     */
2541    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2542
2543    /**
2544     * Flag indicating that the bottom scroll indicator should be displayed
2545     * when this view can scroll down.
2546     */
2547    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2548
2549    /**
2550     * Flag indicating that the left scroll indicator should be displayed
2551     * when this view can scroll left.
2552     */
2553    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2554
2555    /**
2556     * Flag indicating that the right scroll indicator should be displayed
2557     * when this view can scroll right.
2558     */
2559    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2560
2561    /**
2562     * Flag indicating that the start scroll indicator should be displayed
2563     * when this view can scroll in the start direction.
2564     */
2565    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2566
2567    /**
2568     * Flag indicating that the end scroll indicator should be displayed
2569     * when this view can scroll in the end direction.
2570     */
2571    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2572
2573    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2574
2575    static final int SCROLL_INDICATORS_NONE = 0x0000;
2576
2577    /**
2578     * Mask for use with setFlags indicating bits used for indicating which
2579     * scroll indicators are enabled.
2580     */
2581    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2582            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2583            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2584            | PFLAG3_SCROLL_INDICATOR_END;
2585
2586    /**
2587     * Left-shift required to translate between public scroll indicator flags
2588     * and internal PFLAGS3 flags. When used as a right-shift, translates
2589     * PFLAGS3 flags to public flags.
2590     */
2591    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2592
2593    /** @hide */
2594    @Retention(RetentionPolicy.SOURCE)
2595    @IntDef(flag = true,
2596            value = {
2597                    SCROLL_INDICATOR_TOP,
2598                    SCROLL_INDICATOR_BOTTOM,
2599                    SCROLL_INDICATOR_LEFT,
2600                    SCROLL_INDICATOR_RIGHT,
2601                    SCROLL_INDICATOR_START,
2602                    SCROLL_INDICATOR_END,
2603            })
2604    public @interface ScrollIndicators {}
2605
2606    /**
2607     * Scroll indicator direction for the top edge of the view.
2608     *
2609     * @see #setScrollIndicators(int)
2610     * @see #setScrollIndicators(int, int)
2611     * @see #getScrollIndicators()
2612     */
2613    public static final int SCROLL_INDICATOR_TOP =
2614            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2615
2616    /**
2617     * Scroll indicator direction for the bottom edge of the view.
2618     *
2619     * @see #setScrollIndicators(int)
2620     * @see #setScrollIndicators(int, int)
2621     * @see #getScrollIndicators()
2622     */
2623    public static final int SCROLL_INDICATOR_BOTTOM =
2624            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2625
2626    /**
2627     * Scroll indicator direction for the left edge of the view.
2628     *
2629     * @see #setScrollIndicators(int)
2630     * @see #setScrollIndicators(int, int)
2631     * @see #getScrollIndicators()
2632     */
2633    public static final int SCROLL_INDICATOR_LEFT =
2634            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2635
2636    /**
2637     * Scroll indicator direction for the right edge of the view.
2638     *
2639     * @see #setScrollIndicators(int)
2640     * @see #setScrollIndicators(int, int)
2641     * @see #getScrollIndicators()
2642     */
2643    public static final int SCROLL_INDICATOR_RIGHT =
2644            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2645
2646    /**
2647     * Scroll indicator direction for the starting edge of the view.
2648     * <p>
2649     * Resolved according to the view's layout direction, see
2650     * {@link #getLayoutDirection()} for more information.
2651     *
2652     * @see #setScrollIndicators(int)
2653     * @see #setScrollIndicators(int, int)
2654     * @see #getScrollIndicators()
2655     */
2656    public static final int SCROLL_INDICATOR_START =
2657            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2658
2659    /**
2660     * Scroll indicator direction for the ending edge of the view.
2661     * <p>
2662     * Resolved according to the view's layout direction, see
2663     * {@link #getLayoutDirection()} for more information.
2664     *
2665     * @see #setScrollIndicators(int)
2666     * @see #setScrollIndicators(int, int)
2667     * @see #getScrollIndicators()
2668     */
2669    public static final int SCROLL_INDICATOR_END =
2670            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2671
2672    /**
2673     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2674     * into this view.<p>
2675     */
2676    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2677
2678    /**
2679     * Flag indicating that the view is a root of a keyboard navigation cluster.
2680     *
2681     * @see #isKeyboardNavigationCluster()
2682     * @see #setKeyboardNavigationCluster(boolean)
2683     */
2684    private static final int PFLAG3_CLUSTER = 0x8000;
2685
2686    /**
2687     * Flag indicating that the view is a root of a keyboard navigation section.
2688     *
2689     * @see #isKeyboardNavigationSection()
2690     * @see #setKeyboardNavigationSection(boolean)
2691     */
2692    private static final int PFLAG3_SECTION = 0x10000;
2693
2694    /**
2695     * Whether this view has rendered elements that overlap (see {@link
2696     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2697     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2698     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2699     * determined by whatever {@link #hasOverlappingRendering()} returns.
2700     */
2701    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2702
2703    /**
2704     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2705     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2706     */
2707    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2708
2709    /**
2710     * Flag indicating that the view is temporarily detached from the parent view.
2711     *
2712     * @see #onStartTemporaryDetach()
2713     * @see #onFinishTemporaryDetach()
2714     */
2715    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
2716
2717    /**
2718     * Flag indicating that the view does not wish to be revealed within its parent
2719     * hierarchy when it gains focus. Expressed in the negative since the historical
2720     * default behavior is to reveal on focus; this flag suppresses that behavior.
2721     *
2722     * @see #setRevealOnFocusHint(boolean)
2723     * @see #getRevealOnFocusHint()
2724     */
2725    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
2726
2727    /* End of masks for mPrivateFlags3 */
2728
2729    /**
2730     * Always allow a user to over-scroll this view, provided it is a
2731     * view that can scroll.
2732     *
2733     * @see #getOverScrollMode()
2734     * @see #setOverScrollMode(int)
2735     */
2736    public static final int OVER_SCROLL_ALWAYS = 0;
2737
2738    /**
2739     * Allow a user to over-scroll this view only if the content is large
2740     * enough to meaningfully scroll, provided it is a view that can scroll.
2741     *
2742     * @see #getOverScrollMode()
2743     * @see #setOverScrollMode(int)
2744     */
2745    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2746
2747    /**
2748     * Never allow a user to over-scroll this view.
2749     *
2750     * @see #getOverScrollMode()
2751     * @see #setOverScrollMode(int)
2752     */
2753    public static final int OVER_SCROLL_NEVER = 2;
2754
2755    /**
2756     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2757     * requested the system UI (status bar) to be visible (the default).
2758     *
2759     * @see #setSystemUiVisibility(int)
2760     */
2761    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2762
2763    /**
2764     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2765     * system UI to enter an unobtrusive "low profile" mode.
2766     *
2767     * <p>This is for use in games, book readers, video players, or any other
2768     * "immersive" application where the usual system chrome is deemed too distracting.
2769     *
2770     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2771     *
2772     * @see #setSystemUiVisibility(int)
2773     */
2774    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2775
2776    /**
2777     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2778     * system navigation be temporarily hidden.
2779     *
2780     * <p>This is an even less obtrusive state than that called for by
2781     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2782     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2783     * those to disappear. This is useful (in conjunction with the
2784     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2785     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2786     * window flags) for displaying content using every last pixel on the display.
2787     *
2788     * <p>There is a limitation: because navigation controls are so important, the least user
2789     * interaction will cause them to reappear immediately.  When this happens, both
2790     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2791     * so that both elements reappear at the same time.
2792     *
2793     * @see #setSystemUiVisibility(int)
2794     */
2795    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2796
2797    /**
2798     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2799     * into the normal fullscreen mode so that its content can take over the screen
2800     * while still allowing the user to interact with the application.
2801     *
2802     * <p>This has the same visual effect as
2803     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2804     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2805     * meaning that non-critical screen decorations (such as the status bar) will be
2806     * hidden while the user is in the View's window, focusing the experience on
2807     * that content.  Unlike the window flag, if you are using ActionBar in
2808     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2809     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2810     * hide the action bar.
2811     *
2812     * <p>This approach to going fullscreen is best used over the window flag when
2813     * it is a transient state -- that is, the application does this at certain
2814     * points in its user interaction where it wants to allow the user to focus
2815     * on content, but not as a continuous state.  For situations where the application
2816     * would like to simply stay full screen the entire time (such as a game that
2817     * wants to take over the screen), the
2818     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2819     * is usually a better approach.  The state set here will be removed by the system
2820     * in various situations (such as the user moving to another application) like
2821     * the other system UI states.
2822     *
2823     * <p>When using this flag, the application should provide some easy facility
2824     * for the user to go out of it.  A common example would be in an e-book
2825     * reader, where tapping on the screen brings back whatever screen and UI
2826     * decorations that had been hidden while the user was immersed in reading
2827     * the book.
2828     *
2829     * @see #setSystemUiVisibility(int)
2830     */
2831    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2832
2833    /**
2834     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2835     * flags, we would like a stable view of the content insets given to
2836     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2837     * will always represent the worst case that the application can expect
2838     * as a continuous state.  In the stock Android UI this is the space for
2839     * the system bar, nav bar, and status bar, but not more transient elements
2840     * such as an input method.
2841     *
2842     * The stable layout your UI sees is based on the system UI modes you can
2843     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2844     * then you will get a stable layout for changes of the
2845     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2846     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2847     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2848     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2849     * with a stable layout.  (Note that you should avoid using
2850     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2851     *
2852     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2853     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2854     * then a hidden status bar will be considered a "stable" state for purposes
2855     * here.  This allows your UI to continually hide the status bar, while still
2856     * using the system UI flags to hide the action bar while still retaining
2857     * a stable layout.  Note that changing the window fullscreen flag will never
2858     * provide a stable layout for a clean transition.
2859     *
2860     * <p>If you are using ActionBar in
2861     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2862     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2863     * insets it adds to those given to the application.
2864     */
2865    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2866
2867    /**
2868     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2869     * to be laid out as if it has requested
2870     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2871     * allows it to avoid artifacts when switching in and out of that mode, at
2872     * the expense that some of its user interface may be covered by screen
2873     * decorations when they are shown.  You can perform layout of your inner
2874     * UI elements to account for the navigation system UI through the
2875     * {@link #fitSystemWindows(Rect)} method.
2876     */
2877    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2878
2879    /**
2880     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2881     * to be laid out as if it has requested
2882     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2883     * allows it to avoid artifacts when switching in and out of that mode, at
2884     * the expense that some of its user interface may be covered by screen
2885     * decorations when they are shown.  You can perform layout of your inner
2886     * UI elements to account for non-fullscreen system UI through the
2887     * {@link #fitSystemWindows(Rect)} method.
2888     */
2889    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2890
2891    /**
2892     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2893     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2894     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2895     * user interaction.
2896     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2897     * has an effect when used in combination with that flag.</p>
2898     */
2899    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2900
2901    /**
2902     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2903     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2904     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2905     * experience while also hiding the system bars.  If this flag is not set,
2906     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2907     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2908     * if the user swipes from the top of the screen.
2909     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2910     * system gestures, such as swiping from the top of the screen.  These transient system bars
2911     * will overlay app’s content, may have some degree of transparency, and will automatically
2912     * hide after a short timeout.
2913     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2914     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2915     * with one or both of those flags.</p>
2916     */
2917    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2918
2919    /**
2920     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2921     * is compatible with light status bar backgrounds.
2922     *
2923     * <p>For this to take effect, the window must request
2924     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2925     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2926     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2927     *         FLAG_TRANSLUCENT_STATUS}.
2928     *
2929     * @see android.R.attr#windowLightStatusBar
2930     */
2931    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2932
2933    /**
2934     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
2935     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
2936     */
2937    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
2938
2939    /**
2940     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
2941     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
2942     */
2943    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
2944
2945    /**
2946     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
2947     * that is compatible with light navigation bar backgrounds.
2948     *
2949     * <p>For this to take effect, the window must request
2950     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2951     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2952     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
2953     *         FLAG_TRANSLUCENT_NAVIGATION}.
2954     */
2955    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
2956
2957    /**
2958     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2959     */
2960    @Deprecated
2961    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2962
2963    /**
2964     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2965     */
2966    @Deprecated
2967    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2968
2969    /**
2970     * @hide
2971     *
2972     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2973     * out of the public fields to keep the undefined bits out of the developer's way.
2974     *
2975     * Flag to make the status bar not expandable.  Unless you also
2976     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2977     */
2978    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2979
2980    /**
2981     * @hide
2982     *
2983     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2984     * out of the public fields to keep the undefined bits out of the developer's way.
2985     *
2986     * Flag to hide notification icons and scrolling ticker text.
2987     */
2988    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2989
2990    /**
2991     * @hide
2992     *
2993     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2994     * out of the public fields to keep the undefined bits out of the developer's way.
2995     *
2996     * Flag to disable incoming notification alerts.  This will not block
2997     * icons, but it will block sound, vibrating and other visual or aural notifications.
2998     */
2999    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3000
3001    /**
3002     * @hide
3003     *
3004     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3005     * out of the public fields to keep the undefined bits out of the developer's way.
3006     *
3007     * Flag to hide only the scrolling ticker.  Note that
3008     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3009     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3010     */
3011    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3012
3013    /**
3014     * @hide
3015     *
3016     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3017     * out of the public fields to keep the undefined bits out of the developer's way.
3018     *
3019     * Flag to hide the center system info area.
3020     */
3021    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3022
3023    /**
3024     * @hide
3025     *
3026     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3027     * out of the public fields to keep the undefined bits out of the developer's way.
3028     *
3029     * Flag to hide only the home button.  Don't use this
3030     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3031     */
3032    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3033
3034    /**
3035     * @hide
3036     *
3037     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3038     * out of the public fields to keep the undefined bits out of the developer's way.
3039     *
3040     * Flag to hide only the back button. Don't use this
3041     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3042     */
3043    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3044
3045    /**
3046     * @hide
3047     *
3048     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3049     * out of the public fields to keep the undefined bits out of the developer's way.
3050     *
3051     * Flag to hide only the clock.  You might use this if your activity has
3052     * its own clock making the status bar's clock redundant.
3053     */
3054    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3055
3056    /**
3057     * @hide
3058     *
3059     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3060     * out of the public fields to keep the undefined bits out of the developer's way.
3061     *
3062     * Flag to hide only the recent apps button. Don't use this
3063     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3064     */
3065    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3066
3067    /**
3068     * @hide
3069     *
3070     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3071     * out of the public fields to keep the undefined bits out of the developer's way.
3072     *
3073     * Flag to disable the global search gesture. Don't use this
3074     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3075     */
3076    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3077
3078    /**
3079     * @hide
3080     *
3081     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3082     * out of the public fields to keep the undefined bits out of the developer's way.
3083     *
3084     * Flag to specify that the status bar is displayed in transient mode.
3085     */
3086    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3087
3088    /**
3089     * @hide
3090     *
3091     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3092     * out of the public fields to keep the undefined bits out of the developer's way.
3093     *
3094     * Flag to specify that the navigation bar is displayed in transient mode.
3095     */
3096    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3097
3098    /**
3099     * @hide
3100     *
3101     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3102     * out of the public fields to keep the undefined bits out of the developer's way.
3103     *
3104     * Flag to specify that the hidden status bar would like to be shown.
3105     */
3106    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3107
3108    /**
3109     * @hide
3110     *
3111     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3112     * out of the public fields to keep the undefined bits out of the developer's way.
3113     *
3114     * Flag to specify that the hidden navigation bar would like to be shown.
3115     */
3116    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3117
3118    /**
3119     * @hide
3120     *
3121     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3122     * out of the public fields to keep the undefined bits out of the developer's way.
3123     *
3124     * Flag to specify that the status bar is displayed in translucent mode.
3125     */
3126    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3127
3128    /**
3129     * @hide
3130     *
3131     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3132     * out of the public fields to keep the undefined bits out of the developer's way.
3133     *
3134     * Flag to specify that the navigation bar is displayed in translucent mode.
3135     */
3136    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3137
3138    /**
3139     * @hide
3140     *
3141     * Makes navigation bar transparent (but not the status bar).
3142     */
3143    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3144
3145    /**
3146     * @hide
3147     *
3148     * Makes status bar transparent (but not the navigation bar).
3149     */
3150    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3151
3152    /**
3153     * @hide
3154     *
3155     * Makes both status bar and navigation bar transparent.
3156     */
3157    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3158            | STATUS_BAR_TRANSPARENT;
3159
3160    /**
3161     * @hide
3162     */
3163    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3164
3165    /**
3166     * These are the system UI flags that can be cleared by events outside
3167     * of an application.  Currently this is just the ability to tap on the
3168     * screen while hiding the navigation bar to have it return.
3169     * @hide
3170     */
3171    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3172            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3173            | SYSTEM_UI_FLAG_FULLSCREEN;
3174
3175    /**
3176     * Flags that can impact the layout in relation to system UI.
3177     */
3178    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3179            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3180            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3181
3182    /** @hide */
3183    @IntDef(flag = true,
3184            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3185    @Retention(RetentionPolicy.SOURCE)
3186    public @interface FindViewFlags {}
3187
3188    /**
3189     * Find views that render the specified text.
3190     *
3191     * @see #findViewsWithText(ArrayList, CharSequence, int)
3192     */
3193    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3194
3195    /**
3196     * Find find views that contain the specified content description.
3197     *
3198     * @see #findViewsWithText(ArrayList, CharSequence, int)
3199     */
3200    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3201
3202    /**
3203     * Find views that contain {@link AccessibilityNodeProvider}. Such
3204     * a View is a root of virtual view hierarchy and may contain the searched
3205     * text. If this flag is set Views with providers are automatically
3206     * added and it is a responsibility of the client to call the APIs of
3207     * the provider to determine whether the virtual tree rooted at this View
3208     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3209     * representing the virtual views with this text.
3210     *
3211     * @see #findViewsWithText(ArrayList, CharSequence, int)
3212     *
3213     * @hide
3214     */
3215    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3216
3217    /**
3218     * The undefined cursor position.
3219     *
3220     * @hide
3221     */
3222    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3223
3224    /**
3225     * Indicates that the screen has changed state and is now off.
3226     *
3227     * @see #onScreenStateChanged(int)
3228     */
3229    public static final int SCREEN_STATE_OFF = 0x0;
3230
3231    /**
3232     * Indicates that the screen has changed state and is now on.
3233     *
3234     * @see #onScreenStateChanged(int)
3235     */
3236    public static final int SCREEN_STATE_ON = 0x1;
3237
3238    /**
3239     * Indicates no axis of view scrolling.
3240     */
3241    public static final int SCROLL_AXIS_NONE = 0;
3242
3243    /**
3244     * Indicates scrolling along the horizontal axis.
3245     */
3246    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3247
3248    /**
3249     * Indicates scrolling along the vertical axis.
3250     */
3251    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3252
3253    /**
3254     * Controls the over-scroll mode for this view.
3255     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3256     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3257     * and {@link #OVER_SCROLL_NEVER}.
3258     */
3259    private int mOverScrollMode;
3260
3261    /**
3262     * The parent this view is attached to.
3263     * {@hide}
3264     *
3265     * @see #getParent()
3266     */
3267    protected ViewParent mParent;
3268
3269    /**
3270     * {@hide}
3271     */
3272    AttachInfo mAttachInfo;
3273
3274    /**
3275     * {@hide}
3276     */
3277    @ViewDebug.ExportedProperty(flagMapping = {
3278        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3279                name = "FORCE_LAYOUT"),
3280        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3281                name = "LAYOUT_REQUIRED"),
3282        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3283            name = "DRAWING_CACHE_INVALID", outputIf = false),
3284        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3285        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3286        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3287        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3288    }, formatToHexString = true)
3289    int mPrivateFlags;
3290    int mPrivateFlags2;
3291    int mPrivateFlags3;
3292
3293    /**
3294     * This view's request for the visibility of the status bar.
3295     * @hide
3296     */
3297    @ViewDebug.ExportedProperty(flagMapping = {
3298        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3299                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3300                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3301        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3302                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3303                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3304        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3305                                equals = SYSTEM_UI_FLAG_VISIBLE,
3306                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3307    }, formatToHexString = true)
3308    int mSystemUiVisibility;
3309
3310    /**
3311     * Reference count for transient state.
3312     * @see #setHasTransientState(boolean)
3313     */
3314    int mTransientStateCount = 0;
3315
3316    /**
3317     * Count of how many windows this view has been attached to.
3318     */
3319    int mWindowAttachCount;
3320
3321    /**
3322     * The layout parameters associated with this view and used by the parent
3323     * {@link android.view.ViewGroup} to determine how this view should be
3324     * laid out.
3325     * {@hide}
3326     */
3327    protected ViewGroup.LayoutParams mLayoutParams;
3328
3329    /**
3330     * The view flags hold various views states.
3331     * {@hide}
3332     */
3333    @ViewDebug.ExportedProperty(formatToHexString = true)
3334    int mViewFlags;
3335
3336    static class TransformationInfo {
3337        /**
3338         * The transform matrix for the View. This transform is calculated internally
3339         * based on the translation, rotation, and scale properties.
3340         *
3341         * Do *not* use this variable directly; instead call getMatrix(), which will
3342         * load the value from the View's RenderNode.
3343         */
3344        private final Matrix mMatrix = new Matrix();
3345
3346        /**
3347         * The inverse transform matrix for the View. This transform is calculated
3348         * internally based on the translation, rotation, and scale properties.
3349         *
3350         * Do *not* use this variable directly; instead call getInverseMatrix(),
3351         * which will load the value from the View's RenderNode.
3352         */
3353        private Matrix mInverseMatrix;
3354
3355        /**
3356         * The opacity of the View. This is a value from 0 to 1, where 0 means
3357         * completely transparent and 1 means completely opaque.
3358         */
3359        @ViewDebug.ExportedProperty
3360        float mAlpha = 1f;
3361
3362        /**
3363         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3364         * property only used by transitions, which is composited with the other alpha
3365         * values to calculate the final visual alpha value.
3366         */
3367        float mTransitionAlpha = 1f;
3368    }
3369
3370    TransformationInfo mTransformationInfo;
3371
3372    /**
3373     * Current clip bounds. to which all drawing of this view are constrained.
3374     */
3375    Rect mClipBounds = null;
3376
3377    private boolean mLastIsOpaque;
3378
3379    /**
3380     * The distance in pixels from the left edge of this view's parent
3381     * to the left edge of this view.
3382     * {@hide}
3383     */
3384    @ViewDebug.ExportedProperty(category = "layout")
3385    protected int mLeft;
3386    /**
3387     * The distance in pixels from the left edge of this view's parent
3388     * to the right edge of this view.
3389     * {@hide}
3390     */
3391    @ViewDebug.ExportedProperty(category = "layout")
3392    protected int mRight;
3393    /**
3394     * The distance in pixels from the top edge of this view's parent
3395     * to the top edge of this view.
3396     * {@hide}
3397     */
3398    @ViewDebug.ExportedProperty(category = "layout")
3399    protected int mTop;
3400    /**
3401     * The distance in pixels from the top edge of this view's parent
3402     * to the bottom edge of this view.
3403     * {@hide}
3404     */
3405    @ViewDebug.ExportedProperty(category = "layout")
3406    protected int mBottom;
3407
3408    /**
3409     * The offset, in pixels, by which the content of this view is scrolled
3410     * horizontally.
3411     * {@hide}
3412     */
3413    @ViewDebug.ExportedProperty(category = "scrolling")
3414    protected int mScrollX;
3415    /**
3416     * The offset, in pixels, by which the content of this view is scrolled
3417     * vertically.
3418     * {@hide}
3419     */
3420    @ViewDebug.ExportedProperty(category = "scrolling")
3421    protected int mScrollY;
3422
3423    /**
3424     * The left padding in pixels, that is the distance in pixels between the
3425     * left edge of this view and the left edge of its content.
3426     * {@hide}
3427     */
3428    @ViewDebug.ExportedProperty(category = "padding")
3429    protected int mPaddingLeft = 0;
3430    /**
3431     * The right padding in pixels, that is the distance in pixels between the
3432     * right edge of this view and the right edge of its content.
3433     * {@hide}
3434     */
3435    @ViewDebug.ExportedProperty(category = "padding")
3436    protected int mPaddingRight = 0;
3437    /**
3438     * The top padding in pixels, that is the distance in pixels between the
3439     * top edge of this view and the top edge of its content.
3440     * {@hide}
3441     */
3442    @ViewDebug.ExportedProperty(category = "padding")
3443    protected int mPaddingTop;
3444    /**
3445     * The bottom padding in pixels, that is the distance in pixels between the
3446     * bottom edge of this view and the bottom edge of its content.
3447     * {@hide}
3448     */
3449    @ViewDebug.ExportedProperty(category = "padding")
3450    protected int mPaddingBottom;
3451
3452    /**
3453     * The layout insets in pixels, that is the distance in pixels between the
3454     * visible edges of this view its bounds.
3455     */
3456    private Insets mLayoutInsets;
3457
3458    /**
3459     * Briefly describes the view and is primarily used for accessibility support.
3460     */
3461    private CharSequence mContentDescription;
3462
3463    /**
3464     * Specifies the id of a view for which this view serves as a label for
3465     * accessibility purposes.
3466     */
3467    private int mLabelForId = View.NO_ID;
3468
3469    /**
3470     * Predicate for matching labeled view id with its label for
3471     * accessibility purposes.
3472     */
3473    private MatchLabelForPredicate mMatchLabelForPredicate;
3474
3475    /**
3476     * Specifies a view before which this one is visited in accessibility traversal.
3477     */
3478    private int mAccessibilityTraversalBeforeId = NO_ID;
3479
3480    /**
3481     * Specifies a view after which this one is visited in accessibility traversal.
3482     */
3483    private int mAccessibilityTraversalAfterId = NO_ID;
3484
3485    /**
3486     * Predicate for matching a view by its id.
3487     */
3488    private MatchIdPredicate mMatchIdPredicate;
3489
3490    /**
3491     * Cache the paddingRight set by the user to append to the scrollbar's size.
3492     *
3493     * @hide
3494     */
3495    @ViewDebug.ExportedProperty(category = "padding")
3496    protected int mUserPaddingRight;
3497
3498    /**
3499     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3500     *
3501     * @hide
3502     */
3503    @ViewDebug.ExportedProperty(category = "padding")
3504    protected int mUserPaddingBottom;
3505
3506    /**
3507     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3508     *
3509     * @hide
3510     */
3511    @ViewDebug.ExportedProperty(category = "padding")
3512    protected int mUserPaddingLeft;
3513
3514    /**
3515     * Cache the paddingStart set by the user to append to the scrollbar's size.
3516     *
3517     */
3518    @ViewDebug.ExportedProperty(category = "padding")
3519    int mUserPaddingStart;
3520
3521    /**
3522     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3523     *
3524     */
3525    @ViewDebug.ExportedProperty(category = "padding")
3526    int mUserPaddingEnd;
3527
3528    /**
3529     * Cache initial left padding.
3530     *
3531     * @hide
3532     */
3533    int mUserPaddingLeftInitial;
3534
3535    /**
3536     * Cache initial right padding.
3537     *
3538     * @hide
3539     */
3540    int mUserPaddingRightInitial;
3541
3542    /**
3543     * Default undefined padding
3544     */
3545    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3546
3547    /**
3548     * Cache if a left padding has been defined
3549     */
3550    private boolean mLeftPaddingDefined = false;
3551
3552    /**
3553     * Cache if a right padding has been defined
3554     */
3555    private boolean mRightPaddingDefined = false;
3556
3557    /**
3558     * @hide
3559     */
3560    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3561    /**
3562     * @hide
3563     */
3564    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3565
3566    private LongSparseLongArray mMeasureCache;
3567
3568    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3569    private Drawable mBackground;
3570    private TintInfo mBackgroundTint;
3571
3572    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3573    private ForegroundInfo mForegroundInfo;
3574
3575    private Drawable mScrollIndicatorDrawable;
3576
3577    /**
3578     * RenderNode used for backgrounds.
3579     * <p>
3580     * When non-null and valid, this is expected to contain an up-to-date copy
3581     * of the background drawable. It is cleared on temporary detach, and reset
3582     * on cleanup.
3583     */
3584    private RenderNode mBackgroundRenderNode;
3585
3586    private int mBackgroundResource;
3587    private boolean mBackgroundSizeChanged;
3588
3589    private String mTransitionName;
3590
3591    static class TintInfo {
3592        ColorStateList mTintList;
3593        PorterDuff.Mode mTintMode;
3594        boolean mHasTintMode;
3595        boolean mHasTintList;
3596    }
3597
3598    private static class ForegroundInfo {
3599        private Drawable mDrawable;
3600        private TintInfo mTintInfo;
3601        private int mGravity = Gravity.FILL;
3602        private boolean mInsidePadding = true;
3603        private boolean mBoundsChanged = true;
3604        private final Rect mSelfBounds = new Rect();
3605        private final Rect mOverlayBounds = new Rect();
3606    }
3607
3608    static class ListenerInfo {
3609        /**
3610         * Listener used to dispatch focus change events.
3611         * This field should be made private, so it is hidden from the SDK.
3612         * {@hide}
3613         */
3614        protected OnFocusChangeListener mOnFocusChangeListener;
3615
3616        /**
3617         * Listeners for layout change events.
3618         */
3619        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3620
3621        protected OnScrollChangeListener mOnScrollChangeListener;
3622
3623        /**
3624         * Listeners for attach events.
3625         */
3626        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3627
3628        /**
3629         * Listener used to dispatch click events.
3630         * This field should be made private, so it is hidden from the SDK.
3631         * {@hide}
3632         */
3633        public OnClickListener mOnClickListener;
3634
3635        /**
3636         * Listener used to dispatch long click events.
3637         * This field should be made private, so it is hidden from the SDK.
3638         * {@hide}
3639         */
3640        protected OnLongClickListener mOnLongClickListener;
3641
3642        /**
3643         * Listener used to dispatch context click events. This field should be made private, so it
3644         * is hidden from the SDK.
3645         * {@hide}
3646         */
3647        protected OnContextClickListener mOnContextClickListener;
3648
3649        /**
3650         * Listener used to build the context menu.
3651         * This field should be made private, so it is hidden from the SDK.
3652         * {@hide}
3653         */
3654        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3655
3656        private OnKeyListener mOnKeyListener;
3657
3658        private OnTouchListener mOnTouchListener;
3659
3660        private OnHoverListener mOnHoverListener;
3661
3662        private OnGenericMotionListener mOnGenericMotionListener;
3663
3664        private OnDragListener mOnDragListener;
3665
3666        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3667
3668        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3669    }
3670
3671    ListenerInfo mListenerInfo;
3672
3673    private static class TooltipInfo {
3674        /**
3675         * Text to be displayed in a tooltip popup.
3676         */
3677        @Nullable
3678        CharSequence mTooltip;
3679
3680        /**
3681         * View-relative position of the tooltip anchor point.
3682         */
3683        int mAnchorX;
3684        int mAnchorY;
3685
3686        /**
3687         * The tooltip popup.
3688         */
3689        @Nullable
3690        TooltipPopup mTooltipPopup;
3691
3692        /**
3693         * Set to true if the tooltip was shown as a result of a long click.
3694         */
3695        boolean mTooltipFromLongClick;
3696
3697        /**
3698         * Keep these Runnables so that they can be used to reschedule.
3699         */
3700        Runnable mShowTooltipRunnable;
3701        Runnable mHideTooltipRunnable;
3702    }
3703
3704    TooltipInfo mTooltipInfo;
3705
3706    // Temporary values used to hold (x,y) coordinates when delegating from the
3707    // two-arg performLongClick() method to the legacy no-arg version.
3708    private float mLongClickX = Float.NaN;
3709    private float mLongClickY = Float.NaN;
3710
3711    /**
3712     * The application environment this view lives in.
3713     * This field should be made private, so it is hidden from the SDK.
3714     * {@hide}
3715     */
3716    @ViewDebug.ExportedProperty(deepExport = true)
3717    protected Context mContext;
3718
3719    private final Resources mResources;
3720
3721    private ScrollabilityCache mScrollCache;
3722
3723    private int[] mDrawableState = null;
3724
3725    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3726
3727    /**
3728     * Animator that automatically runs based on state changes.
3729     */
3730    private StateListAnimator mStateListAnimator;
3731
3732    /**
3733     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3734     * the user may specify which view to go to next.
3735     */
3736    private int mNextFocusLeftId = View.NO_ID;
3737
3738    /**
3739     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3740     * the user may specify which view to go to next.
3741     */
3742    private int mNextFocusRightId = View.NO_ID;
3743
3744    /**
3745     * When this view has focus and the next focus is {@link #FOCUS_UP},
3746     * the user may specify which view to go to next.
3747     */
3748    private int mNextFocusUpId = View.NO_ID;
3749
3750    /**
3751     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3752     * the user may specify which view to go to next.
3753     */
3754    private int mNextFocusDownId = View.NO_ID;
3755
3756    /**
3757     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3758     * the user may specify which view to go to next.
3759     */
3760    int mNextFocusForwardId = View.NO_ID;
3761
3762    /**
3763     * User-specified next keyboard navigation cluster.
3764     */
3765    int mNextClusterForwardId = View.NO_ID;
3766
3767    /**
3768     * User-specified next keyboard navigation section.
3769     */
3770    int mNextSectionForwardId = View.NO_ID;
3771
3772    private CheckForLongPress mPendingCheckForLongPress;
3773    private CheckForTap mPendingCheckForTap = null;
3774    private PerformClick mPerformClick;
3775    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3776
3777    private UnsetPressedState mUnsetPressedState;
3778
3779    /**
3780     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3781     * up event while a long press is invoked as soon as the long press duration is reached, so
3782     * a long press could be performed before the tap is checked, in which case the tap's action
3783     * should not be invoked.
3784     */
3785    private boolean mHasPerformedLongPress;
3786
3787    /**
3788     * Whether a context click button is currently pressed down. This is true when the stylus is
3789     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3790     * pressed. This is false once the button is released or if the stylus has been lifted.
3791     */
3792    private boolean mInContextButtonPress;
3793
3794    /**
3795     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3796     * true after a stylus button press has occured, when the next up event should not be recognized
3797     * as a tap.
3798     */
3799    private boolean mIgnoreNextUpEvent;
3800
3801    /**
3802     * The minimum height of the view. We'll try our best to have the height
3803     * of this view to at least this amount.
3804     */
3805    @ViewDebug.ExportedProperty(category = "measurement")
3806    private int mMinHeight;
3807
3808    /**
3809     * The minimum width of the view. We'll try our best to have the width
3810     * of this view to at least this amount.
3811     */
3812    @ViewDebug.ExportedProperty(category = "measurement")
3813    private int mMinWidth;
3814
3815    /**
3816     * The delegate to handle touch events that are physically in this view
3817     * but should be handled by another view.
3818     */
3819    private TouchDelegate mTouchDelegate = null;
3820
3821    /**
3822     * Solid color to use as a background when creating the drawing cache. Enables
3823     * the cache to use 16 bit bitmaps instead of 32 bit.
3824     */
3825    private int mDrawingCacheBackgroundColor = 0;
3826
3827    /**
3828     * Special tree observer used when mAttachInfo is null.
3829     */
3830    private ViewTreeObserver mFloatingTreeObserver;
3831
3832    /**
3833     * Cache the touch slop from the context that created the view.
3834     */
3835    private int mTouchSlop;
3836
3837    /**
3838     * Object that handles automatic animation of view properties.
3839     */
3840    private ViewPropertyAnimator mAnimator = null;
3841
3842    /**
3843     * List of registered FrameMetricsObservers.
3844     */
3845    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
3846
3847    /**
3848     * Flag indicating that a drag can cross window boundaries.  When
3849     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3850     * with this flag set, all visible applications with targetSdkVersion >=
3851     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
3852     * in the drag operation and receive the dragged content.
3853     *
3854     * <p>If this is the only flag set, then the drag recipient will only have access to text data
3855     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3856     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
3857     */
3858    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3859
3860    /**
3861     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3862     * request read access to the content URI(s) contained in the {@link ClipData} object.
3863     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3864     */
3865    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3866
3867    /**
3868     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3869     * request write access to the content URI(s) contained in the {@link ClipData} object.
3870     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3871     */
3872    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3873
3874    /**
3875     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3876     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3877     * reboots until explicitly revoked with
3878     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3879     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3880     */
3881    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3882            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3883
3884    /**
3885     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3886     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3887     * match against the original granted URI.
3888     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3889     */
3890    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3891            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3892
3893    /**
3894     * Flag indicating that the drag shadow will be opaque.  When
3895     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3896     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3897     */
3898    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3899
3900    /**
3901     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3902     */
3903    private float mVerticalScrollFactor;
3904
3905    /**
3906     * Position of the vertical scroll bar.
3907     */
3908    private int mVerticalScrollbarPosition;
3909
3910    /**
3911     * Position the scroll bar at the default position as determined by the system.
3912     */
3913    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3914
3915    /**
3916     * Position the scroll bar along the left edge.
3917     */
3918    public static final int SCROLLBAR_POSITION_LEFT = 1;
3919
3920    /**
3921     * Position the scroll bar along the right edge.
3922     */
3923    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3924
3925    /**
3926     * Indicates that the view does not have a layer.
3927     *
3928     * @see #getLayerType()
3929     * @see #setLayerType(int, android.graphics.Paint)
3930     * @see #LAYER_TYPE_SOFTWARE
3931     * @see #LAYER_TYPE_HARDWARE
3932     */
3933    public static final int LAYER_TYPE_NONE = 0;
3934
3935    /**
3936     * <p>Indicates that the view has a software layer. A software layer is backed
3937     * by a bitmap and causes the view to be rendered using Android's software
3938     * rendering pipeline, even if hardware acceleration is enabled.</p>
3939     *
3940     * <p>Software layers have various usages:</p>
3941     * <p>When the application is not using hardware acceleration, a software layer
3942     * is useful to apply a specific color filter and/or blending mode and/or
3943     * translucency to a view and all its children.</p>
3944     * <p>When the application is using hardware acceleration, a software layer
3945     * is useful to render drawing primitives not supported by the hardware
3946     * accelerated pipeline. It can also be used to cache a complex view tree
3947     * into a texture and reduce the complexity of drawing operations. For instance,
3948     * when animating a complex view tree with a translation, a software layer can
3949     * be used to render the view tree only once.</p>
3950     * <p>Software layers should be avoided when the affected view tree updates
3951     * often. Every update will require to re-render the software layer, which can
3952     * potentially be slow (particularly when hardware acceleration is turned on
3953     * since the layer will have to be uploaded into a hardware texture after every
3954     * update.)</p>
3955     *
3956     * @see #getLayerType()
3957     * @see #setLayerType(int, android.graphics.Paint)
3958     * @see #LAYER_TYPE_NONE
3959     * @see #LAYER_TYPE_HARDWARE
3960     */
3961    public static final int LAYER_TYPE_SOFTWARE = 1;
3962
3963    /**
3964     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3965     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3966     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3967     * rendering pipeline, but only if hardware acceleration is turned on for the
3968     * view hierarchy. When hardware acceleration is turned off, hardware layers
3969     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3970     *
3971     * <p>A hardware layer is useful to apply a specific color filter and/or
3972     * blending mode and/or translucency to a view and all its children.</p>
3973     * <p>A hardware layer can be used to cache a complex view tree into a
3974     * texture and reduce the complexity of drawing operations. For instance,
3975     * when animating a complex view tree with a translation, a hardware layer can
3976     * be used to render the view tree only once.</p>
3977     * <p>A hardware layer can also be used to increase the rendering quality when
3978     * rotation transformations are applied on a view. It can also be used to
3979     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3980     *
3981     * @see #getLayerType()
3982     * @see #setLayerType(int, android.graphics.Paint)
3983     * @see #LAYER_TYPE_NONE
3984     * @see #LAYER_TYPE_SOFTWARE
3985     */
3986    public static final int LAYER_TYPE_HARDWARE = 2;
3987
3988    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3989            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3990            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3991            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3992    })
3993    int mLayerType = LAYER_TYPE_NONE;
3994    Paint mLayerPaint;
3995
3996
3997    /**
3998     * <p>When setting a {@link android.app.assist.AssistStructure}, its nodes should not contain
3999     * PII (Personally Identifiable Information).
4000     */
4001    // TODO(b/33197203) (b/33269702): improve documentation: mention all cases, show examples, etc.
4002    public static final int ASSIST_FLAG_SANITIZED_TEXT = 0x1;
4003
4004    /**
4005     * <p>When setting a {@link android.app.assist.AssistStructure}, its nodes should contain all
4006     * type of data, even sensitive PII (Personally Identifiable Information) like passwords or
4007     * credit card numbers.
4008     */
4009    public static final int ASSIST_FLAG_NON_SANITIZED_TEXT = 0x2;
4010
4011    /**
4012     * Set to true when drawing cache is enabled and cannot be created.
4013     *
4014     * @hide
4015     */
4016    public boolean mCachingFailed;
4017    private Bitmap mDrawingCache;
4018    private Bitmap mUnscaledDrawingCache;
4019
4020    /**
4021     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4022     * <p>
4023     * When non-null and valid, this is expected to contain an up-to-date copy
4024     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4025     * cleanup.
4026     */
4027    final RenderNode mRenderNode;
4028
4029    /**
4030     * Set to true when the view is sending hover accessibility events because it
4031     * is the innermost hovered view.
4032     */
4033    private boolean mSendingHoverAccessibilityEvents;
4034
4035    /**
4036     * Delegate for injecting accessibility functionality.
4037     */
4038    AccessibilityDelegate mAccessibilityDelegate;
4039
4040    /**
4041     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4042     * and add/remove objects to/from the overlay directly through the Overlay methods.
4043     */
4044    ViewOverlay mOverlay;
4045
4046    /**
4047     * The currently active parent view for receiving delegated nested scrolling events.
4048     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4049     * by {@link #stopNestedScroll()} at the same point where we clear
4050     * requestDisallowInterceptTouchEvent.
4051     */
4052    private ViewParent mNestedScrollingParent;
4053
4054    /**
4055     * Consistency verifier for debugging purposes.
4056     * @hide
4057     */
4058    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4059            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4060                    new InputEventConsistencyVerifier(this, 0) : null;
4061
4062    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4063
4064    private int[] mTempNestedScrollConsumed;
4065
4066    /**
4067     * An overlay is going to draw this View instead of being drawn as part of this
4068     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4069     * when this view is invalidated.
4070     */
4071    GhostView mGhostView;
4072
4073    /**
4074     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4075     * @hide
4076     */
4077    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4078    public String[] mAttributes;
4079
4080    /**
4081     * Maps a Resource id to its name.
4082     */
4083    private static SparseArray<String> mAttributeMap;
4084
4085    /**
4086     * Queue of pending runnables. Used to postpone calls to post() until this
4087     * view is attached and has a handler.
4088     */
4089    private HandlerActionQueue mRunQueue;
4090
4091    /**
4092     * The pointer icon when the mouse hovers on this view. The default is null.
4093     */
4094    private PointerIcon mPointerIcon;
4095
4096    /**
4097     * @hide
4098     */
4099    String mStartActivityRequestWho;
4100
4101    @Nullable
4102    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4103
4104    /**
4105     * Simple constructor to use when creating a view from code.
4106     *
4107     * @param context The Context the view is running in, through which it can
4108     *        access the current theme, resources, etc.
4109     */
4110    public View(Context context) {
4111        mContext = context;
4112        mResources = context != null ? context.getResources() : null;
4113        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
4114        // Set some flags defaults
4115        mPrivateFlags2 =
4116                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4117                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4118                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4119                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4120                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4121                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4122        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4123        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4124        mUserPaddingStart = UNDEFINED_PADDING;
4125        mUserPaddingEnd = UNDEFINED_PADDING;
4126        mRenderNode = RenderNode.create(getClass().getName(), this);
4127
4128        if (!sCompatibilityDone && context != null) {
4129            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4130
4131            // Older apps may need this compatibility hack for measurement.
4132            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
4133
4134            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4135            // of whether a layout was requested on that View.
4136            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
4137
4138            Canvas.sCompatibilityRestore = targetSdkVersion < M;
4139
4140            // In M and newer, our widgets can pass a "hint" value in the size
4141            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4142            // know what the expected parent size is going to be, so e.g. list items can size
4143            // themselves at 1/3 the size of their container. It breaks older apps though,
4144            // specifically apps that use some popular open source libraries.
4145            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
4146
4147            // Old versions of the platform would give different results from
4148            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4149            // modes, so we always need to run an additional EXACTLY pass.
4150            sAlwaysRemeasureExactly = targetSdkVersion <= M;
4151
4152            // Prior to N, layout params could change without requiring a
4153            // subsequent call to setLayoutParams() and they would usually
4154            // work. Partial layout breaks this assumption.
4155            sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
4156
4157            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4158            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4159            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
4160
4161            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4162            // in apps so we target check it to avoid breaking existing apps.
4163            sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N;
4164
4165            sCascadedDragDrop = targetSdkVersion < N;
4166
4167            sCompatibilityDone = true;
4168        }
4169    }
4170
4171    /**
4172     * Constructor that is called when inflating a view from XML. This is called
4173     * when a view is being constructed from an XML file, supplying attributes
4174     * that were specified in the XML file. This version uses a default style of
4175     * 0, so the only attribute values applied are those in the Context's Theme
4176     * and the given AttributeSet.
4177     *
4178     * <p>
4179     * The method onFinishInflate() will be called after all children have been
4180     * added.
4181     *
4182     * @param context The Context the view is running in, through which it can
4183     *        access the current theme, resources, etc.
4184     * @param attrs The attributes of the XML tag that is inflating the view.
4185     * @see #View(Context, AttributeSet, int)
4186     */
4187    public View(Context context, @Nullable AttributeSet attrs) {
4188        this(context, attrs, 0);
4189    }
4190
4191    /**
4192     * Perform inflation from XML and apply a class-specific base style from a
4193     * theme attribute. This constructor of View allows subclasses to use their
4194     * own base style when they are inflating. For example, a Button class's
4195     * constructor would call this version of the super class constructor and
4196     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4197     * allows the theme's button style to modify all of the base view attributes
4198     * (in particular its background) as well as the Button class's attributes.
4199     *
4200     * @param context The Context the view is running in, through which it can
4201     *        access the current theme, resources, etc.
4202     * @param attrs The attributes of the XML tag that is inflating the view.
4203     * @param defStyleAttr An attribute in the current theme that contains a
4204     *        reference to a style resource that supplies default values for
4205     *        the view. Can be 0 to not look for defaults.
4206     * @see #View(Context, AttributeSet)
4207     */
4208    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4209        this(context, attrs, defStyleAttr, 0);
4210    }
4211
4212    /**
4213     * Perform inflation from XML and apply a class-specific base style from a
4214     * theme attribute or style resource. This constructor of View allows
4215     * subclasses to use their own base style when they are inflating.
4216     * <p>
4217     * When determining the final value of a particular attribute, there are
4218     * four inputs that come into play:
4219     * <ol>
4220     * <li>Any attribute values in the given AttributeSet.
4221     * <li>The style resource specified in the AttributeSet (named "style").
4222     * <li>The default style specified by <var>defStyleAttr</var>.
4223     * <li>The default style specified by <var>defStyleRes</var>.
4224     * <li>The base values in this theme.
4225     * </ol>
4226     * <p>
4227     * Each of these inputs is considered in-order, with the first listed taking
4228     * precedence over the following ones. In other words, if in the
4229     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4230     * , then the button's text will <em>always</em> be black, regardless of
4231     * what is specified in any of the styles.
4232     *
4233     * @param context The Context the view is running in, through which it can
4234     *        access the current theme, resources, etc.
4235     * @param attrs The attributes of the XML tag that is inflating the view.
4236     * @param defStyleAttr An attribute in the current theme that contains a
4237     *        reference to a style resource that supplies default values for
4238     *        the view. Can be 0 to not look for defaults.
4239     * @param defStyleRes A resource identifier of a style resource that
4240     *        supplies default values for the view, used only if
4241     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4242     *        to not look for defaults.
4243     * @see #View(Context, AttributeSet, int)
4244     */
4245    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4246        this(context);
4247
4248        final TypedArray a = context.obtainStyledAttributes(
4249                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4250
4251        if (mDebugViewAttributes) {
4252            saveAttributeData(attrs, a);
4253        }
4254
4255        Drawable background = null;
4256
4257        int leftPadding = -1;
4258        int topPadding = -1;
4259        int rightPadding = -1;
4260        int bottomPadding = -1;
4261        int startPadding = UNDEFINED_PADDING;
4262        int endPadding = UNDEFINED_PADDING;
4263
4264        int padding = -1;
4265        int paddingHorizontal = -1;
4266        int paddingVertical = -1;
4267
4268        int viewFlagValues = 0;
4269        int viewFlagMasks = 0;
4270
4271        boolean setScrollContainer = false;
4272
4273        int x = 0;
4274        int y = 0;
4275
4276        float tx = 0;
4277        float ty = 0;
4278        float tz = 0;
4279        float elevation = 0;
4280        float rotation = 0;
4281        float rotationX = 0;
4282        float rotationY = 0;
4283        float sx = 1f;
4284        float sy = 1f;
4285        boolean transformSet = false;
4286
4287        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4288        int overScrollMode = mOverScrollMode;
4289        boolean initializeScrollbars = false;
4290        boolean initializeScrollIndicators = false;
4291
4292        boolean startPaddingDefined = false;
4293        boolean endPaddingDefined = false;
4294        boolean leftPaddingDefined = false;
4295        boolean rightPaddingDefined = false;
4296
4297        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4298
4299        final int N = a.getIndexCount();
4300        for (int i = 0; i < N; i++) {
4301            int attr = a.getIndex(i);
4302            switch (attr) {
4303                case com.android.internal.R.styleable.View_background:
4304                    background = a.getDrawable(attr);
4305                    break;
4306                case com.android.internal.R.styleable.View_padding:
4307                    padding = a.getDimensionPixelSize(attr, -1);
4308                    mUserPaddingLeftInitial = padding;
4309                    mUserPaddingRightInitial = padding;
4310                    leftPaddingDefined = true;
4311                    rightPaddingDefined = true;
4312                    break;
4313                case com.android.internal.R.styleable.View_paddingHorizontal:
4314                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4315                    mUserPaddingLeftInitial = paddingHorizontal;
4316                    mUserPaddingRightInitial = paddingHorizontal;
4317                    leftPaddingDefined = true;
4318                    rightPaddingDefined = true;
4319                    break;
4320                case com.android.internal.R.styleable.View_paddingVertical:
4321                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4322                    break;
4323                 case com.android.internal.R.styleable.View_paddingLeft:
4324                    leftPadding = a.getDimensionPixelSize(attr, -1);
4325                    mUserPaddingLeftInitial = leftPadding;
4326                    leftPaddingDefined = true;
4327                    break;
4328                case com.android.internal.R.styleable.View_paddingTop:
4329                    topPadding = a.getDimensionPixelSize(attr, -1);
4330                    break;
4331                case com.android.internal.R.styleable.View_paddingRight:
4332                    rightPadding = a.getDimensionPixelSize(attr, -1);
4333                    mUserPaddingRightInitial = rightPadding;
4334                    rightPaddingDefined = true;
4335                    break;
4336                case com.android.internal.R.styleable.View_paddingBottom:
4337                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4338                    break;
4339                case com.android.internal.R.styleable.View_paddingStart:
4340                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4341                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4342                    break;
4343                case com.android.internal.R.styleable.View_paddingEnd:
4344                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4345                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4346                    break;
4347                case com.android.internal.R.styleable.View_scrollX:
4348                    x = a.getDimensionPixelOffset(attr, 0);
4349                    break;
4350                case com.android.internal.R.styleable.View_scrollY:
4351                    y = a.getDimensionPixelOffset(attr, 0);
4352                    break;
4353                case com.android.internal.R.styleable.View_alpha:
4354                    setAlpha(a.getFloat(attr, 1f));
4355                    break;
4356                case com.android.internal.R.styleable.View_transformPivotX:
4357                    setPivotX(a.getDimension(attr, 0));
4358                    break;
4359                case com.android.internal.R.styleable.View_transformPivotY:
4360                    setPivotY(a.getDimension(attr, 0));
4361                    break;
4362                case com.android.internal.R.styleable.View_translationX:
4363                    tx = a.getDimension(attr, 0);
4364                    transformSet = true;
4365                    break;
4366                case com.android.internal.R.styleable.View_translationY:
4367                    ty = a.getDimension(attr, 0);
4368                    transformSet = true;
4369                    break;
4370                case com.android.internal.R.styleable.View_translationZ:
4371                    tz = a.getDimension(attr, 0);
4372                    transformSet = true;
4373                    break;
4374                case com.android.internal.R.styleable.View_elevation:
4375                    elevation = a.getDimension(attr, 0);
4376                    transformSet = true;
4377                    break;
4378                case com.android.internal.R.styleable.View_rotation:
4379                    rotation = a.getFloat(attr, 0);
4380                    transformSet = true;
4381                    break;
4382                case com.android.internal.R.styleable.View_rotationX:
4383                    rotationX = a.getFloat(attr, 0);
4384                    transformSet = true;
4385                    break;
4386                case com.android.internal.R.styleable.View_rotationY:
4387                    rotationY = a.getFloat(attr, 0);
4388                    transformSet = true;
4389                    break;
4390                case com.android.internal.R.styleable.View_scaleX:
4391                    sx = a.getFloat(attr, 1f);
4392                    transformSet = true;
4393                    break;
4394                case com.android.internal.R.styleable.View_scaleY:
4395                    sy = a.getFloat(attr, 1f);
4396                    transformSet = true;
4397                    break;
4398                case com.android.internal.R.styleable.View_id:
4399                    mID = a.getResourceId(attr, NO_ID);
4400                    break;
4401                case com.android.internal.R.styleable.View_tag:
4402                    mTag = a.getText(attr);
4403                    break;
4404                case com.android.internal.R.styleable.View_fitsSystemWindows:
4405                    if (a.getBoolean(attr, false)) {
4406                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4407                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4408                    }
4409                    break;
4410                case com.android.internal.R.styleable.View_focusable:
4411                    if (a.getBoolean(attr, false)) {
4412                        viewFlagValues |= FOCUSABLE;
4413                        viewFlagMasks |= FOCUSABLE_MASK;
4414                    }
4415                    break;
4416                case com.android.internal.R.styleable.View_focusableInTouchMode:
4417                    if (a.getBoolean(attr, false)) {
4418                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4419                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4420                    }
4421                    break;
4422                case com.android.internal.R.styleable.View_clickable:
4423                    if (a.getBoolean(attr, false)) {
4424                        viewFlagValues |= CLICKABLE;
4425                        viewFlagMasks |= CLICKABLE;
4426                    }
4427                    break;
4428                case com.android.internal.R.styleable.View_longClickable:
4429                    if (a.getBoolean(attr, false)) {
4430                        viewFlagValues |= LONG_CLICKABLE;
4431                        viewFlagMasks |= LONG_CLICKABLE;
4432                    }
4433                    break;
4434                case com.android.internal.R.styleable.View_contextClickable:
4435                    if (a.getBoolean(attr, false)) {
4436                        viewFlagValues |= CONTEXT_CLICKABLE;
4437                        viewFlagMasks |= CONTEXT_CLICKABLE;
4438                    }
4439                    break;
4440                case com.android.internal.R.styleable.View_saveEnabled:
4441                    if (!a.getBoolean(attr, true)) {
4442                        viewFlagValues |= SAVE_DISABLED;
4443                        viewFlagMasks |= SAVE_DISABLED_MASK;
4444                    }
4445                    break;
4446                case com.android.internal.R.styleable.View_duplicateParentState:
4447                    if (a.getBoolean(attr, false)) {
4448                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4449                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4450                    }
4451                    break;
4452                case com.android.internal.R.styleable.View_visibility:
4453                    final int visibility = a.getInt(attr, 0);
4454                    if (visibility != 0) {
4455                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4456                        viewFlagMasks |= VISIBILITY_MASK;
4457                    }
4458                    break;
4459                case com.android.internal.R.styleable.View_layoutDirection:
4460                    // Clear any layout direction flags (included resolved bits) already set
4461                    mPrivateFlags2 &=
4462                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4463                    // Set the layout direction flags depending on the value of the attribute
4464                    final int layoutDirection = a.getInt(attr, -1);
4465                    final int value = (layoutDirection != -1) ?
4466                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4467                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4468                    break;
4469                case com.android.internal.R.styleable.View_drawingCacheQuality:
4470                    final int cacheQuality = a.getInt(attr, 0);
4471                    if (cacheQuality != 0) {
4472                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4473                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4474                    }
4475                    break;
4476                case com.android.internal.R.styleable.View_contentDescription:
4477                    setContentDescription(a.getString(attr));
4478                    break;
4479                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4480                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4481                    break;
4482                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4483                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4484                    break;
4485                case com.android.internal.R.styleable.View_labelFor:
4486                    setLabelFor(a.getResourceId(attr, NO_ID));
4487                    break;
4488                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4489                    if (!a.getBoolean(attr, true)) {
4490                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4491                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4492                    }
4493                    break;
4494                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4495                    if (!a.getBoolean(attr, true)) {
4496                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4497                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4498                    }
4499                    break;
4500                case R.styleable.View_scrollbars:
4501                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4502                    if (scrollbars != SCROLLBARS_NONE) {
4503                        viewFlagValues |= scrollbars;
4504                        viewFlagMasks |= SCROLLBARS_MASK;
4505                        initializeScrollbars = true;
4506                    }
4507                    break;
4508                //noinspection deprecation
4509                case R.styleable.View_fadingEdge:
4510                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4511                        // Ignore the attribute starting with ICS
4512                        break;
4513                    }
4514                    // With builds < ICS, fall through and apply fading edges
4515                case R.styleable.View_requiresFadingEdge:
4516                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4517                    if (fadingEdge != FADING_EDGE_NONE) {
4518                        viewFlagValues |= fadingEdge;
4519                        viewFlagMasks |= FADING_EDGE_MASK;
4520                        initializeFadingEdgeInternal(a);
4521                    }
4522                    break;
4523                case R.styleable.View_scrollbarStyle:
4524                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4525                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4526                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4527                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4528                    }
4529                    break;
4530                case R.styleable.View_isScrollContainer:
4531                    setScrollContainer = true;
4532                    if (a.getBoolean(attr, false)) {
4533                        setScrollContainer(true);
4534                    }
4535                    break;
4536                case com.android.internal.R.styleable.View_keepScreenOn:
4537                    if (a.getBoolean(attr, false)) {
4538                        viewFlagValues |= KEEP_SCREEN_ON;
4539                        viewFlagMasks |= KEEP_SCREEN_ON;
4540                    }
4541                    break;
4542                case R.styleable.View_filterTouchesWhenObscured:
4543                    if (a.getBoolean(attr, false)) {
4544                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4545                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4546                    }
4547                    break;
4548                case R.styleable.View_nextFocusLeft:
4549                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4550                    break;
4551                case R.styleable.View_nextFocusRight:
4552                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4553                    break;
4554                case R.styleable.View_nextFocusUp:
4555                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4556                    break;
4557                case R.styleable.View_nextFocusDown:
4558                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4559                    break;
4560                case R.styleable.View_nextFocusForward:
4561                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4562                    break;
4563                case R.styleable.View_nextClusterForward:
4564                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4565                    break;
4566                case R.styleable.View_nextSectionForward:
4567                    mNextSectionForwardId = a.getResourceId(attr, View.NO_ID);
4568                    break;
4569                case R.styleable.View_minWidth:
4570                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4571                    break;
4572                case R.styleable.View_minHeight:
4573                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4574                    break;
4575                case R.styleable.View_onClick:
4576                    if (context.isRestricted()) {
4577                        throw new IllegalStateException("The android:onClick attribute cannot "
4578                                + "be used within a restricted context");
4579                    }
4580
4581                    final String handlerName = a.getString(attr);
4582                    if (handlerName != null) {
4583                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4584                    }
4585                    break;
4586                case R.styleable.View_overScrollMode:
4587                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4588                    break;
4589                case R.styleable.View_verticalScrollbarPosition:
4590                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4591                    break;
4592                case R.styleable.View_layerType:
4593                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4594                    break;
4595                case R.styleable.View_textDirection:
4596                    // Clear any text direction flag already set
4597                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4598                    // Set the text direction flags depending on the value of the attribute
4599                    final int textDirection = a.getInt(attr, -1);
4600                    if (textDirection != -1) {
4601                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4602                    }
4603                    break;
4604                case R.styleable.View_textAlignment:
4605                    // Clear any text alignment flag already set
4606                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4607                    // Set the text alignment flag depending on the value of the attribute
4608                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4609                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4610                    break;
4611                case R.styleable.View_importantForAccessibility:
4612                    setImportantForAccessibility(a.getInt(attr,
4613                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4614                    break;
4615                case R.styleable.View_accessibilityLiveRegion:
4616                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4617                    break;
4618                case R.styleable.View_transitionName:
4619                    setTransitionName(a.getString(attr));
4620                    break;
4621                case R.styleable.View_nestedScrollingEnabled:
4622                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4623                    break;
4624                case R.styleable.View_stateListAnimator:
4625                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4626                            a.getResourceId(attr, 0)));
4627                    break;
4628                case R.styleable.View_backgroundTint:
4629                    // This will get applied later during setBackground().
4630                    if (mBackgroundTint == null) {
4631                        mBackgroundTint = new TintInfo();
4632                    }
4633                    mBackgroundTint.mTintList = a.getColorStateList(
4634                            R.styleable.View_backgroundTint);
4635                    mBackgroundTint.mHasTintList = true;
4636                    break;
4637                case R.styleable.View_backgroundTintMode:
4638                    // This will get applied later during setBackground().
4639                    if (mBackgroundTint == null) {
4640                        mBackgroundTint = new TintInfo();
4641                    }
4642                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4643                            R.styleable.View_backgroundTintMode, -1), null);
4644                    mBackgroundTint.mHasTintMode = true;
4645                    break;
4646                case R.styleable.View_outlineProvider:
4647                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4648                            PROVIDER_BACKGROUND));
4649                    break;
4650                case R.styleable.View_foreground:
4651                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4652                        setForeground(a.getDrawable(attr));
4653                    }
4654                    break;
4655                case R.styleable.View_foregroundGravity:
4656                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4657                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4658                    }
4659                    break;
4660                case R.styleable.View_foregroundTintMode:
4661                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4662                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4663                    }
4664                    break;
4665                case R.styleable.View_foregroundTint:
4666                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4667                        setForegroundTintList(a.getColorStateList(attr));
4668                    }
4669                    break;
4670                case R.styleable.View_foregroundInsidePadding:
4671                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4672                        if (mForegroundInfo == null) {
4673                            mForegroundInfo = new ForegroundInfo();
4674                        }
4675                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4676                                mForegroundInfo.mInsidePadding);
4677                    }
4678                    break;
4679                case R.styleable.View_scrollIndicators:
4680                    final int scrollIndicators =
4681                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4682                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4683                    if (scrollIndicators != 0) {
4684                        mPrivateFlags3 |= scrollIndicators;
4685                        initializeScrollIndicators = true;
4686                    }
4687                    break;
4688                case R.styleable.View_pointerIcon:
4689                    final int resourceId = a.getResourceId(attr, 0);
4690                    if (resourceId != 0) {
4691                        setPointerIcon(PointerIcon.load(
4692                                context.getResources(), resourceId));
4693                    } else {
4694                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4695                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4696                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
4697                        }
4698                    }
4699                    break;
4700                case R.styleable.View_forceHasOverlappingRendering:
4701                    if (a.peekValue(attr) != null) {
4702                        forceHasOverlappingRendering(a.getBoolean(attr, true));
4703                    }
4704                    break;
4705                case R.styleable.View_tooltip:
4706                    setTooltip(a.getText(attr));
4707                    break;
4708                case R.styleable.View_keyboardNavigationCluster:
4709                    if (a.peekValue(attr) != null) {
4710                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
4711                    }
4712                    break;
4713                case R.styleable.View_keyboardNavigationSection:
4714                    if (a.peekValue(attr) != null) {
4715                        setKeyboardNavigationSection(a.getBoolean(attr, true));
4716                    }
4717                    break;
4718            }
4719        }
4720
4721        setOverScrollMode(overScrollMode);
4722
4723        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4724        // the resolved layout direction). Those cached values will be used later during padding
4725        // resolution.
4726        mUserPaddingStart = startPadding;
4727        mUserPaddingEnd = endPadding;
4728
4729        if (background != null) {
4730            setBackground(background);
4731        }
4732
4733        // setBackground above will record that padding is currently provided by the background.
4734        // If we have padding specified via xml, record that here instead and use it.
4735        mLeftPaddingDefined = leftPaddingDefined;
4736        mRightPaddingDefined = rightPaddingDefined;
4737
4738        if (padding >= 0) {
4739            leftPadding = padding;
4740            topPadding = padding;
4741            rightPadding = padding;
4742            bottomPadding = padding;
4743            mUserPaddingLeftInitial = padding;
4744            mUserPaddingRightInitial = padding;
4745        } else {
4746            if (paddingHorizontal >= 0) {
4747                leftPadding = paddingHorizontal;
4748                rightPadding = paddingHorizontal;
4749                mUserPaddingLeftInitial = paddingHorizontal;
4750                mUserPaddingRightInitial = paddingHorizontal;
4751            }
4752            if (paddingVertical >= 0) {
4753                topPadding = paddingVertical;
4754                bottomPadding = paddingVertical;
4755            }
4756        }
4757
4758        if (isRtlCompatibilityMode()) {
4759            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4760            // left / right padding are used if defined (meaning here nothing to do). If they are not
4761            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4762            // start / end and resolve them as left / right (layout direction is not taken into account).
4763            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4764            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4765            // defined.
4766            if (!mLeftPaddingDefined && startPaddingDefined) {
4767                leftPadding = startPadding;
4768            }
4769            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4770            if (!mRightPaddingDefined && endPaddingDefined) {
4771                rightPadding = endPadding;
4772            }
4773            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4774        } else {
4775            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4776            // values defined. Otherwise, left /right values are used.
4777            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4778            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4779            // defined.
4780            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4781
4782            if (mLeftPaddingDefined && !hasRelativePadding) {
4783                mUserPaddingLeftInitial = leftPadding;
4784            }
4785            if (mRightPaddingDefined && !hasRelativePadding) {
4786                mUserPaddingRightInitial = rightPadding;
4787            }
4788        }
4789
4790        internalSetPadding(
4791                mUserPaddingLeftInitial,
4792                topPadding >= 0 ? topPadding : mPaddingTop,
4793                mUserPaddingRightInitial,
4794                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4795
4796        if (viewFlagMasks != 0) {
4797            setFlags(viewFlagValues, viewFlagMasks);
4798        }
4799
4800        if (initializeScrollbars) {
4801            initializeScrollbarsInternal(a);
4802        }
4803
4804        if (initializeScrollIndicators) {
4805            initializeScrollIndicatorsInternal();
4806        }
4807
4808        a.recycle();
4809
4810        // Needs to be called after mViewFlags is set
4811        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4812            recomputePadding();
4813        }
4814
4815        if (x != 0 || y != 0) {
4816            scrollTo(x, y);
4817        }
4818
4819        if (transformSet) {
4820            setTranslationX(tx);
4821            setTranslationY(ty);
4822            setTranslationZ(tz);
4823            setElevation(elevation);
4824            setRotation(rotation);
4825            setRotationX(rotationX);
4826            setRotationY(rotationY);
4827            setScaleX(sx);
4828            setScaleY(sy);
4829        }
4830
4831        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4832            setScrollContainer(true);
4833        }
4834
4835        computeOpaqueFlags();
4836    }
4837
4838    /**
4839     * An implementation of OnClickListener that attempts to lazily load a
4840     * named click handling method from a parent or ancestor context.
4841     */
4842    private static class DeclaredOnClickListener implements OnClickListener {
4843        private final View mHostView;
4844        private final String mMethodName;
4845
4846        private Method mResolvedMethod;
4847        private Context mResolvedContext;
4848
4849        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4850            mHostView = hostView;
4851            mMethodName = methodName;
4852        }
4853
4854        @Override
4855        public void onClick(@NonNull View v) {
4856            if (mResolvedMethod == null) {
4857                resolveMethod(mHostView.getContext(), mMethodName);
4858            }
4859
4860            try {
4861                mResolvedMethod.invoke(mResolvedContext, v);
4862            } catch (IllegalAccessException e) {
4863                throw new IllegalStateException(
4864                        "Could not execute non-public method for android:onClick", e);
4865            } catch (InvocationTargetException e) {
4866                throw new IllegalStateException(
4867                        "Could not execute method for android:onClick", e);
4868            }
4869        }
4870
4871        @NonNull
4872        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4873            while (context != null) {
4874                try {
4875                    if (!context.isRestricted()) {
4876                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4877                        if (method != null) {
4878                            mResolvedMethod = method;
4879                            mResolvedContext = context;
4880                            return;
4881                        }
4882                    }
4883                } catch (NoSuchMethodException e) {
4884                    // Failed to find method, keep searching up the hierarchy.
4885                }
4886
4887                if (context instanceof ContextWrapper) {
4888                    context = ((ContextWrapper) context).getBaseContext();
4889                } else {
4890                    // Can't search up the hierarchy, null out and fail.
4891                    context = null;
4892                }
4893            }
4894
4895            final int id = mHostView.getId();
4896            final String idText = id == NO_ID ? "" : " with id '"
4897                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4898            throw new IllegalStateException("Could not find method " + mMethodName
4899                    + "(View) in a parent or ancestor Context for android:onClick "
4900                    + "attribute defined on view " + mHostView.getClass() + idText);
4901        }
4902    }
4903
4904    /**
4905     * Non-public constructor for use in testing
4906     */
4907    View() {
4908        mResources = null;
4909        mRenderNode = RenderNode.create(getClass().getName(), this);
4910    }
4911
4912    final boolean debugDraw() {
4913        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
4914    }
4915
4916    private static SparseArray<String> getAttributeMap() {
4917        if (mAttributeMap == null) {
4918            mAttributeMap = new SparseArray<>();
4919        }
4920        return mAttributeMap;
4921    }
4922
4923    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4924        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4925        final int indexCount = t.getIndexCount();
4926        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4927
4928        int i = 0;
4929
4930        // Store raw XML attributes.
4931        for (int j = 0; j < attrsCount; ++j) {
4932            attributes[i] = attrs.getAttributeName(j);
4933            attributes[i + 1] = attrs.getAttributeValue(j);
4934            i += 2;
4935        }
4936
4937        // Store resolved styleable attributes.
4938        final Resources res = t.getResources();
4939        final SparseArray<String> attributeMap = getAttributeMap();
4940        for (int j = 0; j < indexCount; ++j) {
4941            final int index = t.getIndex(j);
4942            if (!t.hasValueOrEmpty(index)) {
4943                // Value is undefined. Skip it.
4944                continue;
4945            }
4946
4947            final int resourceId = t.getResourceId(index, 0);
4948            if (resourceId == 0) {
4949                // Value is not a reference. Skip it.
4950                continue;
4951            }
4952
4953            String resourceName = attributeMap.get(resourceId);
4954            if (resourceName == null) {
4955                try {
4956                    resourceName = res.getResourceName(resourceId);
4957                } catch (Resources.NotFoundException e) {
4958                    resourceName = "0x" + Integer.toHexString(resourceId);
4959                }
4960                attributeMap.put(resourceId, resourceName);
4961            }
4962
4963            attributes[i] = resourceName;
4964            attributes[i + 1] = t.getString(index);
4965            i += 2;
4966        }
4967
4968        // Trim to fit contents.
4969        final String[] trimmed = new String[i];
4970        System.arraycopy(attributes, 0, trimmed, 0, i);
4971        mAttributes = trimmed;
4972    }
4973
4974    public String toString() {
4975        StringBuilder out = new StringBuilder(128);
4976        out.append(getClass().getName());
4977        out.append('{');
4978        out.append(Integer.toHexString(System.identityHashCode(this)));
4979        out.append(' ');
4980        switch (mViewFlags&VISIBILITY_MASK) {
4981            case VISIBLE: out.append('V'); break;
4982            case INVISIBLE: out.append('I'); break;
4983            case GONE: out.append('G'); break;
4984            default: out.append('.'); break;
4985        }
4986        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4987        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4988        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4989        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4990        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4991        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4992        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4993        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4994        out.append(' ');
4995        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4996        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4997        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4998        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4999            out.append('p');
5000        } else {
5001            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5002        }
5003        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5004        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5005        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5006        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5007        out.append(' ');
5008        out.append(mLeft);
5009        out.append(',');
5010        out.append(mTop);
5011        out.append('-');
5012        out.append(mRight);
5013        out.append(',');
5014        out.append(mBottom);
5015        final int id = getId();
5016        if (id != NO_ID) {
5017            out.append(" #");
5018            out.append(Integer.toHexString(id));
5019            final Resources r = mResources;
5020            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5021                try {
5022                    String pkgname;
5023                    switch (id&0xff000000) {
5024                        case 0x7f000000:
5025                            pkgname="app";
5026                            break;
5027                        case 0x01000000:
5028                            pkgname="android";
5029                            break;
5030                        default:
5031                            pkgname = r.getResourcePackageName(id);
5032                            break;
5033                    }
5034                    String typename = r.getResourceTypeName(id);
5035                    String entryname = r.getResourceEntryName(id);
5036                    out.append(" ");
5037                    out.append(pkgname);
5038                    out.append(":");
5039                    out.append(typename);
5040                    out.append("/");
5041                    out.append(entryname);
5042                } catch (Resources.NotFoundException e) {
5043                }
5044            }
5045        }
5046        out.append("}");
5047        return out.toString();
5048    }
5049
5050    /**
5051     * <p>
5052     * Initializes the fading edges from a given set of styled attributes. This
5053     * method should be called by subclasses that need fading edges and when an
5054     * instance of these subclasses is created programmatically rather than
5055     * being inflated from XML. This method is automatically called when the XML
5056     * is inflated.
5057     * </p>
5058     *
5059     * @param a the styled attributes set to initialize the fading edges from
5060     *
5061     * @removed
5062     */
5063    protected void initializeFadingEdge(TypedArray a) {
5064        // This method probably shouldn't have been included in the SDK to begin with.
5065        // It relies on 'a' having been initialized using an attribute filter array that is
5066        // not publicly available to the SDK. The old method has been renamed
5067        // to initializeFadingEdgeInternal and hidden for framework use only;
5068        // this one initializes using defaults to make it safe to call for apps.
5069
5070        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5071
5072        initializeFadingEdgeInternal(arr);
5073
5074        arr.recycle();
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     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5088     */
5089    protected void initializeFadingEdgeInternal(TypedArray a) {
5090        initScrollCache();
5091
5092        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5093                R.styleable.View_fadingEdgeLength,
5094                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5095    }
5096
5097    /**
5098     * Returns the size of the vertical faded edges used to indicate that more
5099     * content in this view is visible.
5100     *
5101     * @return The size in pixels of the vertical faded edge or 0 if vertical
5102     *         faded edges are not enabled for this view.
5103     * @attr ref android.R.styleable#View_fadingEdgeLength
5104     */
5105    public int getVerticalFadingEdgeLength() {
5106        if (isVerticalFadingEdgeEnabled()) {
5107            ScrollabilityCache cache = mScrollCache;
5108            if (cache != null) {
5109                return cache.fadingEdgeLength;
5110            }
5111        }
5112        return 0;
5113    }
5114
5115    /**
5116     * Set the size of the faded edge used to indicate that more content in this
5117     * view is available.  Will not change whether the fading edge is enabled; use
5118     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5119     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5120     * for the vertical or horizontal fading edges.
5121     *
5122     * @param length The size in pixels of the faded edge used to indicate that more
5123     *        content in this view is visible.
5124     */
5125    public void setFadingEdgeLength(int length) {
5126        initScrollCache();
5127        mScrollCache.fadingEdgeLength = length;
5128    }
5129
5130    /**
5131     * Returns the size of the horizontal faded edges used to indicate that more
5132     * content in this view is visible.
5133     *
5134     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5135     *         faded edges are not enabled for this view.
5136     * @attr ref android.R.styleable#View_fadingEdgeLength
5137     */
5138    public int getHorizontalFadingEdgeLength() {
5139        if (isHorizontalFadingEdgeEnabled()) {
5140            ScrollabilityCache cache = mScrollCache;
5141            if (cache != null) {
5142                return cache.fadingEdgeLength;
5143            }
5144        }
5145        return 0;
5146    }
5147
5148    /**
5149     * Returns the width of the vertical scrollbar.
5150     *
5151     * @return The width in pixels of the vertical scrollbar or 0 if there
5152     *         is no vertical scrollbar.
5153     */
5154    public int getVerticalScrollbarWidth() {
5155        ScrollabilityCache cache = mScrollCache;
5156        if (cache != null) {
5157            ScrollBarDrawable scrollBar = cache.scrollBar;
5158            if (scrollBar != null) {
5159                int size = scrollBar.getSize(true);
5160                if (size <= 0) {
5161                    size = cache.scrollBarSize;
5162                }
5163                return size;
5164            }
5165            return 0;
5166        }
5167        return 0;
5168    }
5169
5170    /**
5171     * Returns the height of the horizontal scrollbar.
5172     *
5173     * @return The height in pixels of the horizontal scrollbar or 0 if
5174     *         there is no horizontal scrollbar.
5175     */
5176    protected int getHorizontalScrollbarHeight() {
5177        ScrollabilityCache cache = mScrollCache;
5178        if (cache != null) {
5179            ScrollBarDrawable scrollBar = cache.scrollBar;
5180            if (scrollBar != null) {
5181                int size = scrollBar.getSize(false);
5182                if (size <= 0) {
5183                    size = cache.scrollBarSize;
5184                }
5185                return size;
5186            }
5187            return 0;
5188        }
5189        return 0;
5190    }
5191
5192    /**
5193     * <p>
5194     * Initializes the scrollbars from a given set of styled attributes. This
5195     * method should be called by subclasses that need scrollbars and when an
5196     * instance of these subclasses is created programmatically rather than
5197     * being inflated from XML. This method is automatically called when the XML
5198     * is inflated.
5199     * </p>
5200     *
5201     * @param a the styled attributes set to initialize the scrollbars from
5202     *
5203     * @removed
5204     */
5205    protected void initializeScrollbars(TypedArray a) {
5206        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5207        // using the View filter array which is not available to the SDK. As such, internal
5208        // framework usage now uses initializeScrollbarsInternal and we grab a default
5209        // TypedArray with the right filter instead here.
5210        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5211
5212        initializeScrollbarsInternal(arr);
5213
5214        // We ignored the method parameter. Recycle the one we actually did use.
5215        arr.recycle();
5216    }
5217
5218    /**
5219     * <p>
5220     * Initializes the scrollbars from a given set of styled attributes. This
5221     * method should be called by subclasses that need scrollbars and when an
5222     * instance of these subclasses is created programmatically rather than
5223     * being inflated from XML. This method is automatically called when the XML
5224     * is inflated.
5225     * </p>
5226     *
5227     * @param a the styled attributes set to initialize the scrollbars from
5228     * @hide
5229     */
5230    protected void initializeScrollbarsInternal(TypedArray a) {
5231        initScrollCache();
5232
5233        final ScrollabilityCache scrollabilityCache = mScrollCache;
5234
5235        if (scrollabilityCache.scrollBar == null) {
5236            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5237            scrollabilityCache.scrollBar.setState(getDrawableState());
5238            scrollabilityCache.scrollBar.setCallback(this);
5239        }
5240
5241        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5242
5243        if (!fadeScrollbars) {
5244            scrollabilityCache.state = ScrollabilityCache.ON;
5245        }
5246        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5247
5248
5249        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5250                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5251                        .getScrollBarFadeDuration());
5252        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5253                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5254                ViewConfiguration.getScrollDefaultDelay());
5255
5256
5257        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5258                com.android.internal.R.styleable.View_scrollbarSize,
5259                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5260
5261        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5262        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5263
5264        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5265        if (thumb != null) {
5266            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5267        }
5268
5269        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5270                false);
5271        if (alwaysDraw) {
5272            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5273        }
5274
5275        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5276        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5277
5278        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5279        if (thumb != null) {
5280            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5281        }
5282
5283        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5284                false);
5285        if (alwaysDraw) {
5286            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5287        }
5288
5289        // Apply layout direction to the new Drawables if needed
5290        final int layoutDirection = getLayoutDirection();
5291        if (track != null) {
5292            track.setLayoutDirection(layoutDirection);
5293        }
5294        if (thumb != null) {
5295            thumb.setLayoutDirection(layoutDirection);
5296        }
5297
5298        // Re-apply user/background padding so that scrollbar(s) get added
5299        resolvePadding();
5300    }
5301
5302    private void initializeScrollIndicatorsInternal() {
5303        // Some day maybe we'll break this into top/left/start/etc. and let the
5304        // client control it. Until then, you can have any scroll indicator you
5305        // want as long as it's a 1dp foreground-colored rectangle.
5306        if (mScrollIndicatorDrawable == null) {
5307            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5308        }
5309    }
5310
5311    /**
5312     * <p>
5313     * Initalizes the scrollability cache if necessary.
5314     * </p>
5315     */
5316    private void initScrollCache() {
5317        if (mScrollCache == null) {
5318            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5319        }
5320    }
5321
5322    private ScrollabilityCache getScrollCache() {
5323        initScrollCache();
5324        return mScrollCache;
5325    }
5326
5327    /**
5328     * Set the position of the vertical scroll bar. Should be one of
5329     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5330     * {@link #SCROLLBAR_POSITION_RIGHT}.
5331     *
5332     * @param position Where the vertical scroll bar should be positioned.
5333     */
5334    public void setVerticalScrollbarPosition(int position) {
5335        if (mVerticalScrollbarPosition != position) {
5336            mVerticalScrollbarPosition = position;
5337            computeOpaqueFlags();
5338            resolvePadding();
5339        }
5340    }
5341
5342    /**
5343     * @return The position where the vertical scroll bar will show, if applicable.
5344     * @see #setVerticalScrollbarPosition(int)
5345     */
5346    public int getVerticalScrollbarPosition() {
5347        return mVerticalScrollbarPosition;
5348    }
5349
5350    boolean isOnScrollbar(float x, float y) {
5351        if (mScrollCache == null) {
5352            return false;
5353        }
5354        x += getScrollX();
5355        y += getScrollY();
5356        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5357            final Rect bounds = mScrollCache.mScrollBarBounds;
5358            getVerticalScrollBarBounds(bounds);
5359            if (bounds.contains((int)x, (int)y)) {
5360                return true;
5361            }
5362        }
5363        if (isHorizontalScrollBarEnabled()) {
5364            final Rect bounds = mScrollCache.mScrollBarBounds;
5365            getHorizontalScrollBarBounds(bounds);
5366            if (bounds.contains((int)x, (int)y)) {
5367                return true;
5368            }
5369        }
5370        return false;
5371    }
5372
5373    boolean isOnScrollbarThumb(float x, float y) {
5374        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5375    }
5376
5377    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5378        if (mScrollCache == null) {
5379            return false;
5380        }
5381        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5382            x += getScrollX();
5383            y += getScrollY();
5384            final Rect bounds = mScrollCache.mScrollBarBounds;
5385            getVerticalScrollBarBounds(bounds);
5386            final int range = computeVerticalScrollRange();
5387            final int offset = computeVerticalScrollOffset();
5388            final int extent = computeVerticalScrollExtent();
5389            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5390                    extent, range);
5391            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5392                    extent, range, offset);
5393            final int thumbTop = bounds.top + thumbOffset;
5394            if (x >= bounds.left && x <= bounds.right && y >= thumbTop
5395                    && y <= thumbTop + thumbLength) {
5396                return true;
5397            }
5398        }
5399        return false;
5400    }
5401
5402    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5403        if (mScrollCache == null) {
5404            return false;
5405        }
5406        if (isHorizontalScrollBarEnabled()) {
5407            x += getScrollX();
5408            y += getScrollY();
5409            final Rect bounds = mScrollCache.mScrollBarBounds;
5410            getHorizontalScrollBarBounds(bounds);
5411            final int range = computeHorizontalScrollRange();
5412            final int offset = computeHorizontalScrollOffset();
5413            final int extent = computeHorizontalScrollExtent();
5414            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5415                    extent, range);
5416            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5417                    extent, range, offset);
5418            final int thumbLeft = bounds.left + thumbOffset;
5419            if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
5420                    && y <= bounds.bottom) {
5421                return true;
5422            }
5423        }
5424        return false;
5425    }
5426
5427    boolean isDraggingScrollBar() {
5428        return mScrollCache != null
5429                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5430    }
5431
5432    /**
5433     * Sets the state of all scroll indicators.
5434     * <p>
5435     * See {@link #setScrollIndicators(int, int)} for usage information.
5436     *
5437     * @param indicators a bitmask of indicators that should be enabled, or
5438     *                   {@code 0} to disable all indicators
5439     * @see #setScrollIndicators(int, int)
5440     * @see #getScrollIndicators()
5441     * @attr ref android.R.styleable#View_scrollIndicators
5442     */
5443    public void setScrollIndicators(@ScrollIndicators int indicators) {
5444        setScrollIndicators(indicators,
5445                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5446    }
5447
5448    /**
5449     * Sets the state of the scroll indicators specified by the mask. To change
5450     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5451     * <p>
5452     * When a scroll indicator is enabled, it will be displayed if the view
5453     * can scroll in the direction of the indicator.
5454     * <p>
5455     * Multiple indicator types may be enabled or disabled by passing the
5456     * logical OR of the desired types. If multiple types are specified, they
5457     * will all be set to the same enabled state.
5458     * <p>
5459     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5460     *
5461     * @param indicators the indicator direction, or the logical OR of multiple
5462     *             indicator directions. One or more of:
5463     *             <ul>
5464     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5465     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5466     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5467     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5468     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5469     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5470     *             </ul>
5471     * @see #setScrollIndicators(int)
5472     * @see #getScrollIndicators()
5473     * @attr ref android.R.styleable#View_scrollIndicators
5474     */
5475    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5476        // Shift and sanitize mask.
5477        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5478        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5479
5480        // Shift and mask indicators.
5481        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5482        indicators &= mask;
5483
5484        // Merge with non-masked flags.
5485        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5486
5487        if (mPrivateFlags3 != updatedFlags) {
5488            mPrivateFlags3 = updatedFlags;
5489
5490            if (indicators != 0) {
5491                initializeScrollIndicatorsInternal();
5492            }
5493            invalidate();
5494        }
5495    }
5496
5497    /**
5498     * Returns a bitmask representing the enabled scroll indicators.
5499     * <p>
5500     * For example, if the top and left scroll indicators are enabled and all
5501     * other indicators are disabled, the return value will be
5502     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5503     * <p>
5504     * To check whether the bottom scroll indicator is enabled, use the value
5505     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5506     *
5507     * @return a bitmask representing the enabled scroll indicators
5508     */
5509    @ScrollIndicators
5510    public int getScrollIndicators() {
5511        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5512                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5513    }
5514
5515    ListenerInfo getListenerInfo() {
5516        if (mListenerInfo != null) {
5517            return mListenerInfo;
5518        }
5519        mListenerInfo = new ListenerInfo();
5520        return mListenerInfo;
5521    }
5522
5523    /**
5524     * Register a callback to be invoked when the scroll X or Y positions of
5525     * this view change.
5526     * <p>
5527     * <b>Note:</b> Some views handle scrolling independently from View and may
5528     * have their own separate listeners for scroll-type events. For example,
5529     * {@link android.widget.ListView ListView} allows clients to register an
5530     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5531     * to listen for changes in list scroll position.
5532     *
5533     * @param l The listener to notify when the scroll X or Y position changes.
5534     * @see android.view.View#getScrollX()
5535     * @see android.view.View#getScrollY()
5536     */
5537    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5538        getListenerInfo().mOnScrollChangeListener = l;
5539    }
5540
5541    /**
5542     * Register a callback to be invoked when focus of this view changed.
5543     *
5544     * @param l The callback that will run.
5545     */
5546    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5547        getListenerInfo().mOnFocusChangeListener = l;
5548    }
5549
5550    /**
5551     * Add a listener that will be called when the bounds of the view change due to
5552     * layout processing.
5553     *
5554     * @param listener The listener that will be called when layout bounds change.
5555     */
5556    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5557        ListenerInfo li = getListenerInfo();
5558        if (li.mOnLayoutChangeListeners == null) {
5559            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5560        }
5561        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5562            li.mOnLayoutChangeListeners.add(listener);
5563        }
5564    }
5565
5566    /**
5567     * Remove a listener for layout changes.
5568     *
5569     * @param listener The listener for layout bounds change.
5570     */
5571    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5572        ListenerInfo li = mListenerInfo;
5573        if (li == null || li.mOnLayoutChangeListeners == null) {
5574            return;
5575        }
5576        li.mOnLayoutChangeListeners.remove(listener);
5577    }
5578
5579    /**
5580     * Add a listener for attach state changes.
5581     *
5582     * This listener will be called whenever this view is attached or detached
5583     * from a window. Remove the listener using
5584     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5585     *
5586     * @param listener Listener to attach
5587     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5588     */
5589    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5590        ListenerInfo li = getListenerInfo();
5591        if (li.mOnAttachStateChangeListeners == null) {
5592            li.mOnAttachStateChangeListeners
5593                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5594        }
5595        li.mOnAttachStateChangeListeners.add(listener);
5596    }
5597
5598    /**
5599     * Remove a listener for attach state changes. The listener will receive no further
5600     * notification of window attach/detach events.
5601     *
5602     * @param listener Listener to remove
5603     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5604     */
5605    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5606        ListenerInfo li = mListenerInfo;
5607        if (li == null || li.mOnAttachStateChangeListeners == null) {
5608            return;
5609        }
5610        li.mOnAttachStateChangeListeners.remove(listener);
5611    }
5612
5613    /**
5614     * Returns the focus-change callback registered for this view.
5615     *
5616     * @return The callback, or null if one is not registered.
5617     */
5618    public OnFocusChangeListener getOnFocusChangeListener() {
5619        ListenerInfo li = mListenerInfo;
5620        return li != null ? li.mOnFocusChangeListener : null;
5621    }
5622
5623    /**
5624     * Register a callback to be invoked when this view is clicked. If this view is not
5625     * clickable, it becomes clickable.
5626     *
5627     * @param l The callback that will run
5628     *
5629     * @see #setClickable(boolean)
5630     */
5631    public void setOnClickListener(@Nullable OnClickListener l) {
5632        if (!isClickable()) {
5633            setClickable(true);
5634        }
5635        getListenerInfo().mOnClickListener = l;
5636    }
5637
5638    /**
5639     * Return whether this view has an attached OnClickListener.  Returns
5640     * true if there is a listener, false if there is none.
5641     */
5642    public boolean hasOnClickListeners() {
5643        ListenerInfo li = mListenerInfo;
5644        return (li != null && li.mOnClickListener != null);
5645    }
5646
5647    /**
5648     * Register a callback to be invoked when this view is clicked and held. If this view is not
5649     * long clickable, it becomes long clickable.
5650     *
5651     * @param l The callback that will run
5652     *
5653     * @see #setLongClickable(boolean)
5654     */
5655    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5656        if (!isLongClickable()) {
5657            setLongClickable(true);
5658        }
5659        getListenerInfo().mOnLongClickListener = l;
5660    }
5661
5662    /**
5663     * Register a callback to be invoked when this view is context clicked. If the view is not
5664     * context clickable, it becomes context clickable.
5665     *
5666     * @param l The callback that will run
5667     * @see #setContextClickable(boolean)
5668     */
5669    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5670        if (!isContextClickable()) {
5671            setContextClickable(true);
5672        }
5673        getListenerInfo().mOnContextClickListener = l;
5674    }
5675
5676    /**
5677     * Register a callback to be invoked when the context menu for this view is
5678     * being built. If this view is not long clickable, it becomes long clickable.
5679     *
5680     * @param l The callback that will run
5681     *
5682     */
5683    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5684        if (!isLongClickable()) {
5685            setLongClickable(true);
5686        }
5687        getListenerInfo().mOnCreateContextMenuListener = l;
5688    }
5689
5690    /**
5691     * Set an observer to collect stats for each frame rendered for this view.
5692     *
5693     * @hide
5694     */
5695    public void addFrameMetricsListener(Window window,
5696            Window.OnFrameMetricsAvailableListener listener,
5697            Handler handler) {
5698        if (mAttachInfo != null) {
5699            if (mAttachInfo.mThreadedRenderer != null) {
5700                if (mFrameMetricsObservers == null) {
5701                    mFrameMetricsObservers = new ArrayList<>();
5702                }
5703
5704                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5705                        handler.getLooper(), listener);
5706                mFrameMetricsObservers.add(fmo);
5707                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
5708            } else {
5709                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5710            }
5711        } else {
5712            if (mFrameMetricsObservers == null) {
5713                mFrameMetricsObservers = new ArrayList<>();
5714            }
5715
5716            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5717                    handler.getLooper(), listener);
5718            mFrameMetricsObservers.add(fmo);
5719        }
5720    }
5721
5722    /**
5723     * Remove observer configured to collect frame stats for this view.
5724     *
5725     * @hide
5726     */
5727    public void removeFrameMetricsListener(
5728            Window.OnFrameMetricsAvailableListener listener) {
5729        ThreadedRenderer renderer = getThreadedRenderer();
5730        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
5731        if (fmo == null) {
5732            throw new IllegalArgumentException(
5733                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
5734        }
5735
5736        if (mFrameMetricsObservers != null) {
5737            mFrameMetricsObservers.remove(fmo);
5738            if (renderer != null) {
5739                renderer.removeFrameMetricsObserver(fmo);
5740            }
5741        }
5742    }
5743
5744    private void registerPendingFrameMetricsObservers() {
5745        if (mFrameMetricsObservers != null) {
5746            ThreadedRenderer renderer = getThreadedRenderer();
5747            if (renderer != null) {
5748                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
5749                    renderer.addFrameMetricsObserver(fmo);
5750                }
5751            } else {
5752                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5753            }
5754        }
5755    }
5756
5757    private FrameMetricsObserver findFrameMetricsObserver(
5758            Window.OnFrameMetricsAvailableListener listener) {
5759        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
5760            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
5761            if (observer.mListener == listener) {
5762                return observer;
5763            }
5764        }
5765
5766        return null;
5767    }
5768
5769    /**
5770     * Call this view's OnClickListener, if it is defined.  Performs all normal
5771     * actions associated with clicking: reporting accessibility event, playing
5772     * a sound, etc.
5773     *
5774     * @return True there was an assigned OnClickListener that was called, false
5775     *         otherwise is returned.
5776     */
5777    public boolean performClick() {
5778        final boolean result;
5779        final ListenerInfo li = mListenerInfo;
5780        if (li != null && li.mOnClickListener != null) {
5781            playSoundEffect(SoundEffectConstants.CLICK);
5782            li.mOnClickListener.onClick(this);
5783            result = true;
5784        } else {
5785            result = false;
5786        }
5787
5788        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5789        return result;
5790    }
5791
5792    /**
5793     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5794     * this only calls the listener, and does not do any associated clicking
5795     * actions like reporting an accessibility event.
5796     *
5797     * @return True there was an assigned OnClickListener that was called, false
5798     *         otherwise is returned.
5799     */
5800    public boolean callOnClick() {
5801        ListenerInfo li = mListenerInfo;
5802        if (li != null && li.mOnClickListener != null) {
5803            li.mOnClickListener.onClick(this);
5804            return true;
5805        }
5806        return false;
5807    }
5808
5809    /**
5810     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5811     * context menu if the OnLongClickListener did not consume the event.
5812     *
5813     * @return {@code true} if one of the above receivers consumed the event,
5814     *         {@code false} otherwise
5815     */
5816    public boolean performLongClick() {
5817        return performLongClickInternal(mLongClickX, mLongClickY);
5818    }
5819
5820    /**
5821     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5822     * context menu if the OnLongClickListener did not consume the event,
5823     * anchoring it to an (x,y) coordinate.
5824     *
5825     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5826     *          to disable anchoring
5827     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5828     *          to disable anchoring
5829     * @return {@code true} if one of the above receivers consumed the event,
5830     *         {@code false} otherwise
5831     */
5832    public boolean performLongClick(float x, float y) {
5833        mLongClickX = x;
5834        mLongClickY = y;
5835        final boolean handled = performLongClick();
5836        mLongClickX = Float.NaN;
5837        mLongClickY = Float.NaN;
5838        return handled;
5839    }
5840
5841    /**
5842     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5843     * context menu if the OnLongClickListener did not consume the event,
5844     * optionally anchoring it to an (x,y) coordinate.
5845     *
5846     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5847     *          to disable anchoring
5848     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5849     *          to disable anchoring
5850     * @return {@code true} if one of the above receivers consumed the event,
5851     *         {@code false} otherwise
5852     */
5853    private boolean performLongClickInternal(float x, float y) {
5854        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5855
5856        boolean handled = false;
5857        final ListenerInfo li = mListenerInfo;
5858        if (li != null && li.mOnLongClickListener != null) {
5859            handled = li.mOnLongClickListener.onLongClick(View.this);
5860        }
5861        if (!handled) {
5862            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5863            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5864        }
5865        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
5866            if (!handled) {
5867                handled = showLongClickTooltip((int) x, (int) y);
5868            }
5869        }
5870        if (handled) {
5871            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5872        }
5873        return handled;
5874    }
5875
5876    /**
5877     * Call this view's OnContextClickListener, if it is defined.
5878     *
5879     * @param x the x coordinate of the context click
5880     * @param y the y coordinate of the context click
5881     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5882     *         otherwise.
5883     */
5884    public boolean performContextClick(float x, float y) {
5885        return performContextClick();
5886    }
5887
5888    /**
5889     * Call this view's OnContextClickListener, if it is defined.
5890     *
5891     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5892     *         otherwise.
5893     */
5894    public boolean performContextClick() {
5895        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5896
5897        boolean handled = false;
5898        ListenerInfo li = mListenerInfo;
5899        if (li != null && li.mOnContextClickListener != null) {
5900            handled = li.mOnContextClickListener.onContextClick(View.this);
5901        }
5902        if (handled) {
5903            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5904        }
5905        return handled;
5906    }
5907
5908    /**
5909     * Performs button-related actions during a touch down event.
5910     *
5911     * @param event The event.
5912     * @return True if the down was consumed.
5913     *
5914     * @hide
5915     */
5916    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5917        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5918            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5919            showContextMenu(event.getX(), event.getY());
5920            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5921            return true;
5922        }
5923        return false;
5924    }
5925
5926    /**
5927     * Shows the context menu for this view.
5928     *
5929     * @return {@code true} if the context menu was shown, {@code false}
5930     *         otherwise
5931     * @see #showContextMenu(float, float)
5932     */
5933    public boolean showContextMenu() {
5934        return getParent().showContextMenuForChild(this);
5935    }
5936
5937    /**
5938     * Shows the context menu for this view anchored to the specified
5939     * view-relative coordinate.
5940     *
5941     * @param x the X coordinate in pixels relative to the view to which the
5942     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5943     * @param y the Y coordinate in pixels relative to the view to which the
5944     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5945     * @return {@code true} if the context menu was shown, {@code false}
5946     *         otherwise
5947     */
5948    public boolean showContextMenu(float x, float y) {
5949        return getParent().showContextMenuForChild(this, x, y);
5950    }
5951
5952    /**
5953     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5954     *
5955     * @param callback Callback that will control the lifecycle of the action mode
5956     * @return The new action mode if it is started, null otherwise
5957     *
5958     * @see ActionMode
5959     * @see #startActionMode(android.view.ActionMode.Callback, int)
5960     */
5961    public ActionMode startActionMode(ActionMode.Callback callback) {
5962        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5963    }
5964
5965    /**
5966     * Start an action mode with the given type.
5967     *
5968     * @param callback Callback that will control the lifecycle of the action mode
5969     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5970     * @return The new action mode if it is started, null otherwise
5971     *
5972     * @see ActionMode
5973     */
5974    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5975        ViewParent parent = getParent();
5976        if (parent == null) return null;
5977        try {
5978            return parent.startActionModeForChild(this, callback, type);
5979        } catch (AbstractMethodError ame) {
5980            // Older implementations of custom views might not implement this.
5981            return parent.startActionModeForChild(this, callback);
5982        }
5983    }
5984
5985    /**
5986     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5987     * Context, creating a unique View identifier to retrieve the result.
5988     *
5989     * @param intent The Intent to be started.
5990     * @param requestCode The request code to use.
5991     * @hide
5992     */
5993    public void startActivityForResult(Intent intent, int requestCode) {
5994        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5995        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5996    }
5997
5998    /**
5999     * If this View corresponds to the calling who, dispatches the activity result.
6000     * @param who The identifier for the targeted View to receive the result.
6001     * @param requestCode The integer request code originally supplied to
6002     *                    startActivityForResult(), allowing you to identify who this
6003     *                    result came from.
6004     * @param resultCode The integer result code returned by the child activity
6005     *                   through its setResult().
6006     * @param data An Intent, which can return result data to the caller
6007     *               (various data can be attached to Intent "extras").
6008     * @return {@code true} if the activity result was dispatched.
6009     * @hide
6010     */
6011    public boolean dispatchActivityResult(
6012            String who, int requestCode, int resultCode, Intent data) {
6013        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6014            onActivityResult(requestCode, resultCode, data);
6015            mStartActivityRequestWho = null;
6016            return true;
6017        }
6018        return false;
6019    }
6020
6021    /**
6022     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6023     *
6024     * @param requestCode The integer request code originally supplied to
6025     *                    startActivityForResult(), allowing you to identify who this
6026     *                    result came from.
6027     * @param resultCode The integer result code returned by the child activity
6028     *                   through its setResult().
6029     * @param data An Intent, which can return result data to the caller
6030     *               (various data can be attached to Intent "extras").
6031     * @hide
6032     */
6033    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6034        // Do nothing.
6035    }
6036
6037    /**
6038     * Register a callback to be invoked when a hardware key is pressed in this view.
6039     * Key presses in software input methods will generally not trigger the methods of
6040     * this listener.
6041     * @param l the key listener to attach to this view
6042     */
6043    public void setOnKeyListener(OnKeyListener l) {
6044        getListenerInfo().mOnKeyListener = l;
6045    }
6046
6047    /**
6048     * Register a callback to be invoked when a touch event is sent to this view.
6049     * @param l the touch listener to attach to this view
6050     */
6051    public void setOnTouchListener(OnTouchListener l) {
6052        getListenerInfo().mOnTouchListener = l;
6053    }
6054
6055    /**
6056     * Register a callback to be invoked when a generic motion event is sent to this view.
6057     * @param l the generic motion listener to attach to this view
6058     */
6059    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6060        getListenerInfo().mOnGenericMotionListener = l;
6061    }
6062
6063    /**
6064     * Register a callback to be invoked when a hover event is sent to this view.
6065     * @param l the hover listener to attach to this view
6066     */
6067    public void setOnHoverListener(OnHoverListener l) {
6068        getListenerInfo().mOnHoverListener = l;
6069    }
6070
6071    /**
6072     * Register a drag event listener callback object for this View. The parameter is
6073     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6074     * View, the system calls the
6075     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6076     * @param l An implementation of {@link android.view.View.OnDragListener}.
6077     */
6078    public void setOnDragListener(OnDragListener l) {
6079        getListenerInfo().mOnDragListener = l;
6080    }
6081
6082    /**
6083     * Give this view focus. This will cause
6084     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6085     *
6086     * Note: this does not check whether this {@link View} should get focus, it just
6087     * gives it focus no matter what.  It should only be called internally by framework
6088     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6089     *
6090     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6091     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6092     *        focus moved when requestFocus() is called. It may not always
6093     *        apply, in which case use the default View.FOCUS_DOWN.
6094     * @param previouslyFocusedRect The rectangle of the view that had focus
6095     *        prior in this View's coordinate system.
6096     */
6097    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6098        if (DBG) {
6099            System.out.println(this + " requestFocus()");
6100        }
6101
6102        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6103            mPrivateFlags |= PFLAG_FOCUSED;
6104
6105            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6106
6107            if (mParent != null) {
6108                mParent.requestChildFocus(this, this);
6109            }
6110
6111            if (mAttachInfo != null) {
6112                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6113            }
6114
6115            onFocusChanged(true, direction, previouslyFocusedRect);
6116            refreshDrawableState();
6117        }
6118    }
6119
6120    /**
6121     * Sets this view's preference for reveal behavior when it gains focus.
6122     *
6123     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6124     * this view would prefer to be brought fully into view when it gains focus.
6125     * For example, a text field that a user is meant to type into. Other views such
6126     * as scrolling containers may prefer to opt-out of this behavior.</p>
6127     *
6128     * <p>The default value for views is true, though subclasses may change this
6129     * based on their preferred behavior.</p>
6130     *
6131     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6132     *
6133     * @see #getRevealOnFocusHint()
6134     */
6135    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6136        if (revealOnFocus) {
6137            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6138        } else {
6139            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6140        }
6141    }
6142
6143    /**
6144     * Returns this view's preference for reveal behavior when it gains focus.
6145     *
6146     * <p>When this method returns true for a child view requesting focus, ancestor
6147     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6148     * should make a best effort to make the newly focused child fully visible to the user.
6149     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6150     * other properties affecting visibility to the user as part of the focus change.</p>
6151     *
6152     * @return true if this view would prefer to become fully visible when it gains focus,
6153     *         false if it would prefer not to disrupt scroll positioning
6154     *
6155     * @see #setRevealOnFocusHint(boolean)
6156     */
6157    public final boolean getRevealOnFocusHint() {
6158        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6159    }
6160
6161    /**
6162     * Populates <code>outRect</code> with the hotspot bounds. By default,
6163     * the hotspot bounds are identical to the screen bounds.
6164     *
6165     * @param outRect rect to populate with hotspot bounds
6166     * @hide Only for internal use by views and widgets.
6167     */
6168    public void getHotspotBounds(Rect outRect) {
6169        final Drawable background = getBackground();
6170        if (background != null) {
6171            background.getHotspotBounds(outRect);
6172        } else {
6173            getBoundsOnScreen(outRect);
6174        }
6175    }
6176
6177    /**
6178     * Request that a rectangle of this view be visible on the screen,
6179     * scrolling if necessary just enough.
6180     *
6181     * <p>A View should call this if it maintains some notion of which part
6182     * of its content is interesting.  For example, a text editing view
6183     * should call this when its cursor moves.
6184     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6185     * It should not be affected by which part of the View is currently visible or its scroll
6186     * position.
6187     *
6188     * @param rectangle The rectangle in the View's content coordinate space
6189     * @return Whether any parent scrolled.
6190     */
6191    public boolean requestRectangleOnScreen(Rect rectangle) {
6192        return requestRectangleOnScreen(rectangle, false);
6193    }
6194
6195    /**
6196     * Request that a rectangle of this view be visible on the screen,
6197     * scrolling if necessary just enough.
6198     *
6199     * <p>A View should call this if it maintains some notion of which part
6200     * of its content is interesting.  For example, a text editing view
6201     * should call this when its cursor moves.
6202     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6203     * It should not be affected by which part of the View is currently visible or its scroll
6204     * position.
6205     * <p>When <code>immediate</code> is set to true, scrolling will not be
6206     * animated.
6207     *
6208     * @param rectangle The rectangle in the View's content coordinate space
6209     * @param immediate True to forbid animated scrolling, false otherwise
6210     * @return Whether any parent scrolled.
6211     */
6212    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6213        if (mParent == null) {
6214            return false;
6215        }
6216
6217        View child = this;
6218
6219        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6220        position.set(rectangle);
6221
6222        ViewParent parent = mParent;
6223        boolean scrolled = false;
6224        while (parent != null) {
6225            rectangle.set((int) position.left, (int) position.top,
6226                    (int) position.right, (int) position.bottom);
6227
6228            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6229
6230            if (!(parent instanceof View)) {
6231                break;
6232            }
6233
6234            // move it from child's content coordinate space to parent's content coordinate space
6235            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6236
6237            child = (View) parent;
6238            parent = child.getParent();
6239        }
6240
6241        return scrolled;
6242    }
6243
6244    /**
6245     * Called when this view wants to give up focus. If focus is cleared
6246     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6247     * <p>
6248     * <strong>Note:</strong> When a View clears focus the framework is trying
6249     * to give focus to the first focusable View from the top. Hence, if this
6250     * View is the first from the top that can take focus, then all callbacks
6251     * related to clearing focus will be invoked after which the framework will
6252     * give focus to this view.
6253     * </p>
6254     */
6255    public void clearFocus() {
6256        if (DBG) {
6257            System.out.println(this + " clearFocus()");
6258        }
6259
6260        clearFocusInternal(null, true, true);
6261    }
6262
6263    /**
6264     * Clears focus from the view, optionally propagating the change up through
6265     * the parent hierarchy and requesting that the root view place new focus.
6266     *
6267     * @param propagate whether to propagate the change up through the parent
6268     *            hierarchy
6269     * @param refocus when propagate is true, specifies whether to request the
6270     *            root view place new focus
6271     */
6272    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6273        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6274            mPrivateFlags &= ~PFLAG_FOCUSED;
6275
6276            if (propagate && mParent != null) {
6277                mParent.clearChildFocus(this);
6278            }
6279
6280            onFocusChanged(false, 0, null);
6281            refreshDrawableState();
6282
6283            if (propagate && (!refocus || !rootViewRequestFocus())) {
6284                notifyGlobalFocusCleared(this);
6285            }
6286        }
6287    }
6288
6289    void notifyGlobalFocusCleared(View oldFocus) {
6290        if (oldFocus != null && mAttachInfo != null) {
6291            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6292        }
6293    }
6294
6295    boolean rootViewRequestFocus() {
6296        final View root = getRootView();
6297        return root != null && root.requestFocus();
6298    }
6299
6300    /**
6301     * Called internally by the view system when a new view is getting focus.
6302     * This is what clears the old focus.
6303     * <p>
6304     * <b>NOTE:</b> The parent view's focused child must be updated manually
6305     * after calling this method. Otherwise, the view hierarchy may be left in
6306     * an inconstent state.
6307     */
6308    void unFocus(View focused) {
6309        if (DBG) {
6310            System.out.println(this + " unFocus()");
6311        }
6312
6313        clearFocusInternal(focused, false, false);
6314    }
6315
6316    /**
6317     * Returns true if this view has focus itself, or is the ancestor of the
6318     * view that has focus.
6319     *
6320     * @return True if this view has or contains focus, false otherwise.
6321     */
6322    @ViewDebug.ExportedProperty(category = "focus")
6323    public boolean hasFocus() {
6324        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6325    }
6326
6327    /**
6328     * Returns true if this view is focusable or if it contains a reachable View
6329     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
6330     * is a View whose parents do not block descendants focus.
6331     *
6332     * Only {@link #VISIBLE} views are considered focusable.
6333     *
6334     * @return True if the view is focusable or if the view contains a focusable
6335     *         View, false otherwise.
6336     *
6337     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6338     * @see ViewGroup#getTouchscreenBlocksFocus()
6339     */
6340    public boolean hasFocusable() {
6341        if (!isFocusableInTouchMode()) {
6342            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6343                final ViewGroup g = (ViewGroup) p;
6344                if (g.shouldBlockFocusForTouchscreen()) {
6345                    return false;
6346                }
6347            }
6348        }
6349        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
6350    }
6351
6352    /**
6353     * Called by the view system when the focus state of this view changes.
6354     * When the focus change event is caused by directional navigation, direction
6355     * and previouslyFocusedRect provide insight into where the focus is coming from.
6356     * When overriding, be sure to call up through to the super class so that
6357     * the standard focus handling will occur.
6358     *
6359     * @param gainFocus True if the View has focus; false otherwise.
6360     * @param direction The direction focus has moved when requestFocus()
6361     *                  is called to give this view focus. Values are
6362     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6363     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6364     *                  It may not always apply, in which case use the default.
6365     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6366     *        system, of the previously focused view.  If applicable, this will be
6367     *        passed in as finer grained information about where the focus is coming
6368     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6369     */
6370    @CallSuper
6371    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6372            @Nullable Rect previouslyFocusedRect) {
6373        if (gainFocus) {
6374            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6375        } else {
6376            notifyViewAccessibilityStateChangedIfNeeded(
6377                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6378        }
6379
6380        InputMethodManager imm = InputMethodManager.peekInstance();
6381        if (!gainFocus) {
6382            if (isPressed()) {
6383                setPressed(false);
6384            }
6385            if (imm != null && mAttachInfo != null
6386                    && mAttachInfo.mHasWindowFocus) {
6387                imm.focusOut(this);
6388            }
6389            onFocusLost();
6390        } else if (imm != null && mAttachInfo != null
6391                && mAttachInfo.mHasWindowFocus) {
6392            imm.focusIn(this);
6393        }
6394
6395        invalidate(true);
6396        ListenerInfo li = mListenerInfo;
6397        if (li != null && li.mOnFocusChangeListener != null) {
6398            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6399        }
6400
6401        if (mAttachInfo != null) {
6402            mAttachInfo.mKeyDispatchState.reset(this);
6403        }
6404    }
6405
6406    /**
6407     * Sends an accessibility event of the given type. If accessibility is
6408     * not enabled this method has no effect. The default implementation calls
6409     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6410     * to populate information about the event source (this View), then calls
6411     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6412     * populate the text content of the event source including its descendants,
6413     * and last calls
6414     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6415     * on its parent to request sending of the event to interested parties.
6416     * <p>
6417     * If an {@link AccessibilityDelegate} has been specified via calling
6418     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6419     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6420     * responsible for handling this call.
6421     * </p>
6422     *
6423     * @param eventType The type of the event to send, as defined by several types from
6424     * {@link android.view.accessibility.AccessibilityEvent}, such as
6425     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6426     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6427     *
6428     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6429     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6430     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6431     * @see AccessibilityDelegate
6432     */
6433    public void sendAccessibilityEvent(int eventType) {
6434        if (mAccessibilityDelegate != null) {
6435            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6436        } else {
6437            sendAccessibilityEventInternal(eventType);
6438        }
6439    }
6440
6441    /**
6442     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6443     * {@link AccessibilityEvent} to make an announcement which is related to some
6444     * sort of a context change for which none of the events representing UI transitions
6445     * is a good fit. For example, announcing a new page in a book. If accessibility
6446     * is not enabled this method does nothing.
6447     *
6448     * @param text The announcement text.
6449     */
6450    public void announceForAccessibility(CharSequence text) {
6451        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6452            AccessibilityEvent event = AccessibilityEvent.obtain(
6453                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6454            onInitializeAccessibilityEvent(event);
6455            event.getText().add(text);
6456            event.setContentDescription(null);
6457            mParent.requestSendAccessibilityEvent(this, event);
6458        }
6459    }
6460
6461    /**
6462     * @see #sendAccessibilityEvent(int)
6463     *
6464     * Note: Called from the default {@link AccessibilityDelegate}.
6465     *
6466     * @hide
6467     */
6468    public void sendAccessibilityEventInternal(int eventType) {
6469        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6470            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6471        }
6472    }
6473
6474    /**
6475     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6476     * takes as an argument an empty {@link AccessibilityEvent} and does not
6477     * perform a check whether accessibility is enabled.
6478     * <p>
6479     * If an {@link AccessibilityDelegate} has been specified via calling
6480     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6481     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6482     * is responsible for handling this call.
6483     * </p>
6484     *
6485     * @param event The event to send.
6486     *
6487     * @see #sendAccessibilityEvent(int)
6488     */
6489    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6490        if (mAccessibilityDelegate != null) {
6491            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6492        } else {
6493            sendAccessibilityEventUncheckedInternal(event);
6494        }
6495    }
6496
6497    /**
6498     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6499     *
6500     * Note: Called from the default {@link AccessibilityDelegate}.
6501     *
6502     * @hide
6503     */
6504    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6505        if (!isShown()) {
6506            return;
6507        }
6508        onInitializeAccessibilityEvent(event);
6509        // Only a subset of accessibility events populates text content.
6510        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6511            dispatchPopulateAccessibilityEvent(event);
6512        }
6513        // In the beginning we called #isShown(), so we know that getParent() is not null.
6514        getParent().requestSendAccessibilityEvent(this, event);
6515    }
6516
6517    /**
6518     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6519     * to its children for adding their text content to the event. Note that the
6520     * event text is populated in a separate dispatch path since we add to the
6521     * event not only the text of the source but also the text of all its descendants.
6522     * A typical implementation will call
6523     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6524     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6525     * on each child. Override this method if custom population of the event text
6526     * content is required.
6527     * <p>
6528     * If an {@link AccessibilityDelegate} has been specified via calling
6529     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6530     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6531     * is responsible for handling this call.
6532     * </p>
6533     * <p>
6534     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6535     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6536     * </p>
6537     *
6538     * @param event The event.
6539     *
6540     * @return True if the event population was completed.
6541     */
6542    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6543        if (mAccessibilityDelegate != null) {
6544            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6545        } else {
6546            return dispatchPopulateAccessibilityEventInternal(event);
6547        }
6548    }
6549
6550    /**
6551     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6552     *
6553     * Note: Called from the default {@link AccessibilityDelegate}.
6554     *
6555     * @hide
6556     */
6557    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6558        onPopulateAccessibilityEvent(event);
6559        return false;
6560    }
6561
6562    /**
6563     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6564     * giving a chance to this View to populate the accessibility event with its
6565     * text content. While this method is free to modify event
6566     * attributes other than text content, doing so should normally be performed in
6567     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6568     * <p>
6569     * Example: Adding formatted date string to an accessibility event in addition
6570     *          to the text added by the super implementation:
6571     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6572     *     super.onPopulateAccessibilityEvent(event);
6573     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6574     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6575     *         mCurrentDate.getTimeInMillis(), flags);
6576     *     event.getText().add(selectedDateUtterance);
6577     * }</pre>
6578     * <p>
6579     * If an {@link AccessibilityDelegate} has been specified via calling
6580     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6581     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6582     * is responsible for handling this call.
6583     * </p>
6584     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6585     * information to the event, in case the default implementation has basic information to add.
6586     * </p>
6587     *
6588     * @param event The accessibility event which to populate.
6589     *
6590     * @see #sendAccessibilityEvent(int)
6591     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6592     */
6593    @CallSuper
6594    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6595        if (mAccessibilityDelegate != null) {
6596            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6597        } else {
6598            onPopulateAccessibilityEventInternal(event);
6599        }
6600    }
6601
6602    /**
6603     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6604     *
6605     * Note: Called from the default {@link AccessibilityDelegate}.
6606     *
6607     * @hide
6608     */
6609    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6610    }
6611
6612    /**
6613     * Initializes an {@link AccessibilityEvent} with information about
6614     * this View which is the event source. In other words, the source of
6615     * an accessibility event is the view whose state change triggered firing
6616     * the event.
6617     * <p>
6618     * Example: Setting the password property of an event in addition
6619     *          to properties set by the super implementation:
6620     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6621     *     super.onInitializeAccessibilityEvent(event);
6622     *     event.setPassword(true);
6623     * }</pre>
6624     * <p>
6625     * If an {@link AccessibilityDelegate} has been specified via calling
6626     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6627     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6628     * is responsible for handling this call.
6629     * </p>
6630     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6631     * information to the event, in case the default implementation has basic information to add.
6632     * </p>
6633     * @param event The event to initialize.
6634     *
6635     * @see #sendAccessibilityEvent(int)
6636     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6637     */
6638    @CallSuper
6639    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6640        if (mAccessibilityDelegate != null) {
6641            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6642        } else {
6643            onInitializeAccessibilityEventInternal(event);
6644        }
6645    }
6646
6647    /**
6648     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6649     *
6650     * Note: Called from the default {@link AccessibilityDelegate}.
6651     *
6652     * @hide
6653     */
6654    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6655        event.setSource(this);
6656        event.setClassName(getAccessibilityClassName());
6657        event.setPackageName(getContext().getPackageName());
6658        event.setEnabled(isEnabled());
6659        event.setContentDescription(mContentDescription);
6660
6661        switch (event.getEventType()) {
6662            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6663                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6664                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6665                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6666                event.setItemCount(focusablesTempList.size());
6667                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6668                if (mAttachInfo != null) {
6669                    focusablesTempList.clear();
6670                }
6671            } break;
6672            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6673                CharSequence text = getIterableTextForAccessibility();
6674                if (text != null && text.length() > 0) {
6675                    event.setFromIndex(getAccessibilitySelectionStart());
6676                    event.setToIndex(getAccessibilitySelectionEnd());
6677                    event.setItemCount(text.length());
6678                }
6679            } break;
6680        }
6681    }
6682
6683    /**
6684     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6685     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6686     * This method is responsible for obtaining an accessibility node info from a
6687     * pool of reusable instances and calling
6688     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6689     * initialize the former.
6690     * <p>
6691     * Note: The client is responsible for recycling the obtained instance by calling
6692     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6693     * </p>
6694     *
6695     * @return A populated {@link AccessibilityNodeInfo}.
6696     *
6697     * @see AccessibilityNodeInfo
6698     */
6699    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6700        if (mAccessibilityDelegate != null) {
6701            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6702        } else {
6703            return createAccessibilityNodeInfoInternal();
6704        }
6705    }
6706
6707    /**
6708     * @see #createAccessibilityNodeInfo()
6709     *
6710     * @hide
6711     */
6712    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6713        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6714        if (provider != null) {
6715            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6716        } else {
6717            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6718            onInitializeAccessibilityNodeInfo(info);
6719            return info;
6720        }
6721    }
6722
6723    /**
6724     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6725     * The base implementation sets:
6726     * <ul>
6727     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6728     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6729     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6730     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6731     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6732     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6733     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6734     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6735     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6736     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6737     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6738     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6739     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6740     * </ul>
6741     * <p>
6742     * Subclasses should override this method, call the super implementation,
6743     * and set additional attributes.
6744     * </p>
6745     * <p>
6746     * If an {@link AccessibilityDelegate} has been specified via calling
6747     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6748     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6749     * is responsible for handling this call.
6750     * </p>
6751     *
6752     * @param info The instance to initialize.
6753     */
6754    @CallSuper
6755    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6756        if (mAccessibilityDelegate != null) {
6757            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6758        } else {
6759            onInitializeAccessibilityNodeInfoInternal(info);
6760        }
6761    }
6762
6763    /**
6764     * Gets the location of this view in screen coordinates.
6765     *
6766     * @param outRect The output location
6767     * @hide
6768     */
6769    public void getBoundsOnScreen(Rect outRect) {
6770        getBoundsOnScreen(outRect, false);
6771    }
6772
6773    /**
6774     * Gets the location of this view in screen coordinates.
6775     *
6776     * @param outRect The output location
6777     * @param clipToParent Whether to clip child bounds to the parent ones.
6778     * @hide
6779     */
6780    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6781        if (mAttachInfo == null) {
6782            return;
6783        }
6784
6785        RectF position = mAttachInfo.mTmpTransformRect;
6786        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6787
6788        if (!hasIdentityMatrix()) {
6789            getMatrix().mapRect(position);
6790        }
6791
6792        position.offset(mLeft, mTop);
6793
6794        ViewParent parent = mParent;
6795        while (parent instanceof View) {
6796            View parentView = (View) parent;
6797
6798            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6799
6800            if (clipToParent) {
6801                position.left = Math.max(position.left, 0);
6802                position.top = Math.max(position.top, 0);
6803                position.right = Math.min(position.right, parentView.getWidth());
6804                position.bottom = Math.min(position.bottom, parentView.getHeight());
6805            }
6806
6807            if (!parentView.hasIdentityMatrix()) {
6808                parentView.getMatrix().mapRect(position);
6809            }
6810
6811            position.offset(parentView.mLeft, parentView.mTop);
6812
6813            parent = parentView.mParent;
6814        }
6815
6816        if (parent instanceof ViewRootImpl) {
6817            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6818            position.offset(0, -viewRootImpl.mCurScrollY);
6819        }
6820
6821        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6822
6823        outRect.set(Math.round(position.left), Math.round(position.top),
6824                Math.round(position.right), Math.round(position.bottom));
6825    }
6826
6827    /**
6828     * Return the class name of this object to be used for accessibility purposes.
6829     * Subclasses should only override this if they are implementing something that
6830     * should be seen as a completely new class of view when used by accessibility,
6831     * unrelated to the class it is deriving from.  This is used to fill in
6832     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6833     */
6834    public CharSequence getAccessibilityClassName() {
6835        return View.class.getName();
6836    }
6837
6838    /**
6839     * Called when assist structure is being retrieved from a view as part of
6840     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6841     * @param structure Fill in with structured view data.  The default implementation
6842     * fills in all data that can be inferred from the view itself.
6843     *
6844     * @deprecated As of API O sub-classes should override
6845     * {@link #onProvideStructure(ViewStructure, int)} instead.
6846     */
6847    // TODO(b/33197203): set proper API above
6848    @Deprecated
6849    public void onProvideStructure(ViewStructure structure) {
6850        onProvideStructure(structure, 0);
6851    }
6852
6853    /**
6854     * Called when assist structure is being retrieved from a view as part of
6855     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} or as part
6856     * of an auto-fill request.
6857     *
6858     * <p>The default implementation fills in all data that can be inferred from the view itself.
6859     *
6860     * <p>The structure must be filled according to the request type, which is set in the
6861     * {@code flags} parameter - see the documentation on each flag for more details.
6862     *
6863     * @param structure Fill in with structured view data. The default implementation
6864     * fills in all data that can be inferred from the view itself.
6865     * @param flags optional flags (see {@link #ASSIST_FLAG_SANITIZED_TEXT} and
6866     * {@link #ASSIST_FLAG_NON_SANITIZED_TEXT} for more info).
6867     */
6868    public void onProvideStructure(ViewStructure structure, int flags) {
6869        boolean forAutoFill = (flags
6870                & (View.ASSIST_FLAG_SANITIZED_TEXT
6871                        | View.ASSIST_FLAG_NON_SANITIZED_TEXT)) != 0;
6872        final int id = mID;
6873        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6874                && (id&0x0000ffff) != 0) {
6875            String pkg, type, entry;
6876            try {
6877                final Resources res = getResources();
6878                entry = res.getResourceEntryName(id);
6879                type = res.getResourceTypeName(id);
6880                pkg = res.getResourcePackageName(id);
6881            } catch (Resources.NotFoundException e) {
6882                entry = type = pkg = null;
6883            }
6884            structure.setId(id, pkg, type, entry);
6885        } else {
6886            structure.setId(id, null, null, null);
6887        }
6888
6889        if (forAutoFill) {
6890            // The auto-fill id needs to be unique, but its value doesn't matter, so it's better to
6891            // reuse the accessibility id to save space.
6892            structure.setAutoFillId(getAccessibilityViewId());
6893        }
6894
6895        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6896        if (!hasIdentityMatrix()) {
6897            structure.setTransformation(getMatrix());
6898        }
6899        structure.setElevation(getZ());
6900        structure.setVisibility(getVisibility());
6901        structure.setEnabled(isEnabled());
6902        if (isClickable()) {
6903            structure.setClickable(true);
6904        }
6905        if (isFocusable()) {
6906            structure.setFocusable(true);
6907        }
6908        if (isFocused()) {
6909            structure.setFocused(true);
6910        }
6911        if (isAccessibilityFocused()) {
6912            structure.setAccessibilityFocused(true);
6913        }
6914        if (isSelected()) {
6915            structure.setSelected(true);
6916        }
6917        if (isActivated()) {
6918            structure.setActivated(true);
6919        }
6920        if (isLongClickable()) {
6921            structure.setLongClickable(true);
6922        }
6923        if (this instanceof Checkable) {
6924            structure.setCheckable(true);
6925            if (((Checkable)this).isChecked()) {
6926                structure.setChecked(true);
6927            }
6928        }
6929        if (isContextClickable()) {
6930            structure.setContextClickable(true);
6931        }
6932        structure.setClassName(getAccessibilityClassName().toString());
6933        structure.setContentDescription(getContentDescription());
6934    }
6935
6936    /**
6937     * Called when assist structure is being retrieved from a view as part of
6938     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6939     * generate additional virtual structure under this view.  The defaullt implementation
6940     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6941     * view's virtual accessibility nodes, if any.  You can override this for a more
6942     * optimal implementation providing this data.
6943     *
6944     * @deprecated As of API O, sub-classes should override
6945     * {@link #onProvideVirtualStructure(ViewStructure, int)} instead.
6946     */
6947    // TODO(b/33197203): set proper API above
6948    @Deprecated
6949    public void onProvideVirtualStructure(ViewStructure structure) {
6950        onProvideVirtualStructure(structure, 0);
6951    }
6952
6953    /**
6954     * Called when assist structure is being retrieved from a view as part of
6955     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} or as part
6956     * of an auto-fill request to generate additional virtual structure under this view.
6957     *
6958     * <p>The defaullt implementation uses {@link #getAccessibilityNodeProvider()} to try to
6959     * generate this from the view's virtual accessibility nodes, if any.  You can override this
6960     * for a more optimal implementation providing this data.
6961     *
6962     * <p>The structure must be filled according to the request type, which is set in the
6963     * {@code flags} parameter - see the documentation on each flag for more details.
6964     *
6965     * @param structure Fill in with structured view data.
6966     * @param flags optional flags (see {@link #ASSIST_FLAG_SANITIZED_TEXT} and
6967     * {@link #ASSIST_FLAG_NON_SANITIZED_TEXT} for more info).
6968     */
6969    public void onProvideVirtualStructure(ViewStructure structure, int flags) {
6970        boolean sanitize = (flags & View.ASSIST_FLAG_SANITIZED_TEXT) != 0;
6971
6972        if (sanitize) {
6973            // TODO(b/33197203): change populateVirtualStructure so it sanitizes data in this case.
6974            return;
6975        }
6976
6977        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6978        if (provider != null) {
6979            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6980            structure.setChildCount(1);
6981            ViewStructure root = structure.newChild(0);
6982            populateVirtualStructure(root, provider, info, flags);
6983            info.recycle();
6984        }
6985    }
6986
6987    private void populateVirtualStructure(ViewStructure structure,
6988            AccessibilityNodeProvider provider, AccessibilityNodeInfo info, int flags) {
6989        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6990                null, null, null);
6991        Rect rect = structure.getTempRect();
6992        info.getBoundsInParent(rect);
6993        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6994        structure.setVisibility(VISIBLE);
6995        structure.setEnabled(info.isEnabled());
6996        if (info.isClickable()) {
6997            structure.setClickable(true);
6998        }
6999        if (info.isFocusable()) {
7000            structure.setFocusable(true);
7001        }
7002        if (info.isFocused()) {
7003            structure.setFocused(true);
7004        }
7005        if (info.isAccessibilityFocused()) {
7006            structure.setAccessibilityFocused(true);
7007        }
7008        if (info.isSelected()) {
7009            structure.setSelected(true);
7010        }
7011        if (info.isLongClickable()) {
7012            structure.setLongClickable(true);
7013        }
7014        if (info.isCheckable()) {
7015            structure.setCheckable(true);
7016            if (info.isChecked()) {
7017                structure.setChecked(true);
7018            }
7019        }
7020        if (info.isContextClickable()) {
7021            structure.setContextClickable(true);
7022        }
7023        CharSequence cname = info.getClassName();
7024        structure.setClassName(cname != null ? cname.toString() : null);
7025        structure.setContentDescription(info.getContentDescription());
7026        if (info.getText() != null || info.getError() != null) {
7027            structure.setText(info.getText(), info.getTextSelectionStart(),
7028                    info.getTextSelectionEnd());
7029        }
7030        final int NCHILDREN = info.getChildCount();
7031        if (NCHILDREN > 0) {
7032            structure.setChildCount(NCHILDREN);
7033            for (int i=0; i<NCHILDREN; i++) {
7034                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
7035                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
7036                ViewStructure child = structure.newChild(i);
7037                populateVirtualStructure(child, provider, cinfo, flags);
7038                cinfo.recycle();
7039            }
7040        }
7041    }
7042
7043    /**
7044     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
7045     * implementation calls {@link #onProvideStructure} and
7046     * {@link #onProvideVirtualStructure}.
7047     *
7048     * @deprecated As of API O,  sub-classes should override
7049     * {@link #dispatchProvideStructure(ViewStructure, int)} instead.
7050     */
7051    // TODO(b/33197203): set proper API above
7052    @Deprecated
7053    public void dispatchProvideStructure(ViewStructure structure) {
7054        dispatchProvideStructure(structure, 0);
7055    }
7056
7057    /**
7058     * Dispatch creation of {@link ViewStructure} down the hierarchy.
7059     *
7060     * <p>The structure must be filled according to the request type, which is set in the
7061     * {@code flags} parameter - see the documentation on each flag for more details.
7062     *
7063     * <p>The default implementation calls {@link #onProvideStructure(ViewStructure, int)} and
7064     * {@link #onProvideVirtualStructure(ViewStructure, int)}.
7065     *
7066     * @param structure Fill in with structured view data.
7067     * @param flags optional flags (see {@link #ASSIST_FLAG_SANITIZED_TEXT} and
7068     * {@link #ASSIST_FLAG_NON_SANITIZED_TEXT} for more info).
7069     */
7070    public void dispatchProvideStructure(ViewStructure structure, int flags) {
7071        boolean forAutoFill = (flags
7072                & (View.ASSIST_FLAG_SANITIZED_TEXT
7073                        | View.ASSIST_FLAG_NON_SANITIZED_TEXT)) != 0;
7074
7075        boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
7076        if (!blocked) {
7077            onProvideStructure(structure, flags);
7078            onProvideVirtualStructure(structure, flags);
7079        } else {
7080            structure.setClassName(getAccessibilityClassName().toString());
7081            structure.setAssistBlocked(true);
7082        }
7083    }
7084
7085    /**
7086     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
7087     *
7088     * Note: Called from the default {@link AccessibilityDelegate}.
7089     *
7090     * @hide
7091     */
7092    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
7093        if (mAttachInfo == null) {
7094            return;
7095        }
7096
7097        Rect bounds = mAttachInfo.mTmpInvalRect;
7098
7099        getDrawingRect(bounds);
7100        info.setBoundsInParent(bounds);
7101
7102        getBoundsOnScreen(bounds, true);
7103        info.setBoundsInScreen(bounds);
7104
7105        ViewParent parent = getParentForAccessibility();
7106        if (parent instanceof View) {
7107            info.setParent((View) parent);
7108        }
7109
7110        if (mID != View.NO_ID) {
7111            View rootView = getRootView();
7112            if (rootView == null) {
7113                rootView = this;
7114            }
7115
7116            View label = rootView.findLabelForView(this, mID);
7117            if (label != null) {
7118                info.setLabeledBy(label);
7119            }
7120
7121            if ((mAttachInfo.mAccessibilityFetchFlags
7122                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
7123                    && Resources.resourceHasPackage(mID)) {
7124                try {
7125                    String viewId = getResources().getResourceName(mID);
7126                    info.setViewIdResourceName(viewId);
7127                } catch (Resources.NotFoundException nfe) {
7128                    /* ignore */
7129                }
7130            }
7131        }
7132
7133        if (mLabelForId != View.NO_ID) {
7134            View rootView = getRootView();
7135            if (rootView == null) {
7136                rootView = this;
7137            }
7138            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
7139            if (labeled != null) {
7140                info.setLabelFor(labeled);
7141            }
7142        }
7143
7144        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
7145            View rootView = getRootView();
7146            if (rootView == null) {
7147                rootView = this;
7148            }
7149            View next = rootView.findViewInsideOutShouldExist(this,
7150                    mAccessibilityTraversalBeforeId);
7151            if (next != null && next.includeForAccessibility()) {
7152                info.setTraversalBefore(next);
7153            }
7154        }
7155
7156        if (mAccessibilityTraversalAfterId != View.NO_ID) {
7157            View rootView = getRootView();
7158            if (rootView == null) {
7159                rootView = this;
7160            }
7161            View next = rootView.findViewInsideOutShouldExist(this,
7162                    mAccessibilityTraversalAfterId);
7163            if (next != null && next.includeForAccessibility()) {
7164                info.setTraversalAfter(next);
7165            }
7166        }
7167
7168        info.setVisibleToUser(isVisibleToUser());
7169
7170        info.setImportantForAccessibility(isImportantForAccessibility());
7171        info.setPackageName(mContext.getPackageName());
7172        info.setClassName(getAccessibilityClassName());
7173        info.setContentDescription(getContentDescription());
7174
7175        info.setEnabled(isEnabled());
7176        info.setClickable(isClickable());
7177        info.setFocusable(isFocusable());
7178        info.setFocused(isFocused());
7179        info.setAccessibilityFocused(isAccessibilityFocused());
7180        info.setSelected(isSelected());
7181        info.setLongClickable(isLongClickable());
7182        info.setContextClickable(isContextClickable());
7183        info.setLiveRegion(getAccessibilityLiveRegion());
7184
7185        // TODO: These make sense only if we are in an AdapterView but all
7186        // views can be selected. Maybe from accessibility perspective
7187        // we should report as selectable view in an AdapterView.
7188        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
7189        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
7190
7191        if (isFocusable()) {
7192            if (isFocused()) {
7193                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
7194            } else {
7195                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
7196            }
7197        }
7198
7199        if (!isAccessibilityFocused()) {
7200            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
7201        } else {
7202            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
7203        }
7204
7205        if (isClickable() && isEnabled()) {
7206            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
7207        }
7208
7209        if (isLongClickable() && isEnabled()) {
7210            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
7211        }
7212
7213        if (isContextClickable() && isEnabled()) {
7214            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
7215        }
7216
7217        CharSequence text = getIterableTextForAccessibility();
7218        if (text != null && text.length() > 0) {
7219            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
7220
7221            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
7222            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
7223            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
7224            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
7225                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
7226                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
7227        }
7228
7229        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
7230        populateAccessibilityNodeInfoDrawingOrderInParent(info);
7231    }
7232
7233    /**
7234     * Determine the order in which this view will be drawn relative to its siblings for a11y
7235     *
7236     * @param info The info whose drawing order should be populated
7237     */
7238    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7239        /*
7240         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7241         * drawing order may not be well-defined, and some Views with custom drawing order may
7242         * not be initialized sufficiently to respond properly getChildDrawingOrder.
7243         */
7244        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7245            info.setDrawingOrder(0);
7246            return;
7247        }
7248        int drawingOrderInParent = 1;
7249        // Iterate up the hierarchy if parents are not important for a11y
7250        View viewAtDrawingLevel = this;
7251        final ViewParent parent = getParentForAccessibility();
7252        while (viewAtDrawingLevel != parent) {
7253            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7254            if (!(currentParent instanceof ViewGroup)) {
7255                // Should only happen for the Decor
7256                drawingOrderInParent = 0;
7257                break;
7258            } else {
7259                final ViewGroup parentGroup = (ViewGroup) currentParent;
7260                final int childCount = parentGroup.getChildCount();
7261                if (childCount > 1) {
7262                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7263                    if (preorderedList != null) {
7264                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7265                        for (int i = 0; i < childDrawIndex; i++) {
7266                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7267                        }
7268                    } else {
7269                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7270                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7271                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7272                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7273                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7274                        if (childDrawIndex != 0) {
7275                            for (int i = 0; i < numChildrenToIterate; i++) {
7276                                final int otherDrawIndex = (customOrder ?
7277                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7278                                if (otherDrawIndex < childDrawIndex) {
7279                                    drawingOrderInParent +=
7280                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7281                                }
7282                            }
7283                        }
7284                    }
7285                }
7286            }
7287            viewAtDrawingLevel = (View) currentParent;
7288        }
7289        info.setDrawingOrder(drawingOrderInParent);
7290    }
7291
7292    private static int numViewsForAccessibility(View view) {
7293        if (view != null) {
7294            if (view.includeForAccessibility()) {
7295                return 1;
7296            } else if (view instanceof ViewGroup) {
7297                return ((ViewGroup) view).getNumChildrenForAccessibility();
7298            }
7299        }
7300        return 0;
7301    }
7302
7303    private View findLabelForView(View view, int labeledId) {
7304        if (mMatchLabelForPredicate == null) {
7305            mMatchLabelForPredicate = new MatchLabelForPredicate();
7306        }
7307        mMatchLabelForPredicate.mLabeledId = labeledId;
7308        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7309    }
7310
7311    /**
7312     * Computes whether this view is visible to the user. Such a view is
7313     * attached, visible, all its predecessors are visible, it is not clipped
7314     * entirely by its predecessors, and has an alpha greater than zero.
7315     *
7316     * @return Whether the view is visible on the screen.
7317     *
7318     * @hide
7319     */
7320    protected boolean isVisibleToUser() {
7321        return isVisibleToUser(null);
7322    }
7323
7324    /**
7325     * Computes whether the given portion of this view is visible to the user.
7326     * Such a view is attached, visible, all its predecessors are visible,
7327     * has an alpha greater than zero, and the specified portion is not
7328     * clipped entirely by its predecessors.
7329     *
7330     * @param boundInView the portion of the view to test; coordinates should be relative; may be
7331     *                    <code>null</code>, and the entire view will be tested in this case.
7332     *                    When <code>true</code> is returned by the function, the actual visible
7333     *                    region will be stored in this parameter; that is, if boundInView is fully
7334     *                    contained within the view, no modification will be made, otherwise regions
7335     *                    outside of the visible area of the view will be clipped.
7336     *
7337     * @return Whether the specified portion of the view is visible on the screen.
7338     *
7339     * @hide
7340     */
7341    protected boolean isVisibleToUser(Rect boundInView) {
7342        if (mAttachInfo != null) {
7343            // Attached to invisible window means this view is not visible.
7344            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
7345                return false;
7346            }
7347            // An invisible predecessor or one with alpha zero means
7348            // that this view is not visible to the user.
7349            Object current = this;
7350            while (current instanceof View) {
7351                View view = (View) current;
7352                // We have attach info so this view is attached and there is no
7353                // need to check whether we reach to ViewRootImpl on the way up.
7354                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
7355                        view.getVisibility() != VISIBLE) {
7356                    return false;
7357                }
7358                current = view.mParent;
7359            }
7360            // Check if the view is entirely covered by its predecessors.
7361            Rect visibleRect = mAttachInfo.mTmpInvalRect;
7362            Point offset = mAttachInfo.mPoint;
7363            if (!getGlobalVisibleRect(visibleRect, offset)) {
7364                return false;
7365            }
7366            // Check if the visible portion intersects the rectangle of interest.
7367            if (boundInView != null) {
7368                visibleRect.offset(-offset.x, -offset.y);
7369                return boundInView.intersect(visibleRect);
7370            }
7371            return true;
7372        }
7373        return false;
7374    }
7375
7376    /**
7377     * Returns the delegate for implementing accessibility support via
7378     * composition. For more details see {@link AccessibilityDelegate}.
7379     *
7380     * @return The delegate, or null if none set.
7381     *
7382     * @hide
7383     */
7384    public AccessibilityDelegate getAccessibilityDelegate() {
7385        return mAccessibilityDelegate;
7386    }
7387
7388    /**
7389     * Sets a delegate for implementing accessibility support via composition
7390     * (as opposed to inheritance). For more details, see
7391     * {@link AccessibilityDelegate}.
7392     * <p>
7393     * <strong>Note:</strong> On platform versions prior to
7394     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
7395     * views in the {@code android.widget.*} package are called <i>before</i>
7396     * host methods. This prevents certain properties such as class name from
7397     * being modified by overriding
7398     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
7399     * as any changes will be overwritten by the host class.
7400     * <p>
7401     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
7402     * methods are called <i>after</i> host methods, which all properties to be
7403     * modified without being overwritten by the host class.
7404     *
7405     * @param delegate the object to which accessibility method calls should be
7406     *                 delegated
7407     * @see AccessibilityDelegate
7408     */
7409    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
7410        mAccessibilityDelegate = delegate;
7411    }
7412
7413    /**
7414     * Gets the provider for managing a virtual view hierarchy rooted at this View
7415     * and reported to {@link android.accessibilityservice.AccessibilityService}s
7416     * that explore the window content.
7417     * <p>
7418     * If this method returns an instance, this instance is responsible for managing
7419     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
7420     * View including the one representing the View itself. Similarly the returned
7421     * instance is responsible for performing accessibility actions on any virtual
7422     * view or the root view itself.
7423     * </p>
7424     * <p>
7425     * If an {@link AccessibilityDelegate} has been specified via calling
7426     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7427     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
7428     * is responsible for handling this call.
7429     * </p>
7430     *
7431     * @return The provider.
7432     *
7433     * @see AccessibilityNodeProvider
7434     */
7435    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
7436        if (mAccessibilityDelegate != null) {
7437            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
7438        } else {
7439            return null;
7440        }
7441    }
7442
7443    /**
7444     * Gets the unique identifier of this view on the screen for accessibility purposes.
7445     *
7446     * @return The view accessibility id.
7447     *
7448     * @hide
7449     */
7450    public int getAccessibilityViewId() {
7451        if (mAccessibilityViewId == NO_ID) {
7452            mAccessibilityViewId = sNextAccessibilityViewId++;
7453        }
7454        return mAccessibilityViewId;
7455    }
7456
7457    /**
7458     * Gets the unique identifier of the window in which this View reseides.
7459     *
7460     * @return The window accessibility id.
7461     *
7462     * @hide
7463     */
7464    public int getAccessibilityWindowId() {
7465        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
7466                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
7467    }
7468
7469    /**
7470     * Returns the {@link View}'s content description.
7471     * <p>
7472     * <strong>Note:</strong> Do not override this method, as it will have no
7473     * effect on the content description presented to accessibility services.
7474     * You must call {@link #setContentDescription(CharSequence)} to modify the
7475     * content description.
7476     *
7477     * @return the content description
7478     * @see #setContentDescription(CharSequence)
7479     * @attr ref android.R.styleable#View_contentDescription
7480     */
7481    @ViewDebug.ExportedProperty(category = "accessibility")
7482    public CharSequence getContentDescription() {
7483        return mContentDescription;
7484    }
7485
7486    /**
7487     * Sets the {@link View}'s content description.
7488     * <p>
7489     * A content description briefly describes the view and is primarily used
7490     * for accessibility support to determine how a view should be presented to
7491     * the user. In the case of a view with no textual representation, such as
7492     * {@link android.widget.ImageButton}, a useful content description
7493     * explains what the view does. For example, an image button with a phone
7494     * icon that is used to place a call may use "Call" as its content
7495     * description. An image of a floppy disk that is used to save a file may
7496     * use "Save".
7497     *
7498     * @param contentDescription The content description.
7499     * @see #getContentDescription()
7500     * @attr ref android.R.styleable#View_contentDescription
7501     */
7502    @RemotableViewMethod
7503    public void setContentDescription(CharSequence contentDescription) {
7504        if (mContentDescription == null) {
7505            if (contentDescription == null) {
7506                return;
7507            }
7508        } else if (mContentDescription.equals(contentDescription)) {
7509            return;
7510        }
7511        mContentDescription = contentDescription;
7512        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
7513        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
7514            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
7515            notifySubtreeAccessibilityStateChangedIfNeeded();
7516        } else {
7517            notifyViewAccessibilityStateChangedIfNeeded(
7518                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
7519        }
7520    }
7521
7522    /**
7523     * Sets the id of a view before which this one is visited in accessibility traversal.
7524     * A screen-reader must visit the content of this view before the content of the one
7525     * it precedes. For example, if view B is set to be before view A, then a screen-reader
7526     * will traverse the entire content of B before traversing the entire content of A,
7527     * regardles of what traversal strategy it is using.
7528     * <p>
7529     * Views that do not have specified before/after relationships are traversed in order
7530     * determined by the screen-reader.
7531     * </p>
7532     * <p>
7533     * Setting that this view is before a view that is not important for accessibility
7534     * or if this view is not important for accessibility will have no effect as the
7535     * screen-reader is not aware of unimportant views.
7536     * </p>
7537     *
7538     * @param beforeId The id of a view this one precedes in accessibility traversal.
7539     *
7540     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
7541     *
7542     * @see #setImportantForAccessibility(int)
7543     */
7544    @RemotableViewMethod
7545    public void setAccessibilityTraversalBefore(int beforeId) {
7546        if (mAccessibilityTraversalBeforeId == beforeId) {
7547            return;
7548        }
7549        mAccessibilityTraversalBeforeId = beforeId;
7550        notifyViewAccessibilityStateChangedIfNeeded(
7551                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7552    }
7553
7554    /**
7555     * Gets the id of a view before which this one is visited in accessibility traversal.
7556     *
7557     * @return The id of a view this one precedes in accessibility traversal if
7558     *         specified, otherwise {@link #NO_ID}.
7559     *
7560     * @see #setAccessibilityTraversalBefore(int)
7561     */
7562    public int getAccessibilityTraversalBefore() {
7563        return mAccessibilityTraversalBeforeId;
7564    }
7565
7566    /**
7567     * Sets the id of a view after which this one is visited in accessibility traversal.
7568     * A screen-reader must visit the content of the other view before the content of this
7569     * one. For example, if view B is set to be after view A, then a screen-reader
7570     * will traverse the entire content of A before traversing the entire content of B,
7571     * regardles of what traversal strategy it is using.
7572     * <p>
7573     * Views that do not have specified before/after relationships are traversed in order
7574     * determined by the screen-reader.
7575     * </p>
7576     * <p>
7577     * Setting that this view is after a view that is not important for accessibility
7578     * or if this view is not important for accessibility will have no effect as the
7579     * screen-reader is not aware of unimportant views.
7580     * </p>
7581     *
7582     * @param afterId The id of a view this one succedees in accessibility traversal.
7583     *
7584     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
7585     *
7586     * @see #setImportantForAccessibility(int)
7587     */
7588    @RemotableViewMethod
7589    public void setAccessibilityTraversalAfter(int afterId) {
7590        if (mAccessibilityTraversalAfterId == afterId) {
7591            return;
7592        }
7593        mAccessibilityTraversalAfterId = afterId;
7594        notifyViewAccessibilityStateChangedIfNeeded(
7595                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7596    }
7597
7598    /**
7599     * Gets the id of a view after which this one is visited in accessibility traversal.
7600     *
7601     * @return The id of a view this one succeedes in accessibility traversal if
7602     *         specified, otherwise {@link #NO_ID}.
7603     *
7604     * @see #setAccessibilityTraversalAfter(int)
7605     */
7606    public int getAccessibilityTraversalAfter() {
7607        return mAccessibilityTraversalAfterId;
7608    }
7609
7610    /**
7611     * Gets the id of a view for which this view serves as a label for
7612     * accessibility purposes.
7613     *
7614     * @return The labeled view id.
7615     */
7616    @ViewDebug.ExportedProperty(category = "accessibility")
7617    public int getLabelFor() {
7618        return mLabelForId;
7619    }
7620
7621    /**
7622     * Sets the id of a view for which this view serves as a label for
7623     * accessibility purposes.
7624     *
7625     * @param id The labeled view id.
7626     */
7627    @RemotableViewMethod
7628    public void setLabelFor(@IdRes int id) {
7629        if (mLabelForId == id) {
7630            return;
7631        }
7632        mLabelForId = id;
7633        if (mLabelForId != View.NO_ID
7634                && mID == View.NO_ID) {
7635            mID = generateViewId();
7636        }
7637        notifyViewAccessibilityStateChangedIfNeeded(
7638                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7639    }
7640
7641    /**
7642     * Invoked whenever this view loses focus, either by losing window focus or by losing
7643     * focus within its window. This method can be used to clear any state tied to the
7644     * focus. For instance, if a button is held pressed with the trackball and the window
7645     * loses focus, this method can be used to cancel the press.
7646     *
7647     * Subclasses of View overriding this method should always call super.onFocusLost().
7648     *
7649     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7650     * @see #onWindowFocusChanged(boolean)
7651     *
7652     * @hide pending API council approval
7653     */
7654    @CallSuper
7655    protected void onFocusLost() {
7656        resetPressedState();
7657    }
7658
7659    private void resetPressedState() {
7660        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7661            return;
7662        }
7663
7664        if (isPressed()) {
7665            setPressed(false);
7666
7667            if (!mHasPerformedLongPress) {
7668                removeLongPressCallback();
7669            }
7670        }
7671    }
7672
7673    /**
7674     * Returns true if this view has focus
7675     *
7676     * @return True if this view has focus, false otherwise.
7677     */
7678    @ViewDebug.ExportedProperty(category = "focus")
7679    public boolean isFocused() {
7680        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7681    }
7682
7683    /**
7684     * Find the view in the hierarchy rooted at this view that currently has
7685     * focus.
7686     *
7687     * @return The view that currently has focus, or null if no focused view can
7688     *         be found.
7689     */
7690    public View findFocus() {
7691        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7692    }
7693
7694    /**
7695     * Indicates whether this view is one of the set of scrollable containers in
7696     * its window.
7697     *
7698     * @return whether this view is one of the set of scrollable containers in
7699     * its window
7700     *
7701     * @attr ref android.R.styleable#View_isScrollContainer
7702     */
7703    public boolean isScrollContainer() {
7704        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7705    }
7706
7707    /**
7708     * Change whether this view is one of the set of scrollable containers in
7709     * its window.  This will be used to determine whether the window can
7710     * resize or must pan when a soft input area is open -- scrollable
7711     * containers allow the window to use resize mode since the container
7712     * will appropriately shrink.
7713     *
7714     * @attr ref android.R.styleable#View_isScrollContainer
7715     */
7716    public void setScrollContainer(boolean isScrollContainer) {
7717        if (isScrollContainer) {
7718            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7719                mAttachInfo.mScrollContainers.add(this);
7720                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7721            }
7722            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7723        } else {
7724            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7725                mAttachInfo.mScrollContainers.remove(this);
7726            }
7727            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7728        }
7729    }
7730
7731    /**
7732     * Returns the quality of the drawing cache.
7733     *
7734     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7735     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7736     *
7737     * @see #setDrawingCacheQuality(int)
7738     * @see #setDrawingCacheEnabled(boolean)
7739     * @see #isDrawingCacheEnabled()
7740     *
7741     * @attr ref android.R.styleable#View_drawingCacheQuality
7742     */
7743    @DrawingCacheQuality
7744    public int getDrawingCacheQuality() {
7745        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7746    }
7747
7748    /**
7749     * Set the drawing cache quality of this view. This value is used only when the
7750     * drawing cache is enabled
7751     *
7752     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7753     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7754     *
7755     * @see #getDrawingCacheQuality()
7756     * @see #setDrawingCacheEnabled(boolean)
7757     * @see #isDrawingCacheEnabled()
7758     *
7759     * @attr ref android.R.styleable#View_drawingCacheQuality
7760     */
7761    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7762        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7763    }
7764
7765    /**
7766     * Returns whether the screen should remain on, corresponding to the current
7767     * value of {@link #KEEP_SCREEN_ON}.
7768     *
7769     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7770     *
7771     * @see #setKeepScreenOn(boolean)
7772     *
7773     * @attr ref android.R.styleable#View_keepScreenOn
7774     */
7775    public boolean getKeepScreenOn() {
7776        return (mViewFlags & KEEP_SCREEN_ON) != 0;
7777    }
7778
7779    /**
7780     * Controls whether the screen should remain on, modifying the
7781     * value of {@link #KEEP_SCREEN_ON}.
7782     *
7783     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7784     *
7785     * @see #getKeepScreenOn()
7786     *
7787     * @attr ref android.R.styleable#View_keepScreenOn
7788     */
7789    public void setKeepScreenOn(boolean keepScreenOn) {
7790        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7791    }
7792
7793    /**
7794     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7795     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7796     *
7797     * @attr ref android.R.styleable#View_nextFocusLeft
7798     */
7799    public int getNextFocusLeftId() {
7800        return mNextFocusLeftId;
7801    }
7802
7803    /**
7804     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7805     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7806     * decide automatically.
7807     *
7808     * @attr ref android.R.styleable#View_nextFocusLeft
7809     */
7810    public void setNextFocusLeftId(int nextFocusLeftId) {
7811        mNextFocusLeftId = nextFocusLeftId;
7812    }
7813
7814    /**
7815     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7816     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7817     *
7818     * @attr ref android.R.styleable#View_nextFocusRight
7819     */
7820    public int getNextFocusRightId() {
7821        return mNextFocusRightId;
7822    }
7823
7824    /**
7825     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7826     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7827     * decide automatically.
7828     *
7829     * @attr ref android.R.styleable#View_nextFocusRight
7830     */
7831    public void setNextFocusRightId(int nextFocusRightId) {
7832        mNextFocusRightId = nextFocusRightId;
7833    }
7834
7835    /**
7836     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7837     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7838     *
7839     * @attr ref android.R.styleable#View_nextFocusUp
7840     */
7841    public int getNextFocusUpId() {
7842        return mNextFocusUpId;
7843    }
7844
7845    /**
7846     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7847     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7848     * decide automatically.
7849     *
7850     * @attr ref android.R.styleable#View_nextFocusUp
7851     */
7852    public void setNextFocusUpId(int nextFocusUpId) {
7853        mNextFocusUpId = nextFocusUpId;
7854    }
7855
7856    /**
7857     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7858     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7859     *
7860     * @attr ref android.R.styleable#View_nextFocusDown
7861     */
7862    public int getNextFocusDownId() {
7863        return mNextFocusDownId;
7864    }
7865
7866    /**
7867     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7868     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7869     * decide automatically.
7870     *
7871     * @attr ref android.R.styleable#View_nextFocusDown
7872     */
7873    public void setNextFocusDownId(int nextFocusDownId) {
7874        mNextFocusDownId = nextFocusDownId;
7875    }
7876
7877    /**
7878     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7879     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7880     *
7881     * @attr ref android.R.styleable#View_nextFocusForward
7882     */
7883    public int getNextFocusForwardId() {
7884        return mNextFocusForwardId;
7885    }
7886
7887    /**
7888     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7889     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7890     * decide automatically.
7891     *
7892     * @attr ref android.R.styleable#View_nextFocusForward
7893     */
7894    public void setNextFocusForwardId(int nextFocusForwardId) {
7895        mNextFocusForwardId = nextFocusForwardId;
7896    }
7897
7898    /**
7899     * Gets the id of the root of the next keyboard navigation cluster.
7900     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
7901     * decide automatically.
7902     *
7903     * @attr ref android.R.styleable#View_nextClusterForward
7904     */
7905    public int getNextClusterForwardId() {
7906        return mNextClusterForwardId;
7907    }
7908
7909    /**
7910     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
7911     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
7912     * decide automatically.
7913     *
7914     * @attr ref android.R.styleable#View_nextClusterForward
7915     */
7916    public void setNextClusterForwardId(int nextClusterForwardId) {
7917        mNextClusterForwardId = nextClusterForwardId;
7918    }
7919
7920    /**
7921     * Gets the id of the root of the next keyboard navigation section.
7922     * @return The next keyboard navigation section ID, or {@link #NO_ID} if the framework should
7923     * decide automatically.
7924     *
7925     * @attr ref android.R.styleable#View_nextSectionForward
7926     */
7927    public int getNextSectionForwardId() {
7928        return mNextSectionForwardId;
7929    }
7930
7931    /**
7932     * Sets the id of the view to use as the root of the next keyboard navigation section.
7933     * @param nextSectionForwardId The next section ID, or {@link #NO_ID} if the framework should
7934     * decide automatically.
7935     *
7936     * @attr ref android.R.styleable#View_nextSectionForward
7937     */
7938    public void setNextSectionForwardId(int nextSectionForwardId) {
7939        mNextSectionForwardId = nextSectionForwardId;
7940    }
7941
7942    /**
7943     * Returns the visibility of this view and all of its ancestors
7944     *
7945     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7946     */
7947    public boolean isShown() {
7948        View current = this;
7949        //noinspection ConstantConditions
7950        do {
7951            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7952                return false;
7953            }
7954            ViewParent parent = current.mParent;
7955            if (parent == null) {
7956                return false; // We are not attached to the view root
7957            }
7958            if (!(parent instanceof View)) {
7959                return true;
7960            }
7961            current = (View) parent;
7962        } while (current != null);
7963
7964        return false;
7965    }
7966
7967    /**
7968     * Called by the view hierarchy when the content insets for a window have
7969     * changed, to allow it to adjust its content to fit within those windows.
7970     * The content insets tell you the space that the status bar, input method,
7971     * and other system windows infringe on the application's window.
7972     *
7973     * <p>You do not normally need to deal with this function, since the default
7974     * window decoration given to applications takes care of applying it to the
7975     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7976     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7977     * and your content can be placed under those system elements.  You can then
7978     * use this method within your view hierarchy if you have parts of your UI
7979     * which you would like to ensure are not being covered.
7980     *
7981     * <p>The default implementation of this method simply applies the content
7982     * insets to the view's padding, consuming that content (modifying the
7983     * insets to be 0), and returning true.  This behavior is off by default, but can
7984     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7985     *
7986     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7987     * insets object is propagated down the hierarchy, so any changes made to it will
7988     * be seen by all following views (including potentially ones above in
7989     * the hierarchy since this is a depth-first traversal).  The first view
7990     * that returns true will abort the entire traversal.
7991     *
7992     * <p>The default implementation works well for a situation where it is
7993     * used with a container that covers the entire window, allowing it to
7994     * apply the appropriate insets to its content on all edges.  If you need
7995     * a more complicated layout (such as two different views fitting system
7996     * windows, one on the top of the window, and one on the bottom),
7997     * you can override the method and handle the insets however you would like.
7998     * Note that the insets provided by the framework are always relative to the
7999     * far edges of the window, not accounting for the location of the called view
8000     * within that window.  (In fact when this method is called you do not yet know
8001     * where the layout will place the view, as it is done before layout happens.)
8002     *
8003     * <p>Note: unlike many View methods, there is no dispatch phase to this
8004     * call.  If you are overriding it in a ViewGroup and want to allow the
8005     * call to continue to your children, you must be sure to call the super
8006     * implementation.
8007     *
8008     * <p>Here is a sample layout that makes use of fitting system windows
8009     * to have controls for a video view placed inside of the window decorations
8010     * that it hides and shows.  This can be used with code like the second
8011     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
8012     *
8013     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
8014     *
8015     * @param insets Current content insets of the window.  Prior to
8016     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
8017     * the insets or else you and Android will be unhappy.
8018     *
8019     * @return {@code true} if this view applied the insets and it should not
8020     * continue propagating further down the hierarchy, {@code false} otherwise.
8021     * @see #getFitsSystemWindows()
8022     * @see #setFitsSystemWindows(boolean)
8023     * @see #setSystemUiVisibility(int)
8024     *
8025     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
8026     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
8027     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
8028     * to implement handling their own insets.
8029     */
8030    @Deprecated
8031    protected boolean fitSystemWindows(Rect insets) {
8032        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
8033            if (insets == null) {
8034                // Null insets by definition have already been consumed.
8035                // This call cannot apply insets since there are none to apply,
8036                // so return false.
8037                return false;
8038            }
8039            // If we're not in the process of dispatching the newer apply insets call,
8040            // that means we're not in the compatibility path. Dispatch into the newer
8041            // apply insets path and take things from there.
8042            try {
8043                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
8044                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
8045            } finally {
8046                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
8047            }
8048        } else {
8049            // We're being called from the newer apply insets path.
8050            // Perform the standard fallback behavior.
8051            return fitSystemWindowsInt(insets);
8052        }
8053    }
8054
8055    private boolean fitSystemWindowsInt(Rect insets) {
8056        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
8057            mUserPaddingStart = UNDEFINED_PADDING;
8058            mUserPaddingEnd = UNDEFINED_PADDING;
8059            Rect localInsets = sThreadLocal.get();
8060            if (localInsets == null) {
8061                localInsets = new Rect();
8062                sThreadLocal.set(localInsets);
8063            }
8064            boolean res = computeFitSystemWindows(insets, localInsets);
8065            mUserPaddingLeftInitial = localInsets.left;
8066            mUserPaddingRightInitial = localInsets.right;
8067            internalSetPadding(localInsets.left, localInsets.top,
8068                    localInsets.right, localInsets.bottom);
8069            return res;
8070        }
8071        return false;
8072    }
8073
8074    /**
8075     * Called when the view should apply {@link WindowInsets} according to its internal policy.
8076     *
8077     * <p>This method should be overridden by views that wish to apply a policy different from or
8078     * in addition to the default behavior. Clients that wish to force a view subtree
8079     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
8080     *
8081     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
8082     * it will be called during dispatch instead of this method. The listener may optionally
8083     * call this method from its own implementation if it wishes to apply the view's default
8084     * insets policy in addition to its own.</p>
8085     *
8086     * <p>Implementations of this method should either return the insets parameter unchanged
8087     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
8088     * that this view applied itself. This allows new inset types added in future platform
8089     * versions to pass through existing implementations unchanged without being erroneously
8090     * consumed.</p>
8091     *
8092     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
8093     * property is set then the view will consume the system window insets and apply them
8094     * as padding for the view.</p>
8095     *
8096     * @param insets Insets to apply
8097     * @return The supplied insets with any applied insets consumed
8098     */
8099    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
8100        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
8101            // We weren't called from within a direct call to fitSystemWindows,
8102            // call into it as a fallback in case we're in a class that overrides it
8103            // and has logic to perform.
8104            if (fitSystemWindows(insets.getSystemWindowInsets())) {
8105                return insets.consumeSystemWindowInsets();
8106            }
8107        } else {
8108            // We were called from within a direct call to fitSystemWindows.
8109            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
8110                return insets.consumeSystemWindowInsets();
8111            }
8112        }
8113        return insets;
8114    }
8115
8116    /**
8117     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
8118     * window insets to this view. The listener's
8119     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
8120     * method will be called instead of the view's
8121     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
8122     *
8123     * @param listener Listener to set
8124     *
8125     * @see #onApplyWindowInsets(WindowInsets)
8126     */
8127    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
8128        getListenerInfo().mOnApplyWindowInsetsListener = listener;
8129    }
8130
8131    /**
8132     * Request to apply the given window insets to this view or another view in its subtree.
8133     *
8134     * <p>This method should be called by clients wishing to apply insets corresponding to areas
8135     * obscured by window decorations or overlays. This can include the status and navigation bars,
8136     * action bars, input methods and more. New inset categories may be added in the future.
8137     * The method returns the insets provided minus any that were applied by this view or its
8138     * children.</p>
8139     *
8140     * <p>Clients wishing to provide custom behavior should override the
8141     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
8142     * {@link OnApplyWindowInsetsListener} via the
8143     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
8144     * method.</p>
8145     *
8146     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
8147     * </p>
8148     *
8149     * @param insets Insets to apply
8150     * @return The provided insets minus the insets that were consumed
8151     */
8152    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
8153        try {
8154            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
8155            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
8156                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
8157            } else {
8158                return onApplyWindowInsets(insets);
8159            }
8160        } finally {
8161            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
8162        }
8163    }
8164
8165    /**
8166     * Compute the view's coordinate within the surface.
8167     *
8168     * <p>Computes the coordinates of this view in its surface. The argument
8169     * must be an array of two integers. After the method returns, the array
8170     * contains the x and y location in that order.</p>
8171     * @hide
8172     * @param location an array of two integers in which to hold the coordinates
8173     */
8174    public void getLocationInSurface(@Size(2) int[] location) {
8175        getLocationInWindow(location);
8176        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
8177            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
8178            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
8179        }
8180    }
8181
8182    /**
8183     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
8184     * only available if the view is attached.
8185     *
8186     * @return WindowInsets from the top of the view hierarchy or null if View is detached
8187     */
8188    public WindowInsets getRootWindowInsets() {
8189        if (mAttachInfo != null) {
8190            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
8191        }
8192        return null;
8193    }
8194
8195    /**
8196     * @hide Compute the insets that should be consumed by this view and the ones
8197     * that should propagate to those under it.
8198     */
8199    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
8200        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8201                || mAttachInfo == null
8202                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
8203                        && !mAttachInfo.mOverscanRequested)) {
8204            outLocalInsets.set(inoutInsets);
8205            inoutInsets.set(0, 0, 0, 0);
8206            return true;
8207        } else {
8208            // The application wants to take care of fitting system window for
8209            // the content...  however we still need to take care of any overscan here.
8210            final Rect overscan = mAttachInfo.mOverscanInsets;
8211            outLocalInsets.set(overscan);
8212            inoutInsets.left -= overscan.left;
8213            inoutInsets.top -= overscan.top;
8214            inoutInsets.right -= overscan.right;
8215            inoutInsets.bottom -= overscan.bottom;
8216            return false;
8217        }
8218    }
8219
8220    /**
8221     * Compute insets that should be consumed by this view and the ones that should propagate
8222     * to those under it.
8223     *
8224     * @param in Insets currently being processed by this View, likely received as a parameter
8225     *           to {@link #onApplyWindowInsets(WindowInsets)}.
8226     * @param outLocalInsets A Rect that will receive the insets that should be consumed
8227     *                       by this view
8228     * @return Insets that should be passed along to views under this one
8229     */
8230    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
8231        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8232                || mAttachInfo == null
8233                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
8234            outLocalInsets.set(in.getSystemWindowInsets());
8235            return in.consumeSystemWindowInsets();
8236        } else {
8237            outLocalInsets.set(0, 0, 0, 0);
8238            return in;
8239        }
8240    }
8241
8242    /**
8243     * Sets whether or not this view should account for system screen decorations
8244     * such as the status bar and inset its content; that is, controlling whether
8245     * the default implementation of {@link #fitSystemWindows(Rect)} will be
8246     * executed.  See that method for more details.
8247     *
8248     * <p>Note that if you are providing your own implementation of
8249     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
8250     * flag to true -- your implementation will be overriding the default
8251     * implementation that checks this flag.
8252     *
8253     * @param fitSystemWindows If true, then the default implementation of
8254     * {@link #fitSystemWindows(Rect)} will be executed.
8255     *
8256     * @attr ref android.R.styleable#View_fitsSystemWindows
8257     * @see #getFitsSystemWindows()
8258     * @see #fitSystemWindows(Rect)
8259     * @see #setSystemUiVisibility(int)
8260     */
8261    public void setFitsSystemWindows(boolean fitSystemWindows) {
8262        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
8263    }
8264
8265    /**
8266     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
8267     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
8268     * will be executed.
8269     *
8270     * @return {@code true} if the default implementation of
8271     * {@link #fitSystemWindows(Rect)} will be executed.
8272     *
8273     * @attr ref android.R.styleable#View_fitsSystemWindows
8274     * @see #setFitsSystemWindows(boolean)
8275     * @see #fitSystemWindows(Rect)
8276     * @see #setSystemUiVisibility(int)
8277     */
8278    @ViewDebug.ExportedProperty
8279    public boolean getFitsSystemWindows() {
8280        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8281    }
8282
8283    /** @hide */
8284    public boolean fitsSystemWindows() {
8285        return getFitsSystemWindows();
8286    }
8287
8288    /**
8289     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8290     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8291     */
8292    @Deprecated
8293    public void requestFitSystemWindows() {
8294        if (mParent != null) {
8295            mParent.requestFitSystemWindows();
8296        }
8297    }
8298
8299    /**
8300     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8301     */
8302    public void requestApplyInsets() {
8303        requestFitSystemWindows();
8304    }
8305
8306    /**
8307     * For use by PhoneWindow to make its own system window fitting optional.
8308     * @hide
8309     */
8310    public void makeOptionalFitsSystemWindows() {
8311        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8312    }
8313
8314    /**
8315     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8316     * treat them as such.
8317     * @hide
8318     */
8319    public void getOutsets(Rect outOutsetRect) {
8320        if (mAttachInfo != null) {
8321            outOutsetRect.set(mAttachInfo.mOutsets);
8322        } else {
8323            outOutsetRect.setEmpty();
8324        }
8325    }
8326
8327    /**
8328     * Returns the visibility status for this view.
8329     *
8330     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8331     * @attr ref android.R.styleable#View_visibility
8332     */
8333    @ViewDebug.ExportedProperty(mapping = {
8334        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8335        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8336        @ViewDebug.IntToString(from = GONE,      to = "GONE")
8337    })
8338    @Visibility
8339    public int getVisibility() {
8340        return mViewFlags & VISIBILITY_MASK;
8341    }
8342
8343    /**
8344     * Set the visibility state of this view.
8345     *
8346     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8347     * @attr ref android.R.styleable#View_visibility
8348     */
8349    @RemotableViewMethod
8350    public void setVisibility(@Visibility int visibility) {
8351        setFlags(visibility, VISIBILITY_MASK);
8352    }
8353
8354    /**
8355     * Returns the enabled status for this view. The interpretation of the
8356     * enabled state varies by subclass.
8357     *
8358     * @return True if this view is enabled, false otherwise.
8359     */
8360    @ViewDebug.ExportedProperty
8361    public boolean isEnabled() {
8362        return (mViewFlags & ENABLED_MASK) == ENABLED;
8363    }
8364
8365    /**
8366     * Set the enabled state of this view. The interpretation of the enabled
8367     * state varies by subclass.
8368     *
8369     * @param enabled True if this view is enabled, false otherwise.
8370     */
8371    @RemotableViewMethod
8372    public void setEnabled(boolean enabled) {
8373        if (enabled == isEnabled()) return;
8374
8375        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
8376
8377        /*
8378         * The View most likely has to change its appearance, so refresh
8379         * the drawable state.
8380         */
8381        refreshDrawableState();
8382
8383        // Invalidate too, since the default behavior for views is to be
8384        // be drawn at 50% alpha rather than to change the drawable.
8385        invalidate(true);
8386
8387        if (!enabled) {
8388            cancelPendingInputEvents();
8389        }
8390    }
8391
8392    /**
8393     * Set whether this view can receive the focus.
8394     *
8395     * Setting this to false will also ensure that this view is not focusable
8396     * in touch mode.
8397     *
8398     * @param focusable If true, this view can receive the focus.
8399     *
8400     * @see #setFocusableInTouchMode(boolean)
8401     * @attr ref android.R.styleable#View_focusable
8402     */
8403    public void setFocusable(boolean focusable) {
8404        if (!focusable) {
8405            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
8406        }
8407        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
8408    }
8409
8410    /**
8411     * Set whether this view can receive focus while in touch mode.
8412     *
8413     * Setting this to true will also ensure that this view is focusable.
8414     *
8415     * @param focusableInTouchMode If true, this view can receive the focus while
8416     *   in touch mode.
8417     *
8418     * @see #setFocusable(boolean)
8419     * @attr ref android.R.styleable#View_focusableInTouchMode
8420     */
8421    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
8422        // Focusable in touch mode should always be set before the focusable flag
8423        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
8424        // which, in touch mode, will not successfully request focus on this view
8425        // because the focusable in touch mode flag is not set
8426        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
8427        if (focusableInTouchMode) {
8428            setFlags(FOCUSABLE, FOCUSABLE_MASK);
8429        }
8430    }
8431
8432    /**
8433     * Set whether this view should have sound effects enabled for events such as
8434     * clicking and touching.
8435     *
8436     * <p>You may wish to disable sound effects for a view if you already play sounds,
8437     * for instance, a dial key that plays dtmf tones.
8438     *
8439     * @param soundEffectsEnabled whether sound effects are enabled for this view.
8440     * @see #isSoundEffectsEnabled()
8441     * @see #playSoundEffect(int)
8442     * @attr ref android.R.styleable#View_soundEffectsEnabled
8443     */
8444    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
8445        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
8446    }
8447
8448    /**
8449     * @return whether this view should have sound effects enabled for events such as
8450     *     clicking and touching.
8451     *
8452     * @see #setSoundEffectsEnabled(boolean)
8453     * @see #playSoundEffect(int)
8454     * @attr ref android.R.styleable#View_soundEffectsEnabled
8455     */
8456    @ViewDebug.ExportedProperty
8457    public boolean isSoundEffectsEnabled() {
8458        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
8459    }
8460
8461    /**
8462     * Set whether this view should have haptic feedback for events such as
8463     * long presses.
8464     *
8465     * <p>You may wish to disable haptic feedback if your view already controls
8466     * its own haptic feedback.
8467     *
8468     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
8469     * @see #isHapticFeedbackEnabled()
8470     * @see #performHapticFeedback(int)
8471     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8472     */
8473    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
8474        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
8475    }
8476
8477    /**
8478     * @return whether this view should have haptic feedback enabled for events
8479     * long presses.
8480     *
8481     * @see #setHapticFeedbackEnabled(boolean)
8482     * @see #performHapticFeedback(int)
8483     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8484     */
8485    @ViewDebug.ExportedProperty
8486    public boolean isHapticFeedbackEnabled() {
8487        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
8488    }
8489
8490    /**
8491     * Returns the layout direction for this view.
8492     *
8493     * @return One of {@link #LAYOUT_DIRECTION_LTR},
8494     *   {@link #LAYOUT_DIRECTION_RTL},
8495     *   {@link #LAYOUT_DIRECTION_INHERIT} or
8496     *   {@link #LAYOUT_DIRECTION_LOCALE}.
8497     *
8498     * @attr ref android.R.styleable#View_layoutDirection
8499     *
8500     * @hide
8501     */
8502    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8503        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
8504        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
8505        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
8506        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
8507    })
8508    @LayoutDir
8509    public int getRawLayoutDirection() {
8510        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
8511    }
8512
8513    /**
8514     * Set the layout direction for this view. This will propagate a reset of layout direction
8515     * resolution to the view's children and resolve layout direction for this view.
8516     *
8517     * @param layoutDirection the layout direction to set. Should be one of:
8518     *
8519     * {@link #LAYOUT_DIRECTION_LTR},
8520     * {@link #LAYOUT_DIRECTION_RTL},
8521     * {@link #LAYOUT_DIRECTION_INHERIT},
8522     * {@link #LAYOUT_DIRECTION_LOCALE}.
8523     *
8524     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
8525     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
8526     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
8527     *
8528     * @attr ref android.R.styleable#View_layoutDirection
8529     */
8530    @RemotableViewMethod
8531    public void setLayoutDirection(@LayoutDir int layoutDirection) {
8532        if (getRawLayoutDirection() != layoutDirection) {
8533            // Reset the current layout direction and the resolved one
8534            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
8535            resetRtlProperties();
8536            // Set the new layout direction (filtered)
8537            mPrivateFlags2 |=
8538                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
8539            // We need to resolve all RTL properties as they all depend on layout direction
8540            resolveRtlPropertiesIfNeeded();
8541            requestLayout();
8542            invalidate(true);
8543        }
8544    }
8545
8546    /**
8547     * Returns the resolved layout direction for this view.
8548     *
8549     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
8550     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
8551     *
8552     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
8553     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
8554     *
8555     * @attr ref android.R.styleable#View_layoutDirection
8556     */
8557    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8558        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
8559        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
8560    })
8561    @ResolvedLayoutDir
8562    public int getLayoutDirection() {
8563        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
8564        if (targetSdkVersion < JELLY_BEAN_MR1) {
8565            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
8566            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
8567        }
8568        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
8569                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
8570    }
8571
8572    /**
8573     * Indicates whether or not this view's layout is right-to-left. This is resolved from
8574     * layout attribute and/or the inherited value from the parent
8575     *
8576     * @return true if the layout is right-to-left.
8577     *
8578     * @hide
8579     */
8580    @ViewDebug.ExportedProperty(category = "layout")
8581    public boolean isLayoutRtl() {
8582        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
8583    }
8584
8585    /**
8586     * Indicates whether the view is currently tracking transient state that the
8587     * app should not need to concern itself with saving and restoring, but that
8588     * the framework should take special note to preserve when possible.
8589     *
8590     * <p>A view with transient state cannot be trivially rebound from an external
8591     * data source, such as an adapter binding item views in a list. This may be
8592     * because the view is performing an animation, tracking user selection
8593     * of content, or similar.</p>
8594     *
8595     * @return true if the view has transient state
8596     */
8597    @ViewDebug.ExportedProperty(category = "layout")
8598    public boolean hasTransientState() {
8599        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
8600    }
8601
8602    /**
8603     * Set whether this view is currently tracking transient state that the
8604     * framework should attempt to preserve when possible. This flag is reference counted,
8605     * so every call to setHasTransientState(true) should be paired with a later call
8606     * to setHasTransientState(false).
8607     *
8608     * <p>A view with transient state cannot be trivially rebound from an external
8609     * data source, such as an adapter binding item views in a list. This may be
8610     * because the view is performing an animation, tracking user selection
8611     * of content, or similar.</p>
8612     *
8613     * @param hasTransientState true if this view has transient state
8614     */
8615    public void setHasTransientState(boolean hasTransientState) {
8616        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
8617                mTransientStateCount - 1;
8618        if (mTransientStateCount < 0) {
8619            mTransientStateCount = 0;
8620            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
8621                    "unmatched pair of setHasTransientState calls");
8622        } else if ((hasTransientState && mTransientStateCount == 1) ||
8623                (!hasTransientState && mTransientStateCount == 0)) {
8624            // update flag if we've just incremented up from 0 or decremented down to 0
8625            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
8626                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
8627            if (mParent != null) {
8628                try {
8629                    mParent.childHasTransientStateChanged(this, hasTransientState);
8630                } catch (AbstractMethodError e) {
8631                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8632                            " does not fully implement ViewParent", e);
8633                }
8634            }
8635        }
8636    }
8637
8638    /**
8639     * Returns true if this view is currently attached to a window.
8640     */
8641    public boolean isAttachedToWindow() {
8642        return mAttachInfo != null;
8643    }
8644
8645    /**
8646     * Returns true if this view has been through at least one layout since it
8647     * was last attached to or detached from a window.
8648     */
8649    public boolean isLaidOut() {
8650        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
8651    }
8652
8653    /**
8654     * If this view doesn't do any drawing on its own, set this flag to
8655     * allow further optimizations. By default, this flag is not set on
8656     * View, but could be set on some View subclasses such as ViewGroup.
8657     *
8658     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8659     * you should clear this flag.
8660     *
8661     * @param willNotDraw whether or not this View draw on its own
8662     */
8663    public void setWillNotDraw(boolean willNotDraw) {
8664        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8665    }
8666
8667    /**
8668     * Returns whether or not this View draws on its own.
8669     *
8670     * @return true if this view has nothing to draw, false otherwise
8671     */
8672    @ViewDebug.ExportedProperty(category = "drawing")
8673    public boolean willNotDraw() {
8674        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8675    }
8676
8677    /**
8678     * When a View's drawing cache is enabled, drawing is redirected to an
8679     * offscreen bitmap. Some views, like an ImageView, must be able to
8680     * bypass this mechanism if they already draw a single bitmap, to avoid
8681     * unnecessary usage of the memory.
8682     *
8683     * @param willNotCacheDrawing true if this view does not cache its
8684     *        drawing, false otherwise
8685     */
8686    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8687        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8688    }
8689
8690    /**
8691     * Returns whether or not this View can cache its drawing or not.
8692     *
8693     * @return true if this view does not cache its drawing, false otherwise
8694     */
8695    @ViewDebug.ExportedProperty(category = "drawing")
8696    public boolean willNotCacheDrawing() {
8697        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8698    }
8699
8700    /**
8701     * Indicates whether this view reacts to click events or not.
8702     *
8703     * @return true if the view is clickable, false otherwise
8704     *
8705     * @see #setClickable(boolean)
8706     * @attr ref android.R.styleable#View_clickable
8707     */
8708    @ViewDebug.ExportedProperty
8709    public boolean isClickable() {
8710        return (mViewFlags & CLICKABLE) == CLICKABLE;
8711    }
8712
8713    /**
8714     * Enables or disables click events for this view. When a view
8715     * is clickable it will change its state to "pressed" on every click.
8716     * Subclasses should set the view clickable to visually react to
8717     * user's clicks.
8718     *
8719     * @param clickable true to make the view clickable, false otherwise
8720     *
8721     * @see #isClickable()
8722     * @attr ref android.R.styleable#View_clickable
8723     */
8724    public void setClickable(boolean clickable) {
8725        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8726    }
8727
8728    /**
8729     * Indicates whether this view reacts to long click events or not.
8730     *
8731     * @return true if the view is long clickable, false otherwise
8732     *
8733     * @see #setLongClickable(boolean)
8734     * @attr ref android.R.styleable#View_longClickable
8735     */
8736    public boolean isLongClickable() {
8737        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8738    }
8739
8740    /**
8741     * Enables or disables long click events for this view. When a view is long
8742     * clickable it reacts to the user holding down the button for a longer
8743     * duration than a tap. This event can either launch the listener or a
8744     * context menu.
8745     *
8746     * @param longClickable true to make the view long clickable, false otherwise
8747     * @see #isLongClickable()
8748     * @attr ref android.R.styleable#View_longClickable
8749     */
8750    public void setLongClickable(boolean longClickable) {
8751        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8752    }
8753
8754    /**
8755     * Indicates whether this view reacts to context clicks or not.
8756     *
8757     * @return true if the view is context clickable, false otherwise
8758     * @see #setContextClickable(boolean)
8759     * @attr ref android.R.styleable#View_contextClickable
8760     */
8761    public boolean isContextClickable() {
8762        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8763    }
8764
8765    /**
8766     * Enables or disables context clicking for this view. This event can launch the listener.
8767     *
8768     * @param contextClickable true to make the view react to a context click, false otherwise
8769     * @see #isContextClickable()
8770     * @attr ref android.R.styleable#View_contextClickable
8771     */
8772    public void setContextClickable(boolean contextClickable) {
8773        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8774    }
8775
8776    /**
8777     * Sets the pressed state for this view and provides a touch coordinate for
8778     * animation hinting.
8779     *
8780     * @param pressed Pass true to set the View's internal state to "pressed",
8781     *            or false to reverts the View's internal state from a
8782     *            previously set "pressed" state.
8783     * @param x The x coordinate of the touch that caused the press
8784     * @param y The y coordinate of the touch that caused the press
8785     */
8786    private void setPressed(boolean pressed, float x, float y) {
8787        if (pressed) {
8788            drawableHotspotChanged(x, y);
8789        }
8790
8791        setPressed(pressed);
8792    }
8793
8794    /**
8795     * Sets the pressed state for this view.
8796     *
8797     * @see #isClickable()
8798     * @see #setClickable(boolean)
8799     *
8800     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8801     *        the View's internal state from a previously set "pressed" state.
8802     */
8803    public void setPressed(boolean pressed) {
8804        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8805
8806        if (pressed) {
8807            mPrivateFlags |= PFLAG_PRESSED;
8808        } else {
8809            mPrivateFlags &= ~PFLAG_PRESSED;
8810        }
8811
8812        if (needsRefresh) {
8813            refreshDrawableState();
8814        }
8815        dispatchSetPressed(pressed);
8816    }
8817
8818    /**
8819     * Dispatch setPressed to all of this View's children.
8820     *
8821     * @see #setPressed(boolean)
8822     *
8823     * @param pressed The new pressed state
8824     */
8825    protected void dispatchSetPressed(boolean pressed) {
8826    }
8827
8828    /**
8829     * Indicates whether the view is currently in pressed state. Unless
8830     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8831     * the pressed state.
8832     *
8833     * @see #setPressed(boolean)
8834     * @see #isClickable()
8835     * @see #setClickable(boolean)
8836     *
8837     * @return true if the view is currently pressed, false otherwise
8838     */
8839    @ViewDebug.ExportedProperty
8840    public boolean isPressed() {
8841        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8842    }
8843
8844    /**
8845     * @hide
8846     * Indicates whether this view will participate in data collection through
8847     * {@link ViewStructure}.  If true, it will not provide any data
8848     * for itself or its children.  If false, the normal data collection will be allowed.
8849     *
8850     * @return Returns false if assist data collection is not blocked, else true.
8851     *
8852     * @see #setAssistBlocked(boolean)
8853     * @attr ref android.R.styleable#View_assistBlocked
8854     */
8855    public boolean isAssistBlocked() {
8856        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8857    }
8858
8859    /**
8860     * @hide
8861     * Indicates whether this view will participate in data collection through
8862     * {@link ViewStructure} for auto-fill purposes.
8863     *
8864     * <p>If {@code true}, it will not provide any data for itself or its children.
8865     * <p>If {@code false}, the normal data collection will be allowed.
8866     *
8867     * @return Returns {@code false} if assist data collection for auto-fill is not blocked,
8868     * else {@code true}.
8869     *
8870     * TODO(b/33197203): update / remove javadoc tags below
8871     * @see #setAssistBlocked(boolean)
8872     * @attr ref android.R.styleable#View_assistBlocked
8873     */
8874    public boolean isAutoFillBlocked() {
8875        return false; // TODO(b/33197203): properly implement it
8876    }
8877
8878    /**
8879     * @hide
8880     * Controls whether assist data collection from this view and its children is enabled
8881     * (that is, whether {@link #onProvideStructure} and
8882     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8883     * allowing normal assist collection.  Setting this to false will disable assist collection.
8884     *
8885     * @param enabled Set to true to <em>disable</em> assist data collection, or false
8886     * (the default) to allow it.
8887     *
8888     * @see #isAssistBlocked()
8889     * @see #onProvideStructure
8890     * @see #onProvideVirtualStructure
8891     * @attr ref android.R.styleable#View_assistBlocked
8892     */
8893    public void setAssistBlocked(boolean enabled) {
8894        if (enabled) {
8895            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8896        } else {
8897            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8898        }
8899    }
8900
8901    /**
8902     * Indicates whether this view will save its state (that is,
8903     * whether its {@link #onSaveInstanceState} method will be called).
8904     *
8905     * @return Returns true if the view state saving is enabled, else false.
8906     *
8907     * @see #setSaveEnabled(boolean)
8908     * @attr ref android.R.styleable#View_saveEnabled
8909     */
8910    public boolean isSaveEnabled() {
8911        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8912    }
8913
8914    /**
8915     * Controls whether the saving of this view's state is
8916     * enabled (that is, whether its {@link #onSaveInstanceState} method
8917     * will be called).  Note that even if freezing is enabled, the
8918     * view still must have an id assigned to it (via {@link #setId(int)})
8919     * for its state to be saved.  This flag can only disable the
8920     * saving of this view; any child views may still have their state saved.
8921     *
8922     * @param enabled Set to false to <em>disable</em> state saving, or true
8923     * (the default) to allow it.
8924     *
8925     * @see #isSaveEnabled()
8926     * @see #setId(int)
8927     * @see #onSaveInstanceState()
8928     * @attr ref android.R.styleable#View_saveEnabled
8929     */
8930    public void setSaveEnabled(boolean enabled) {
8931        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8932    }
8933
8934    /**
8935     * Gets whether the framework should discard touches when the view's
8936     * window is obscured by another visible window.
8937     * Refer to the {@link View} security documentation for more details.
8938     *
8939     * @return True if touch filtering is enabled.
8940     *
8941     * @see #setFilterTouchesWhenObscured(boolean)
8942     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8943     */
8944    @ViewDebug.ExportedProperty
8945    public boolean getFilterTouchesWhenObscured() {
8946        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8947    }
8948
8949    /**
8950     * Sets whether the framework should discard touches when the view's
8951     * window is obscured by another visible window.
8952     * Refer to the {@link View} security documentation for more details.
8953     *
8954     * @param enabled True if touch filtering should be enabled.
8955     *
8956     * @see #getFilterTouchesWhenObscured
8957     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8958     */
8959    public void setFilterTouchesWhenObscured(boolean enabled) {
8960        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8961                FILTER_TOUCHES_WHEN_OBSCURED);
8962    }
8963
8964    /**
8965     * Indicates whether the entire hierarchy under this view will save its
8966     * state when a state saving traversal occurs from its parent.  The default
8967     * is true; if false, these views will not be saved unless
8968     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8969     *
8970     * @return Returns true if the view state saving from parent is enabled, else false.
8971     *
8972     * @see #setSaveFromParentEnabled(boolean)
8973     */
8974    public boolean isSaveFromParentEnabled() {
8975        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8976    }
8977
8978    /**
8979     * Controls whether the entire hierarchy under this view will save its
8980     * state when a state saving traversal occurs from its parent.  The default
8981     * is true; if false, these views will not be saved unless
8982     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8983     *
8984     * @param enabled Set to false to <em>disable</em> state saving, or true
8985     * (the default) to allow it.
8986     *
8987     * @see #isSaveFromParentEnabled()
8988     * @see #setId(int)
8989     * @see #onSaveInstanceState()
8990     */
8991    public void setSaveFromParentEnabled(boolean enabled) {
8992        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8993    }
8994
8995
8996    /**
8997     * Returns whether this View is able to take focus.
8998     *
8999     * @return True if this view can take focus, or false otherwise.
9000     * @attr ref android.R.styleable#View_focusable
9001     */
9002    @ViewDebug.ExportedProperty(category = "focus")
9003    public final boolean isFocusable() {
9004        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
9005    }
9006
9007    /**
9008     * When a view is focusable, it may not want to take focus when in touch mode.
9009     * For example, a button would like focus when the user is navigating via a D-pad
9010     * so that the user can click on it, but once the user starts touching the screen,
9011     * the button shouldn't take focus
9012     * @return Whether the view is focusable in touch mode.
9013     * @attr ref android.R.styleable#View_focusableInTouchMode
9014     */
9015    @ViewDebug.ExportedProperty
9016    public final boolean isFocusableInTouchMode() {
9017        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
9018    }
9019
9020    /**
9021     * Find the nearest view in the specified direction that can take focus.
9022     * This does not actually give focus to that view.
9023     *
9024     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9025     *
9026     * @return The nearest focusable in the specified direction, or null if none
9027     *         can be found.
9028     */
9029    public View focusSearch(@FocusRealDirection int direction) {
9030        if (mParent != null) {
9031            return mParent.focusSearch(this, direction);
9032        } else {
9033            return null;
9034        }
9035    }
9036
9037    /**
9038     * Returns whether this View is a root of a keyboard navigation cluster.
9039     *
9040     * @return True if this view is a root of a cluster, or false otherwise.
9041     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9042     */
9043    @ViewDebug.ExportedProperty(category = "keyboardNavigationCluster")
9044    public final boolean isKeyboardNavigationCluster() {
9045        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
9046    }
9047
9048    /**
9049     * Set whether this view is a root of a keyboard navigation cluster.
9050     *
9051     * @param isCluster If true, this view is a root of a cluster.
9052     *
9053     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9054     */
9055    public void setKeyboardNavigationCluster(boolean isCluster) {
9056        if (isCluster) {
9057            mPrivateFlags3 |= PFLAG3_CLUSTER;
9058        } else {
9059            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
9060        }
9061    }
9062
9063    /**
9064     * Returns whether this View is a root of a keyboard navigation section.
9065     *
9066     * @return True if this view is a root of a section, or false otherwise.
9067     * @attr ref android.R.styleable#View_keyboardNavigationSection
9068     */
9069    @ViewDebug.ExportedProperty(category = "keyboardNavigationSection")
9070    public final boolean isKeyboardNavigationSection() {
9071        return (mPrivateFlags3 & PFLAG3_SECTION) != 0;
9072    }
9073
9074    /**
9075     * Set whether this view is a root of a keyboard navigation section.
9076     *
9077     * @param isSection If true, this view is a root of a section.
9078     *
9079     * @attr ref android.R.styleable#View_keyboardNavigationSection
9080     */
9081    public void setKeyboardNavigationSection(boolean isSection) {
9082        if (isSection) {
9083            mPrivateFlags3 |= PFLAG3_SECTION;
9084        } else {
9085            mPrivateFlags3 &= ~PFLAG3_SECTION;
9086        }
9087    }
9088
9089    /**
9090     * Find the nearest keyboard navigation cluster in the specified direction.
9091     * This does not actually give focus to that cluster.
9092     *
9093     * @param direction Direction to look
9094     *
9095     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
9096     *         can be found
9097     */
9098    public View keyboardNavigationClusterSearch(int direction) {
9099        if (mParent != null) {
9100            final View currentCluster = isKeyboardNavigationCluster() ? this : null;
9101            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
9102        } else {
9103            return null;
9104        }
9105    }
9106
9107    /**
9108     * This method is the last chance for the focused view and its ancestors to
9109     * respond to an arrow key. This is called when the focused view did not
9110     * consume the key internally, nor could the view system find a new view in
9111     * the requested direction to give focus to.
9112     *
9113     * @param focused The currently focused view.
9114     * @param direction The direction focus wants to move. One of FOCUS_UP,
9115     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
9116     * @return True if the this view consumed this unhandled move.
9117     */
9118    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
9119        return false;
9120    }
9121
9122    /**
9123     * If a user manually specified the next view id for a particular direction,
9124     * use the root to look up the view.
9125     * @param root The root view of the hierarchy containing this view.
9126     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
9127     * or FOCUS_BACKWARD.
9128     * @return The user specified next view, or null if there is none.
9129     */
9130    View findUserSetNextFocus(View root, @FocusDirection int direction) {
9131        switch (direction) {
9132            case FOCUS_LEFT:
9133                if (mNextFocusLeftId == View.NO_ID) return null;
9134                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
9135            case FOCUS_RIGHT:
9136                if (mNextFocusRightId == View.NO_ID) return null;
9137                return findViewInsideOutShouldExist(root, mNextFocusRightId);
9138            case FOCUS_UP:
9139                if (mNextFocusUpId == View.NO_ID) return null;
9140                return findViewInsideOutShouldExist(root, mNextFocusUpId);
9141            case FOCUS_DOWN:
9142                if (mNextFocusDownId == View.NO_ID) return null;
9143                return findViewInsideOutShouldExist(root, mNextFocusDownId);
9144            case FOCUS_FORWARD:
9145                if (mNextFocusForwardId == View.NO_ID) return null;
9146                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
9147            case FOCUS_BACKWARD: {
9148                if (mID == View.NO_ID) return null;
9149                final int id = mID;
9150                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
9151                    @Override
9152                    public boolean apply(View t) {
9153                        return t.mNextFocusForwardId == id;
9154                    }
9155                });
9156            }
9157        }
9158        return null;
9159    }
9160
9161    private View findViewInsideOutShouldExist(View root, int id) {
9162        if (mMatchIdPredicate == null) {
9163            mMatchIdPredicate = new MatchIdPredicate();
9164        }
9165        mMatchIdPredicate.mId = id;
9166        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
9167        if (result == null) {
9168            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
9169        }
9170        return result;
9171    }
9172
9173    /**
9174     * Find and return all focusable views that are descendants of this view,
9175     * possibly including this view if it is focusable itself.
9176     *
9177     * @param direction The direction of the focus
9178     * @return A list of focusable views
9179     */
9180    public ArrayList<View> getFocusables(@FocusDirection int direction) {
9181        ArrayList<View> result = new ArrayList<View>(24);
9182        addFocusables(result, direction);
9183        return result;
9184    }
9185
9186    /**
9187     * Add any focusable views that are descendants of this view (possibly
9188     * including this view if it is focusable itself) to views.  If we are in touch mode,
9189     * only add views that are also focusable in touch mode.
9190     *
9191     * @param views Focusable views found so far
9192     * @param direction The direction of the focus
9193     */
9194    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
9195        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
9196    }
9197
9198    /**
9199     * Adds any focusable views that are descendants of this view (possibly
9200     * including this view if it is focusable itself) to views. This method
9201     * adds all focusable views regardless if we are in touch mode or
9202     * only views focusable in touch mode if we are in touch mode or
9203     * only views that can take accessibility focus if accessibility is enabled
9204     * depending on the focusable mode parameter.
9205     *
9206     * @param views Focusable views found so far or null if all we are interested is
9207     *        the number of focusables.
9208     * @param direction The direction of the focus.
9209     * @param focusableMode The type of focusables to be added.
9210     *
9211     * @see #FOCUSABLES_ALL
9212     * @see #FOCUSABLES_TOUCH_MODE
9213     */
9214    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
9215            @FocusableMode int focusableMode) {
9216        if (views == null) {
9217            return;
9218        }
9219        if (!isFocusable()) {
9220            return;
9221        }
9222        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
9223                && !isFocusableInTouchMode()) {
9224            return;
9225        }
9226        views.add(this);
9227    }
9228
9229    /**
9230     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
9231     * including this view if it is a cluster root itself) to views.
9232     *
9233     * @param views Cluster roots found so far
9234     * @param direction Direction to look
9235     */
9236    public void addKeyboardNavigationClusters(@NonNull Collection<View> views, int direction) {
9237        if (!isKeyboardNavigationCluster()) {
9238            return;
9239        }
9240        views.add(this);
9241    }
9242
9243    /**
9244     * Finds the Views that contain given text. The containment is case insensitive.
9245     * The search is performed by either the text that the View renders or the content
9246     * description that describes the view for accessibility purposes and the view does
9247     * not render or both. Clients can specify how the search is to be performed via
9248     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
9249     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
9250     *
9251     * @param outViews The output list of matching Views.
9252     * @param searched The text to match against.
9253     *
9254     * @see #FIND_VIEWS_WITH_TEXT
9255     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
9256     * @see #setContentDescription(CharSequence)
9257     */
9258    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
9259            @FindViewFlags int flags) {
9260        if (getAccessibilityNodeProvider() != null) {
9261            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
9262                outViews.add(this);
9263            }
9264        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
9265                && (searched != null && searched.length() > 0)
9266                && (mContentDescription != null && mContentDescription.length() > 0)) {
9267            String searchedLowerCase = searched.toString().toLowerCase();
9268            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
9269            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
9270                outViews.add(this);
9271            }
9272        }
9273    }
9274
9275    /**
9276     * Find and return all touchable views that are descendants of this view,
9277     * possibly including this view if it is touchable itself.
9278     *
9279     * @return A list of touchable views
9280     */
9281    public ArrayList<View> getTouchables() {
9282        ArrayList<View> result = new ArrayList<View>();
9283        addTouchables(result);
9284        return result;
9285    }
9286
9287    /**
9288     * Add any touchable views that are descendants of this view (possibly
9289     * including this view if it is touchable itself) to views.
9290     *
9291     * @param views Touchable views found so far
9292     */
9293    public void addTouchables(ArrayList<View> views) {
9294        final int viewFlags = mViewFlags;
9295
9296        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
9297                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
9298                && (viewFlags & ENABLED_MASK) == ENABLED) {
9299            views.add(this);
9300        }
9301    }
9302
9303    /**
9304     * Returns whether this View is accessibility focused.
9305     *
9306     * @return True if this View is accessibility focused.
9307     */
9308    public boolean isAccessibilityFocused() {
9309        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
9310    }
9311
9312    /**
9313     * Call this to try to give accessibility focus to this view.
9314     *
9315     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
9316     * returns false or the view is no visible or the view already has accessibility
9317     * focus.
9318     *
9319     * See also {@link #focusSearch(int)}, which is what you call to say that you
9320     * have focus, and you want your parent to look for the next one.
9321     *
9322     * @return Whether this view actually took accessibility focus.
9323     *
9324     * @hide
9325     */
9326    public boolean requestAccessibilityFocus() {
9327        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
9328        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
9329            return false;
9330        }
9331        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9332            return false;
9333        }
9334        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
9335            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
9336            ViewRootImpl viewRootImpl = getViewRootImpl();
9337            if (viewRootImpl != null) {
9338                viewRootImpl.setAccessibilityFocus(this, null);
9339            }
9340            invalidate();
9341            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
9342            return true;
9343        }
9344        return false;
9345    }
9346
9347    /**
9348     * Call this to try to clear accessibility focus of this view.
9349     *
9350     * See also {@link #focusSearch(int)}, which is what you call to say that you
9351     * have focus, and you want your parent to look for the next one.
9352     *
9353     * @hide
9354     */
9355    public void clearAccessibilityFocus() {
9356        clearAccessibilityFocusNoCallbacks(0);
9357
9358        // Clear the global reference of accessibility focus if this view or
9359        // any of its descendants had accessibility focus. This will NOT send
9360        // an event or update internal state if focus is cleared from a
9361        // descendant view, which may leave views in inconsistent states.
9362        final ViewRootImpl viewRootImpl = getViewRootImpl();
9363        if (viewRootImpl != null) {
9364            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
9365            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9366                viewRootImpl.setAccessibilityFocus(null, null);
9367            }
9368        }
9369    }
9370
9371    private void sendAccessibilityHoverEvent(int eventType) {
9372        // Since we are not delivering to a client accessibility events from not
9373        // important views (unless the clinet request that) we need to fire the
9374        // event from the deepest view exposed to the client. As a consequence if
9375        // the user crosses a not exposed view the client will see enter and exit
9376        // of the exposed predecessor followed by and enter and exit of that same
9377        // predecessor when entering and exiting the not exposed descendant. This
9378        // is fine since the client has a clear idea which view is hovered at the
9379        // price of a couple more events being sent. This is a simple and
9380        // working solution.
9381        View source = this;
9382        while (true) {
9383            if (source.includeForAccessibility()) {
9384                source.sendAccessibilityEvent(eventType);
9385                return;
9386            }
9387            ViewParent parent = source.getParent();
9388            if (parent instanceof View) {
9389                source = (View) parent;
9390            } else {
9391                return;
9392            }
9393        }
9394    }
9395
9396    /**
9397     * Clears accessibility focus without calling any callback methods
9398     * normally invoked in {@link #clearAccessibilityFocus()}. This method
9399     * is used separately from that one for clearing accessibility focus when
9400     * giving this focus to another view.
9401     *
9402     * @param action The action, if any, that led to focus being cleared. Set to
9403     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
9404     * the window.
9405     */
9406    void clearAccessibilityFocusNoCallbacks(int action) {
9407        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
9408            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
9409            invalidate();
9410            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9411                AccessibilityEvent event = AccessibilityEvent.obtain(
9412                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
9413                event.setAction(action);
9414                if (mAccessibilityDelegate != null) {
9415                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
9416                } else {
9417                    sendAccessibilityEventUnchecked(event);
9418                }
9419            }
9420        }
9421    }
9422
9423    /**
9424     * Call this to try to give focus to a specific view or to one of its
9425     * descendants.
9426     *
9427     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9428     * false), or if it is focusable and it is not focusable in touch mode
9429     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9430     *
9431     * See also {@link #focusSearch(int)}, which is what you call to say that you
9432     * have focus, and you want your parent to look for the next one.
9433     *
9434     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
9435     * {@link #FOCUS_DOWN} and <code>null</code>.
9436     *
9437     * @return Whether this view or one of its descendants actually took focus.
9438     */
9439    public final boolean requestFocus() {
9440        return requestFocus(View.FOCUS_DOWN);
9441    }
9442
9443    /**
9444     * Call this to try to give focus to a specific view or to one of its
9445     * descendants and give it a hint about what direction focus is heading.
9446     *
9447     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9448     * false), or if it is focusable and it is not focusable in touch mode
9449     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9450     *
9451     * See also {@link #focusSearch(int)}, which is what you call to say that you
9452     * have focus, and you want your parent to look for the next one.
9453     *
9454     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
9455     * <code>null</code> set for the previously focused rectangle.
9456     *
9457     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9458     * @return Whether this view or one of its descendants actually took focus.
9459     */
9460    public final boolean requestFocus(int direction) {
9461        return requestFocus(direction, null);
9462    }
9463
9464    /**
9465     * Call this to try to give focus to a specific view or to one of its descendants
9466     * and give it hints about the direction and a specific rectangle that the focus
9467     * is coming from.  The rectangle can help give larger views a finer grained hint
9468     * about where focus is coming from, and therefore, where to show selection, or
9469     * forward focus change internally.
9470     *
9471     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9472     * false), or if it is focusable and it is not focusable in touch mode
9473     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9474     *
9475     * A View will not take focus if it is not visible.
9476     *
9477     * A View will not take focus if one of its parents has
9478     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
9479     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
9480     *
9481     * See also {@link #focusSearch(int)}, which is what you call to say that you
9482     * have focus, and you want your parent to look for the next one.
9483     *
9484     * You may wish to override this method if your custom {@link View} has an internal
9485     * {@link View} that it wishes to forward the request to.
9486     *
9487     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9488     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
9489     *        to give a finer grained hint about where focus is coming from.  May be null
9490     *        if there is no hint.
9491     * @return Whether this view or one of its descendants actually took focus.
9492     */
9493    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
9494        return requestFocusNoSearch(direction, previouslyFocusedRect);
9495    }
9496
9497    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
9498        // need to be focusable
9499        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
9500                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9501            return false;
9502        }
9503
9504        // need to be focusable in touch mode if in touch mode
9505        if (isInTouchMode() &&
9506            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
9507               return false;
9508        }
9509
9510        // need to not have any parents blocking us
9511        if (hasAncestorThatBlocksDescendantFocus()) {
9512            return false;
9513        }
9514
9515        handleFocusGainInternal(direction, previouslyFocusedRect);
9516        return true;
9517    }
9518
9519    /**
9520     * Call this to try to give focus to a specific view or to one of its descendants. This is a
9521     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
9522     * touch mode to request focus when they are touched.
9523     *
9524     * @return Whether this view or one of its descendants actually took focus.
9525     *
9526     * @see #isInTouchMode()
9527     *
9528     */
9529    public final boolean requestFocusFromTouch() {
9530        // Leave touch mode if we need to
9531        if (isInTouchMode()) {
9532            ViewRootImpl viewRoot = getViewRootImpl();
9533            if (viewRoot != null) {
9534                viewRoot.ensureTouchMode(false);
9535            }
9536        }
9537        return requestFocus(View.FOCUS_DOWN);
9538    }
9539
9540    /**
9541     * @return Whether any ancestor of this view blocks descendant focus.
9542     */
9543    private boolean hasAncestorThatBlocksDescendantFocus() {
9544        final boolean focusableInTouchMode = isFocusableInTouchMode();
9545        ViewParent ancestor = mParent;
9546        while (ancestor instanceof ViewGroup) {
9547            final ViewGroup vgAncestor = (ViewGroup) ancestor;
9548            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
9549                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
9550                return true;
9551            } else {
9552                ancestor = vgAncestor.getParent();
9553            }
9554        }
9555        return false;
9556    }
9557
9558    /**
9559     * Gets the mode for determining whether this View is important for accessibility.
9560     * A view is important for accessibility if it fires accessibility events and if it
9561     * is reported to accessibility services that query the screen.
9562     *
9563     * @return The mode for determining whether a view is important for accessibility, one
9564     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
9565     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
9566     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
9567     *
9568     * @attr ref android.R.styleable#View_importantForAccessibility
9569     *
9570     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9571     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9572     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9573     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9574     */
9575    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
9576            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
9577            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
9578            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
9579            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
9580                    to = "noHideDescendants")
9581        })
9582    public int getImportantForAccessibility() {
9583        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9584                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9585    }
9586
9587    /**
9588     * Sets the live region mode for this view. This indicates to accessibility
9589     * services whether they should automatically notify the user about changes
9590     * to the view's content description or text, or to the content descriptions
9591     * or text of the view's children (where applicable).
9592     * <p>
9593     * For example, in a login screen with a TextView that displays an "incorrect
9594     * password" notification, that view should be marked as a live region with
9595     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9596     * <p>
9597     * To disable change notifications for this view, use
9598     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
9599     * mode for most views.
9600     * <p>
9601     * To indicate that the user should be notified of changes, use
9602     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9603     * <p>
9604     * If the view's changes should interrupt ongoing speech and notify the user
9605     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
9606     *
9607     * @param mode The live region mode for this view, one of:
9608     *        <ul>
9609     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
9610     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
9611     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
9612     *        </ul>
9613     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9614     */
9615    public void setAccessibilityLiveRegion(int mode) {
9616        if (mode != getAccessibilityLiveRegion()) {
9617            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9618            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
9619                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9620            notifyViewAccessibilityStateChangedIfNeeded(
9621                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9622        }
9623    }
9624
9625    /**
9626     * Gets the live region mode for this View.
9627     *
9628     * @return The live region mode for the view.
9629     *
9630     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9631     *
9632     * @see #setAccessibilityLiveRegion(int)
9633     */
9634    public int getAccessibilityLiveRegion() {
9635        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
9636                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
9637    }
9638
9639    /**
9640     * Sets how to determine whether this view is important for accessibility
9641     * which is if it fires accessibility events and if it is reported to
9642     * accessibility services that query the screen.
9643     *
9644     * @param mode How to determine whether this view is important for accessibility.
9645     *
9646     * @attr ref android.R.styleable#View_importantForAccessibility
9647     *
9648     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9649     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9650     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9651     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9652     */
9653    public void setImportantForAccessibility(int mode) {
9654        final int oldMode = getImportantForAccessibility();
9655        if (mode != oldMode) {
9656            final boolean hideDescendants =
9657                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
9658
9659            // If this node or its descendants are no longer important, try to
9660            // clear accessibility focus.
9661            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
9662                final View focusHost = findAccessibilityFocusHost(hideDescendants);
9663                if (focusHost != null) {
9664                    focusHost.clearAccessibilityFocus();
9665                }
9666            }
9667
9668            // If we're moving between AUTO and another state, we might not need
9669            // to send a subtree changed notification. We'll store the computed
9670            // importance, since we'll need to check it later to make sure.
9671            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
9672                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
9673            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
9674            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9675            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
9676                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9677            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
9678                notifySubtreeAccessibilityStateChangedIfNeeded();
9679            } else {
9680                notifyViewAccessibilityStateChangedIfNeeded(
9681                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9682            }
9683        }
9684    }
9685
9686    /**
9687     * Returns the view within this view's hierarchy that is hosting
9688     * accessibility focus.
9689     *
9690     * @param searchDescendants whether to search for focus in descendant views
9691     * @return the view hosting accessibility focus, or {@code null}
9692     */
9693    private View findAccessibilityFocusHost(boolean searchDescendants) {
9694        if (isAccessibilityFocusedViewOrHost()) {
9695            return this;
9696        }
9697
9698        if (searchDescendants) {
9699            final ViewRootImpl viewRoot = getViewRootImpl();
9700            if (viewRoot != null) {
9701                final View focusHost = viewRoot.getAccessibilityFocusedHost();
9702                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9703                    return focusHost;
9704                }
9705            }
9706        }
9707
9708        return null;
9709    }
9710
9711    /**
9712     * Computes whether this view should be exposed for accessibility. In
9713     * general, views that are interactive or provide information are exposed
9714     * while views that serve only as containers are hidden.
9715     * <p>
9716     * If an ancestor of this view has importance
9717     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
9718     * returns <code>false</code>.
9719     * <p>
9720     * Otherwise, the value is computed according to the view's
9721     * {@link #getImportantForAccessibility()} value:
9722     * <ol>
9723     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
9724     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
9725     * </code>
9726     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
9727     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
9728     * view satisfies any of the following:
9729     * <ul>
9730     * <li>Is actionable, e.g. {@link #isClickable()},
9731     * {@link #isLongClickable()}, or {@link #isFocusable()}
9732     * <li>Has an {@link AccessibilityDelegate}
9733     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
9734     * {@link OnKeyListener}, etc.
9735     * <li>Is an accessibility live region, e.g.
9736     * {@link #getAccessibilityLiveRegion()} is not
9737     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
9738     * </ul>
9739     * </ol>
9740     *
9741     * @return Whether the view is exposed for accessibility.
9742     * @see #setImportantForAccessibility(int)
9743     * @see #getImportantForAccessibility()
9744     */
9745    public boolean isImportantForAccessibility() {
9746        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9747                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9748        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
9749                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9750            return false;
9751        }
9752
9753        // Check parent mode to ensure we're not hidden.
9754        ViewParent parent = mParent;
9755        while (parent instanceof View) {
9756            if (((View) parent).getImportantForAccessibility()
9757                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9758                return false;
9759            }
9760            parent = parent.getParent();
9761        }
9762
9763        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
9764                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
9765                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
9766    }
9767
9768    /**
9769     * Gets the parent for accessibility purposes. Note that the parent for
9770     * accessibility is not necessary the immediate parent. It is the first
9771     * predecessor that is important for accessibility.
9772     *
9773     * @return The parent for accessibility purposes.
9774     */
9775    public ViewParent getParentForAccessibility() {
9776        if (mParent instanceof View) {
9777            View parentView = (View) mParent;
9778            if (parentView.includeForAccessibility()) {
9779                return mParent;
9780            } else {
9781                return mParent.getParentForAccessibility();
9782            }
9783        }
9784        return null;
9785    }
9786
9787    /**
9788     * Adds the children of this View relevant for accessibility to the given list
9789     * as output. Since some Views are not important for accessibility the added
9790     * child views are not necessarily direct children of this view, rather they are
9791     * the first level of descendants important for accessibility.
9792     *
9793     * @param outChildren The output list that will receive children for accessibility.
9794     */
9795    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
9796
9797    }
9798
9799    /**
9800     * Whether to regard this view for accessibility. A view is regarded for
9801     * accessibility if it is important for accessibility or the querying
9802     * accessibility service has explicitly requested that view not
9803     * important for accessibility are regarded.
9804     *
9805     * @return Whether to regard the view for accessibility.
9806     *
9807     * @hide
9808     */
9809    public boolean includeForAccessibility() {
9810        if (mAttachInfo != null) {
9811            return (mAttachInfo.mAccessibilityFetchFlags
9812                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
9813                    || isImportantForAccessibility();
9814        }
9815        return false;
9816    }
9817
9818    /**
9819     * Returns whether the View is considered actionable from
9820     * accessibility perspective. Such view are important for
9821     * accessibility.
9822     *
9823     * @return True if the view is actionable for accessibility.
9824     *
9825     * @hide
9826     */
9827    public boolean isActionableForAccessibility() {
9828        return (isClickable() || isLongClickable() || isFocusable());
9829    }
9830
9831    /**
9832     * Returns whether the View has registered callbacks which makes it
9833     * important for accessibility.
9834     *
9835     * @return True if the view is actionable for accessibility.
9836     */
9837    private boolean hasListenersForAccessibility() {
9838        ListenerInfo info = getListenerInfo();
9839        return mTouchDelegate != null || info.mOnKeyListener != null
9840                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
9841                || info.mOnHoverListener != null || info.mOnDragListener != null;
9842    }
9843
9844    /**
9845     * Notifies that the accessibility state of this view changed. The change
9846     * is local to this view and does not represent structural changes such
9847     * as children and parent. For example, the view became focusable. The
9848     * notification is at at most once every
9849     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9850     * to avoid unnecessary load to the system. Also once a view has a pending
9851     * notification this method is a NOP until the notification has been sent.
9852     *
9853     * @hide
9854     */
9855    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
9856        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9857            return;
9858        }
9859        if (mSendViewStateChangedAccessibilityEvent == null) {
9860            mSendViewStateChangedAccessibilityEvent =
9861                    new SendViewStateChangedAccessibilityEvent();
9862        }
9863        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9864    }
9865
9866    /**
9867     * Notifies that the accessibility state of this view changed. The change
9868     * is *not* local to this view and does represent structural changes such
9869     * as children and parent. For example, the view size changed. The
9870     * notification is at at most once every
9871     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9872     * to avoid unnecessary load to the system. Also once a view has a pending
9873     * notification this method is a NOP until the notification has been sent.
9874     *
9875     * @hide
9876     */
9877    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9878        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9879            return;
9880        }
9881        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9882            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9883            if (mParent != null) {
9884                try {
9885                    mParent.notifySubtreeAccessibilityStateChanged(
9886                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9887                } catch (AbstractMethodError e) {
9888                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9889                            " does not fully implement ViewParent", e);
9890                }
9891            }
9892        }
9893    }
9894
9895    /**
9896     * Change the visibility of the View without triggering any other changes. This is
9897     * important for transitions, where visibility changes should not adjust focus or
9898     * trigger a new layout. This is only used when the visibility has already been changed
9899     * and we need a transient value during an animation. When the animation completes,
9900     * the original visibility value is always restored.
9901     *
9902     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9903     * @hide
9904     */
9905    public void setTransitionVisibility(@Visibility int visibility) {
9906        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9907    }
9908
9909    /**
9910     * Reset the flag indicating the accessibility state of the subtree rooted
9911     * at this view changed.
9912     */
9913    void resetSubtreeAccessibilityStateChanged() {
9914        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9915    }
9916
9917    /**
9918     * Report an accessibility action to this view's parents for delegated processing.
9919     *
9920     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9921     * call this method to delegate an accessibility action to a supporting parent. If the parent
9922     * returns true from its
9923     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9924     * method this method will return true to signify that the action was consumed.</p>
9925     *
9926     * <p>This method is useful for implementing nested scrolling child views. If
9927     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9928     * a custom view implementation may invoke this method to allow a parent to consume the
9929     * scroll first. If this method returns true the custom view should skip its own scrolling
9930     * behavior.</p>
9931     *
9932     * @param action Accessibility action to delegate
9933     * @param arguments Optional action arguments
9934     * @return true if the action was consumed by a parent
9935     */
9936    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9937        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9938            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9939                return true;
9940            }
9941        }
9942        return false;
9943    }
9944
9945    /**
9946     * Performs the specified accessibility action on the view. For
9947     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9948     * <p>
9949     * If an {@link AccessibilityDelegate} has been specified via calling
9950     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9951     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9952     * is responsible for handling this call.
9953     * </p>
9954     *
9955     * <p>The default implementation will delegate
9956     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9957     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9958     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9959     *
9960     * @param action The action to perform.
9961     * @param arguments Optional action arguments.
9962     * @return Whether the action was performed.
9963     */
9964    public boolean performAccessibilityAction(int action, Bundle arguments) {
9965      if (mAccessibilityDelegate != null) {
9966          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9967      } else {
9968          return performAccessibilityActionInternal(action, arguments);
9969      }
9970    }
9971
9972   /**
9973    * @see #performAccessibilityAction(int, Bundle)
9974    *
9975    * Note: Called from the default {@link AccessibilityDelegate}.
9976    *
9977    * @hide
9978    */
9979    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9980        if (isNestedScrollingEnabled()
9981                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9982                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9983                || action == R.id.accessibilityActionScrollUp
9984                || action == R.id.accessibilityActionScrollLeft
9985                || action == R.id.accessibilityActionScrollDown
9986                || action == R.id.accessibilityActionScrollRight)) {
9987            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9988                return true;
9989            }
9990        }
9991
9992        switch (action) {
9993            case AccessibilityNodeInfo.ACTION_CLICK: {
9994                if (isClickable()) {
9995                    performClick();
9996                    return true;
9997                }
9998            } break;
9999            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
10000                if (isLongClickable()) {
10001                    performLongClick();
10002                    return true;
10003                }
10004            } break;
10005            case AccessibilityNodeInfo.ACTION_FOCUS: {
10006                if (!hasFocus()) {
10007                    // Get out of touch mode since accessibility
10008                    // wants to move focus around.
10009                    getViewRootImpl().ensureTouchMode(false);
10010                    return requestFocus();
10011                }
10012            } break;
10013            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
10014                if (hasFocus()) {
10015                    clearFocus();
10016                    return !isFocused();
10017                }
10018            } break;
10019            case AccessibilityNodeInfo.ACTION_SELECT: {
10020                if (!isSelected()) {
10021                    setSelected(true);
10022                    return isSelected();
10023                }
10024            } break;
10025            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
10026                if (isSelected()) {
10027                    setSelected(false);
10028                    return !isSelected();
10029                }
10030            } break;
10031            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
10032                if (!isAccessibilityFocused()) {
10033                    return requestAccessibilityFocus();
10034                }
10035            } break;
10036            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
10037                if (isAccessibilityFocused()) {
10038                    clearAccessibilityFocus();
10039                    return true;
10040                }
10041            } break;
10042            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
10043                if (arguments != null) {
10044                    final int granularity = arguments.getInt(
10045                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10046                    final boolean extendSelection = arguments.getBoolean(
10047                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10048                    return traverseAtGranularity(granularity, true, extendSelection);
10049                }
10050            } break;
10051            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
10052                if (arguments != null) {
10053                    final int granularity = arguments.getInt(
10054                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10055                    final boolean extendSelection = arguments.getBoolean(
10056                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10057                    return traverseAtGranularity(granularity, false, extendSelection);
10058                }
10059            } break;
10060            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
10061                CharSequence text = getIterableTextForAccessibility();
10062                if (text == null) {
10063                    return false;
10064                }
10065                final int start = (arguments != null) ? arguments.getInt(
10066                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
10067                final int end = (arguments != null) ? arguments.getInt(
10068                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
10069                // Only cursor position can be specified (selection length == 0)
10070                if ((getAccessibilitySelectionStart() != start
10071                        || getAccessibilitySelectionEnd() != end)
10072                        && (start == end)) {
10073                    setAccessibilitySelection(start, end);
10074                    notifyViewAccessibilityStateChangedIfNeeded(
10075                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10076                    return true;
10077                }
10078            } break;
10079            case R.id.accessibilityActionShowOnScreen: {
10080                if (mAttachInfo != null) {
10081                    final Rect r = mAttachInfo.mTmpInvalRect;
10082                    getDrawingRect(r);
10083                    return requestRectangleOnScreen(r, true);
10084                }
10085            } break;
10086            case R.id.accessibilityActionContextClick: {
10087                if (isContextClickable()) {
10088                    performContextClick();
10089                    return true;
10090                }
10091            } break;
10092        }
10093        return false;
10094    }
10095
10096    private boolean traverseAtGranularity(int granularity, boolean forward,
10097            boolean extendSelection) {
10098        CharSequence text = getIterableTextForAccessibility();
10099        if (text == null || text.length() == 0) {
10100            return false;
10101        }
10102        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
10103        if (iterator == null) {
10104            return false;
10105        }
10106        int current = getAccessibilitySelectionEnd();
10107        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
10108            current = forward ? 0 : text.length();
10109        }
10110        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
10111        if (range == null) {
10112            return false;
10113        }
10114        final int segmentStart = range[0];
10115        final int segmentEnd = range[1];
10116        int selectionStart;
10117        int selectionEnd;
10118        if (extendSelection && isAccessibilitySelectionExtendable()) {
10119            selectionStart = getAccessibilitySelectionStart();
10120            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
10121                selectionStart = forward ? segmentStart : segmentEnd;
10122            }
10123            selectionEnd = forward ? segmentEnd : segmentStart;
10124        } else {
10125            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
10126        }
10127        setAccessibilitySelection(selectionStart, selectionEnd);
10128        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
10129                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
10130        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
10131        return true;
10132    }
10133
10134    /**
10135     * Gets the text reported for accessibility purposes.
10136     *
10137     * @return The accessibility text.
10138     *
10139     * @hide
10140     */
10141    public CharSequence getIterableTextForAccessibility() {
10142        return getContentDescription();
10143    }
10144
10145    /**
10146     * Gets whether accessibility selection can be extended.
10147     *
10148     * @return If selection is extensible.
10149     *
10150     * @hide
10151     */
10152    public boolean isAccessibilitySelectionExtendable() {
10153        return false;
10154    }
10155
10156    /**
10157     * @hide
10158     */
10159    public int getAccessibilitySelectionStart() {
10160        return mAccessibilityCursorPosition;
10161    }
10162
10163    /**
10164     * @hide
10165     */
10166    public int getAccessibilitySelectionEnd() {
10167        return getAccessibilitySelectionStart();
10168    }
10169
10170    /**
10171     * @hide
10172     */
10173    public void setAccessibilitySelection(int start, int end) {
10174        if (start ==  end && end == mAccessibilityCursorPosition) {
10175            return;
10176        }
10177        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
10178            mAccessibilityCursorPosition = start;
10179        } else {
10180            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
10181        }
10182        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
10183    }
10184
10185    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
10186            int fromIndex, int toIndex) {
10187        if (mParent == null) {
10188            return;
10189        }
10190        AccessibilityEvent event = AccessibilityEvent.obtain(
10191                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
10192        onInitializeAccessibilityEvent(event);
10193        onPopulateAccessibilityEvent(event);
10194        event.setFromIndex(fromIndex);
10195        event.setToIndex(toIndex);
10196        event.setAction(action);
10197        event.setMovementGranularity(granularity);
10198        mParent.requestSendAccessibilityEvent(this, event);
10199    }
10200
10201    /**
10202     * @hide
10203     */
10204    public TextSegmentIterator getIteratorForGranularity(int granularity) {
10205        switch (granularity) {
10206            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
10207                CharSequence text = getIterableTextForAccessibility();
10208                if (text != null && text.length() > 0) {
10209                    CharacterTextSegmentIterator iterator =
10210                        CharacterTextSegmentIterator.getInstance(
10211                                mContext.getResources().getConfiguration().locale);
10212                    iterator.initialize(text.toString());
10213                    return iterator;
10214                }
10215            } break;
10216            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
10217                CharSequence text = getIterableTextForAccessibility();
10218                if (text != null && text.length() > 0) {
10219                    WordTextSegmentIterator iterator =
10220                        WordTextSegmentIterator.getInstance(
10221                                mContext.getResources().getConfiguration().locale);
10222                    iterator.initialize(text.toString());
10223                    return iterator;
10224                }
10225            } break;
10226            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
10227                CharSequence text = getIterableTextForAccessibility();
10228                if (text != null && text.length() > 0) {
10229                    ParagraphTextSegmentIterator iterator =
10230                        ParagraphTextSegmentIterator.getInstance();
10231                    iterator.initialize(text.toString());
10232                    return iterator;
10233                }
10234            } break;
10235        }
10236        return null;
10237    }
10238
10239    /**
10240     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
10241     * and {@link #onFinishTemporaryDetach()}.
10242     *
10243     * <p>This method always returns {@code true} when called directly or indirectly from
10244     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
10245     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
10246     * <ul>
10247     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
10248     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
10249     * </ul>
10250     * </p>
10251     *
10252     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
10253     * and {@link #onFinishTemporaryDetach()}.
10254     */
10255    public final boolean isTemporarilyDetached() {
10256        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
10257    }
10258
10259    /**
10260     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
10261     * a container View.
10262     */
10263    @CallSuper
10264    public void dispatchStartTemporaryDetach() {
10265        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
10266        onStartTemporaryDetach();
10267    }
10268
10269    /**
10270     * This is called when a container is going to temporarily detach a child, with
10271     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
10272     * It will either be followed by {@link #onFinishTemporaryDetach()} or
10273     * {@link #onDetachedFromWindow()} when the container is done.
10274     */
10275    public void onStartTemporaryDetach() {
10276        removeUnsetPressCallback();
10277        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
10278    }
10279
10280    /**
10281     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
10282     * a container View.
10283     */
10284    @CallSuper
10285    public void dispatchFinishTemporaryDetach() {
10286        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
10287        onFinishTemporaryDetach();
10288        if (hasWindowFocus() && hasFocus()) {
10289            InputMethodManager.getInstance().focusIn(this);
10290        }
10291    }
10292
10293    /**
10294     * Called after {@link #onStartTemporaryDetach} when the container is done
10295     * changing the view.
10296     */
10297    public void onFinishTemporaryDetach() {
10298    }
10299
10300    /**
10301     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
10302     * for this view's window.  Returns null if the view is not currently attached
10303     * to the window.  Normally you will not need to use this directly, but
10304     * just use the standard high-level event callbacks like
10305     * {@link #onKeyDown(int, KeyEvent)}.
10306     */
10307    public KeyEvent.DispatcherState getKeyDispatcherState() {
10308        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
10309    }
10310
10311    /**
10312     * Dispatch a key event before it is processed by any input method
10313     * associated with the view hierarchy.  This can be used to intercept
10314     * key events in special situations before the IME consumes them; a
10315     * typical example would be handling the BACK key to update the application's
10316     * UI instead of allowing the IME to see it and close itself.
10317     *
10318     * @param event The key event to be dispatched.
10319     * @return True if the event was handled, false otherwise.
10320     */
10321    public boolean dispatchKeyEventPreIme(KeyEvent event) {
10322        return onKeyPreIme(event.getKeyCode(), event);
10323    }
10324
10325    /**
10326     * Dispatch a key event to the next view on the focus path. This path runs
10327     * from the top of the view tree down to the currently focused view. If this
10328     * view has focus, it will dispatch to itself. Otherwise it will dispatch
10329     * the next node down the focus path. This method also fires any key
10330     * listeners.
10331     *
10332     * @param event The key event to be dispatched.
10333     * @return True if the event was handled, false otherwise.
10334     */
10335    public boolean dispatchKeyEvent(KeyEvent event) {
10336        if (mInputEventConsistencyVerifier != null) {
10337            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
10338        }
10339
10340        // Give any attached key listener a first crack at the event.
10341        //noinspection SimplifiableIfStatement
10342        ListenerInfo li = mListenerInfo;
10343        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
10344                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
10345            return true;
10346        }
10347
10348        if (event.dispatch(this, mAttachInfo != null
10349                ? mAttachInfo.mKeyDispatchState : null, this)) {
10350            return true;
10351        }
10352
10353        if (mInputEventConsistencyVerifier != null) {
10354            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10355        }
10356        return false;
10357    }
10358
10359    /**
10360     * Dispatches a key shortcut event.
10361     *
10362     * @param event The key event to be dispatched.
10363     * @return True if the event was handled by the view, false otherwise.
10364     */
10365    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
10366        return onKeyShortcut(event.getKeyCode(), event);
10367    }
10368
10369    /**
10370     * Pass the touch screen motion event down to the target view, or this
10371     * view if it is the target.
10372     *
10373     * @param event The motion event to be dispatched.
10374     * @return True if the event was handled by the view, false otherwise.
10375     */
10376    public boolean dispatchTouchEvent(MotionEvent event) {
10377        // If the event should be handled by accessibility focus first.
10378        if (event.isTargetAccessibilityFocus()) {
10379            // We don't have focus or no virtual descendant has it, do not handle the event.
10380            if (!isAccessibilityFocusedViewOrHost()) {
10381                return false;
10382            }
10383            // We have focus and got the event, then use normal event dispatch.
10384            event.setTargetAccessibilityFocus(false);
10385        }
10386
10387        boolean result = false;
10388
10389        if (mInputEventConsistencyVerifier != null) {
10390            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
10391        }
10392
10393        final int actionMasked = event.getActionMasked();
10394        if (actionMasked == MotionEvent.ACTION_DOWN) {
10395            // Defensive cleanup for new gesture
10396            stopNestedScroll();
10397        }
10398
10399        if (onFilterTouchEventForSecurity(event)) {
10400            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
10401                result = true;
10402            }
10403            //noinspection SimplifiableIfStatement
10404            ListenerInfo li = mListenerInfo;
10405            if (li != null && li.mOnTouchListener != null
10406                    && (mViewFlags & ENABLED_MASK) == ENABLED
10407                    && li.mOnTouchListener.onTouch(this, event)) {
10408                result = true;
10409            }
10410
10411            if (!result && onTouchEvent(event)) {
10412                result = true;
10413            }
10414        }
10415
10416        if (!result && mInputEventConsistencyVerifier != null) {
10417            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10418        }
10419
10420        // Clean up after nested scrolls if this is the end of a gesture;
10421        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
10422        // of the gesture.
10423        if (actionMasked == MotionEvent.ACTION_UP ||
10424                actionMasked == MotionEvent.ACTION_CANCEL ||
10425                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
10426            stopNestedScroll();
10427        }
10428
10429        return result;
10430    }
10431
10432    boolean isAccessibilityFocusedViewOrHost() {
10433        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
10434                .getAccessibilityFocusedHost() == this);
10435    }
10436
10437    /**
10438     * Filter the touch event to apply security policies.
10439     *
10440     * @param event The motion event to be filtered.
10441     * @return True if the event should be dispatched, false if the event should be dropped.
10442     *
10443     * @see #getFilterTouchesWhenObscured
10444     */
10445    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
10446        //noinspection RedundantIfStatement
10447        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
10448                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
10449            // Window is obscured, drop this touch.
10450            return false;
10451        }
10452        return true;
10453    }
10454
10455    /**
10456     * Pass a trackball motion event down to the focused view.
10457     *
10458     * @param event The motion event to be dispatched.
10459     * @return True if the event was handled by the view, false otherwise.
10460     */
10461    public boolean dispatchTrackballEvent(MotionEvent event) {
10462        if (mInputEventConsistencyVerifier != null) {
10463            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
10464        }
10465
10466        return onTrackballEvent(event);
10467    }
10468
10469    /**
10470     * Dispatch a generic motion event.
10471     * <p>
10472     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10473     * are delivered to the view under the pointer.  All other generic motion events are
10474     * delivered to the focused view.  Hover events are handled specially and are delivered
10475     * to {@link #onHoverEvent(MotionEvent)}.
10476     * </p>
10477     *
10478     * @param event The motion event to be dispatched.
10479     * @return True if the event was handled by the view, false otherwise.
10480     */
10481    public boolean dispatchGenericMotionEvent(MotionEvent event) {
10482        if (mInputEventConsistencyVerifier != null) {
10483            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
10484        }
10485
10486        final int source = event.getSource();
10487        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
10488            final int action = event.getAction();
10489            if (action == MotionEvent.ACTION_HOVER_ENTER
10490                    || action == MotionEvent.ACTION_HOVER_MOVE
10491                    || action == MotionEvent.ACTION_HOVER_EXIT) {
10492                if (dispatchHoverEvent(event)) {
10493                    return true;
10494                }
10495            } else if (dispatchGenericPointerEvent(event)) {
10496                return true;
10497            }
10498        } else if (dispatchGenericFocusedEvent(event)) {
10499            return true;
10500        }
10501
10502        if (dispatchGenericMotionEventInternal(event)) {
10503            return true;
10504        }
10505
10506        if (mInputEventConsistencyVerifier != null) {
10507            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10508        }
10509        return false;
10510    }
10511
10512    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
10513        //noinspection SimplifiableIfStatement
10514        ListenerInfo li = mListenerInfo;
10515        if (li != null && li.mOnGenericMotionListener != null
10516                && (mViewFlags & ENABLED_MASK) == ENABLED
10517                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
10518            return true;
10519        }
10520
10521        if (onGenericMotionEvent(event)) {
10522            return true;
10523        }
10524
10525        final int actionButton = event.getActionButton();
10526        switch (event.getActionMasked()) {
10527            case MotionEvent.ACTION_BUTTON_PRESS:
10528                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
10529                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10530                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10531                    if (performContextClick(event.getX(), event.getY())) {
10532                        mInContextButtonPress = true;
10533                        setPressed(true, event.getX(), event.getY());
10534                        removeTapCallback();
10535                        removeLongPressCallback();
10536                        return true;
10537                    }
10538                }
10539                break;
10540
10541            case MotionEvent.ACTION_BUTTON_RELEASE:
10542                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10543                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10544                    mInContextButtonPress = false;
10545                    mIgnoreNextUpEvent = true;
10546                }
10547                break;
10548        }
10549
10550        if (mInputEventConsistencyVerifier != null) {
10551            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10552        }
10553        return false;
10554    }
10555
10556    /**
10557     * Dispatch a hover event.
10558     * <p>
10559     * Do not call this method directly.
10560     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10561     * </p>
10562     *
10563     * @param event The motion event to be dispatched.
10564     * @return True if the event was handled by the view, false otherwise.
10565     */
10566    protected boolean dispatchHoverEvent(MotionEvent event) {
10567        ListenerInfo li = mListenerInfo;
10568        //noinspection SimplifiableIfStatement
10569        if (li != null && li.mOnHoverListener != null
10570                && (mViewFlags & ENABLED_MASK) == ENABLED
10571                && li.mOnHoverListener.onHover(this, event)) {
10572            return true;
10573        }
10574
10575        return onHoverEvent(event);
10576    }
10577
10578    /**
10579     * Returns true if the view has a child to which it has recently sent
10580     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
10581     * it does not have a hovered child, then it must be the innermost hovered view.
10582     * @hide
10583     */
10584    protected boolean hasHoveredChild() {
10585        return false;
10586    }
10587
10588    /**
10589     * Dispatch a generic motion event to the view under the first pointer.
10590     * <p>
10591     * Do not call this method directly.
10592     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10593     * </p>
10594     *
10595     * @param event The motion event to be dispatched.
10596     * @return True if the event was handled by the view, false otherwise.
10597     */
10598    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
10599        return false;
10600    }
10601
10602    /**
10603     * Dispatch a generic motion event to the currently focused view.
10604     * <p>
10605     * Do not call this method directly.
10606     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10607     * </p>
10608     *
10609     * @param event The motion event to be dispatched.
10610     * @return True if the event was handled by the view, false otherwise.
10611     */
10612    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
10613        return false;
10614    }
10615
10616    /**
10617     * Dispatch a pointer event.
10618     * <p>
10619     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
10620     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
10621     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
10622     * and should not be expected to handle other pointing device features.
10623     * </p>
10624     *
10625     * @param event The motion event to be dispatched.
10626     * @return True if the event was handled by the view, false otherwise.
10627     * @hide
10628     */
10629    public final boolean dispatchPointerEvent(MotionEvent event) {
10630        if (event.isTouchEvent()) {
10631            return dispatchTouchEvent(event);
10632        } else {
10633            return dispatchGenericMotionEvent(event);
10634        }
10635    }
10636
10637    /**
10638     * Called when the window containing this view gains or loses window focus.
10639     * ViewGroups should override to route to their children.
10640     *
10641     * @param hasFocus True if the window containing this view now has focus,
10642     *        false otherwise.
10643     */
10644    public void dispatchWindowFocusChanged(boolean hasFocus) {
10645        onWindowFocusChanged(hasFocus);
10646    }
10647
10648    /**
10649     * Called when the window containing this view gains or loses focus.  Note
10650     * that this is separate from view focus: to receive key events, both
10651     * your view and its window must have focus.  If a window is displayed
10652     * on top of yours that takes input focus, then your own window will lose
10653     * focus but the view focus will remain unchanged.
10654     *
10655     * @param hasWindowFocus True if the window containing this view now has
10656     *        focus, false otherwise.
10657     */
10658    public void onWindowFocusChanged(boolean hasWindowFocus) {
10659        InputMethodManager imm = InputMethodManager.peekInstance();
10660        if (!hasWindowFocus) {
10661            if (isPressed()) {
10662                setPressed(false);
10663            }
10664            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10665                imm.focusOut(this);
10666            }
10667            removeLongPressCallback();
10668            removeTapCallback();
10669            onFocusLost();
10670        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10671            imm.focusIn(this);
10672        }
10673        refreshDrawableState();
10674    }
10675
10676    /**
10677     * Returns true if this view is in a window that currently has window focus.
10678     * Note that this is not the same as the view itself having focus.
10679     *
10680     * @return True if this view is in a window that currently has window focus.
10681     */
10682    public boolean hasWindowFocus() {
10683        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
10684    }
10685
10686    /**
10687     * Dispatch a view visibility change down the view hierarchy.
10688     * ViewGroups should override to route to their children.
10689     * @param changedView The view whose visibility changed. Could be 'this' or
10690     * an ancestor view.
10691     * @param visibility The new visibility of changedView: {@link #VISIBLE},
10692     * {@link #INVISIBLE} or {@link #GONE}.
10693     */
10694    protected void dispatchVisibilityChanged(@NonNull View changedView,
10695            @Visibility int visibility) {
10696        onVisibilityChanged(changedView, visibility);
10697    }
10698
10699    /**
10700     * Called when the visibility of the view or an ancestor of the view has
10701     * changed.
10702     *
10703     * @param changedView The view whose visibility changed. May be
10704     *                    {@code this} or an ancestor view.
10705     * @param visibility The new visibility, one of {@link #VISIBLE},
10706     *                   {@link #INVISIBLE} or {@link #GONE}.
10707     */
10708    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
10709    }
10710
10711    /**
10712     * Dispatch a hint about whether this view is displayed. For instance, when
10713     * a View moves out of the screen, it might receives a display hint indicating
10714     * the view is not displayed. Applications should not <em>rely</em> on this hint
10715     * as there is no guarantee that they will receive one.
10716     *
10717     * @param hint A hint about whether or not this view is displayed:
10718     * {@link #VISIBLE} or {@link #INVISIBLE}.
10719     */
10720    public void dispatchDisplayHint(@Visibility int hint) {
10721        onDisplayHint(hint);
10722    }
10723
10724    /**
10725     * Gives this view a hint about whether is displayed or not. For instance, when
10726     * a View moves out of the screen, it might receives a display hint indicating
10727     * the view is not displayed. Applications should not <em>rely</em> on this hint
10728     * as there is no guarantee that they will receive one.
10729     *
10730     * @param hint A hint about whether or not this view is displayed:
10731     * {@link #VISIBLE} or {@link #INVISIBLE}.
10732     */
10733    protected void onDisplayHint(@Visibility int hint) {
10734    }
10735
10736    /**
10737     * Dispatch a window visibility change down the view hierarchy.
10738     * ViewGroups should override to route to their children.
10739     *
10740     * @param visibility The new visibility of the window.
10741     *
10742     * @see #onWindowVisibilityChanged(int)
10743     */
10744    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
10745        onWindowVisibilityChanged(visibility);
10746    }
10747
10748    /**
10749     * Called when the window containing has change its visibility
10750     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
10751     * that this tells you whether or not your window is being made visible
10752     * to the window manager; this does <em>not</em> tell you whether or not
10753     * your window is obscured by other windows on the screen, even if it
10754     * is itself visible.
10755     *
10756     * @param visibility The new visibility of the window.
10757     */
10758    protected void onWindowVisibilityChanged(@Visibility int visibility) {
10759        if (visibility == VISIBLE) {
10760            initialAwakenScrollBars();
10761        }
10762    }
10763
10764    /**
10765     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
10766     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
10767     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
10768     *
10769     * @param isVisible true if this view's visibility to the user is uninterrupted by its
10770     *                  ancestors or by window visibility
10771     * @return true if this view is visible to the user, not counting clipping or overlapping
10772     */
10773    boolean dispatchVisibilityAggregated(boolean isVisible) {
10774        final boolean thisVisible = getVisibility() == VISIBLE;
10775        // If we're not visible but something is telling us we are, ignore it.
10776        if (thisVisible || !isVisible) {
10777            onVisibilityAggregated(isVisible);
10778        }
10779        return thisVisible && isVisible;
10780    }
10781
10782    /**
10783     * Called when the user-visibility of this View is potentially affected by a change
10784     * to this view itself, an ancestor view or the window this view is attached to.
10785     *
10786     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
10787     *                  and this view's window is also visible
10788     */
10789    @CallSuper
10790    public void onVisibilityAggregated(boolean isVisible) {
10791        if (isVisible && mAttachInfo != null) {
10792            initialAwakenScrollBars();
10793        }
10794
10795        final Drawable dr = mBackground;
10796        if (dr != null && isVisible != dr.isVisible()) {
10797            dr.setVisible(isVisible, false);
10798        }
10799        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
10800        if (fg != null && isVisible != fg.isVisible()) {
10801            fg.setVisible(isVisible, false);
10802        }
10803    }
10804
10805    /**
10806     * Returns the current visibility of the window this view is attached to
10807     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
10808     *
10809     * @return Returns the current visibility of the view's window.
10810     */
10811    @Visibility
10812    public int getWindowVisibility() {
10813        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
10814    }
10815
10816    /**
10817     * Retrieve the overall visible display size in which the window this view is
10818     * attached to has been positioned in.  This takes into account screen
10819     * decorations above the window, for both cases where the window itself
10820     * is being position inside of them or the window is being placed under
10821     * then and covered insets are used for the window to position its content
10822     * inside.  In effect, this tells you the available area where content can
10823     * be placed and remain visible to users.
10824     *
10825     * <p>This function requires an IPC back to the window manager to retrieve
10826     * the requested information, so should not be used in performance critical
10827     * code like drawing.
10828     *
10829     * @param outRect Filled in with the visible display frame.  If the view
10830     * is not attached to a window, this is simply the raw display size.
10831     */
10832    public void getWindowVisibleDisplayFrame(Rect outRect) {
10833        if (mAttachInfo != null) {
10834            try {
10835                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10836            } catch (RemoteException e) {
10837                return;
10838            }
10839            // XXX This is really broken, and probably all needs to be done
10840            // in the window manager, and we need to know more about whether
10841            // we want the area behind or in front of the IME.
10842            final Rect insets = mAttachInfo.mVisibleInsets;
10843            outRect.left += insets.left;
10844            outRect.top += insets.top;
10845            outRect.right -= insets.right;
10846            outRect.bottom -= insets.bottom;
10847            return;
10848        }
10849        // The view is not attached to a display so we don't have a context.
10850        // Make a best guess about the display size.
10851        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10852        d.getRectSize(outRect);
10853    }
10854
10855    /**
10856     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
10857     * is currently in without any insets.
10858     *
10859     * @hide
10860     */
10861    public void getWindowDisplayFrame(Rect outRect) {
10862        if (mAttachInfo != null) {
10863            try {
10864                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
10865            } catch (RemoteException e) {
10866                return;
10867            }
10868            return;
10869        }
10870        // The view is not attached to a display so we don't have a context.
10871        // Make a best guess about the display size.
10872        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
10873        d.getRectSize(outRect);
10874    }
10875
10876    /**
10877     * Dispatch a notification about a resource configuration change down
10878     * the view hierarchy.
10879     * ViewGroups should override to route to their children.
10880     *
10881     * @param newConfig The new resource configuration.
10882     *
10883     * @see #onConfigurationChanged(android.content.res.Configuration)
10884     */
10885    public void dispatchConfigurationChanged(Configuration newConfig) {
10886        onConfigurationChanged(newConfig);
10887    }
10888
10889    /**
10890     * Called when the current configuration of the resources being used
10891     * by the application have changed.  You can use this to decide when
10892     * to reload resources that can changed based on orientation and other
10893     * configuration characteristics.  You only need to use this if you are
10894     * not relying on the normal {@link android.app.Activity} mechanism of
10895     * recreating the activity instance upon a configuration change.
10896     *
10897     * @param newConfig The new resource configuration.
10898     */
10899    protected void onConfigurationChanged(Configuration newConfig) {
10900    }
10901
10902    /**
10903     * Private function to aggregate all per-view attributes in to the view
10904     * root.
10905     */
10906    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10907        performCollectViewAttributes(attachInfo, visibility);
10908    }
10909
10910    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10911        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
10912            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
10913                attachInfo.mKeepScreenOn = true;
10914            }
10915            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
10916            ListenerInfo li = mListenerInfo;
10917            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
10918                attachInfo.mHasSystemUiListeners = true;
10919            }
10920        }
10921    }
10922
10923    void needGlobalAttributesUpdate(boolean force) {
10924        final AttachInfo ai = mAttachInfo;
10925        if (ai != null && !ai.mRecomputeGlobalAttributes) {
10926            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
10927                    || ai.mHasSystemUiListeners) {
10928                ai.mRecomputeGlobalAttributes = true;
10929            }
10930        }
10931    }
10932
10933    /**
10934     * Returns whether the device is currently in touch mode.  Touch mode is entered
10935     * once the user begins interacting with the device by touch, and affects various
10936     * things like whether focus is always visible to the user.
10937     *
10938     * @return Whether the device is in touch mode.
10939     */
10940    @ViewDebug.ExportedProperty
10941    public boolean isInTouchMode() {
10942        if (mAttachInfo != null) {
10943            return mAttachInfo.mInTouchMode;
10944        } else {
10945            return ViewRootImpl.isInTouchMode();
10946        }
10947    }
10948
10949    /**
10950     * Returns the context the view is running in, through which it can
10951     * access the current theme, resources, etc.
10952     *
10953     * @return The view's Context.
10954     */
10955    @ViewDebug.CapturedViewProperty
10956    public final Context getContext() {
10957        return mContext;
10958    }
10959
10960    /**
10961     * Handle a key event before it is processed by any input method
10962     * associated with the view hierarchy.  This can be used to intercept
10963     * key events in special situations before the IME consumes them; a
10964     * typical example would be handling the BACK key to update the application's
10965     * UI instead of allowing the IME to see it and close itself.
10966     *
10967     * @param keyCode The value in event.getKeyCode().
10968     * @param event Description of the key event.
10969     * @return If you handled the event, return true. If you want to allow the
10970     *         event to be handled by the next receiver, return false.
10971     */
10972    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10973        return false;
10974    }
10975
10976    /**
10977     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10978     * KeyEvent.Callback.onKeyDown()}: perform press of the view
10979     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10980     * is released, if the view is enabled and clickable.
10981     * <p>
10982     * Key presses in software keyboards will generally NOT trigger this
10983     * listener, although some may elect to do so in some situations. Do not
10984     * rely on this to catch software key presses.
10985     *
10986     * @param keyCode a key code that represents the button pressed, from
10987     *                {@link android.view.KeyEvent}
10988     * @param event the KeyEvent object that defines the button action
10989     */
10990    public boolean onKeyDown(int keyCode, KeyEvent event) {
10991        if (KeyEvent.isConfirmKey(keyCode)) {
10992            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10993                return true;
10994            }
10995
10996            if (event.getRepeatCount() == 0) {
10997                // Long clickable items don't necessarily have to be clickable.
10998                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
10999                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
11000                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
11001                    // For the purposes of menu anchoring and drawable hotspots,
11002                    // key events are considered to be at the center of the view.
11003                    final float x = getWidth() / 2f;
11004                    final float y = getHeight() / 2f;
11005                    if (clickable) {
11006                        setPressed(true, x, y);
11007                    }
11008                    checkForLongClick(0, x, y);
11009                    return true;
11010                }
11011            }
11012        }
11013
11014        return false;
11015    }
11016
11017    /**
11018     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
11019     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
11020     * the event).
11021     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11022     * although some may elect to do so in some situations. Do not rely on this to
11023     * catch software key presses.
11024     */
11025    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
11026        return false;
11027    }
11028
11029    /**
11030     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
11031     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
11032     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
11033     * or {@link KeyEvent#KEYCODE_SPACE} is released.
11034     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11035     * although some may elect to do so in some situations. Do not rely on this to
11036     * catch software key presses.
11037     *
11038     * @param keyCode A key code that represents the button pressed, from
11039     *                {@link android.view.KeyEvent}.
11040     * @param event   The KeyEvent object that defines the button action.
11041     */
11042    public boolean onKeyUp(int keyCode, KeyEvent event) {
11043        if (KeyEvent.isConfirmKey(keyCode)) {
11044            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11045                return true;
11046            }
11047            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
11048                setPressed(false);
11049
11050                if (!mHasPerformedLongPress) {
11051                    // This is a tap, so remove the longpress check
11052                    removeLongPressCallback();
11053                    return performClick();
11054                }
11055            }
11056        }
11057        return false;
11058    }
11059
11060    /**
11061     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
11062     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
11063     * the event).
11064     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11065     * although some may elect to do so in some situations. Do not rely on this to
11066     * catch software key presses.
11067     *
11068     * @param keyCode     A key code that represents the button pressed, from
11069     *                    {@link android.view.KeyEvent}.
11070     * @param repeatCount The number of times the action was made.
11071     * @param event       The KeyEvent object that defines the button action.
11072     */
11073    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
11074        return false;
11075    }
11076
11077    /**
11078     * Called on the focused view when a key shortcut event is not handled.
11079     * Override this method to implement local key shortcuts for the View.
11080     * Key shortcuts can also be implemented by setting the
11081     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
11082     *
11083     * @param keyCode The value in event.getKeyCode().
11084     * @param event Description of the key event.
11085     * @return If you handled the event, return true. If you want to allow the
11086     *         event to be handled by the next receiver, return false.
11087     */
11088    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
11089        return false;
11090    }
11091
11092    /**
11093     * Check whether the called view is a text editor, in which case it
11094     * would make sense to automatically display a soft input window for
11095     * it.  Subclasses should override this if they implement
11096     * {@link #onCreateInputConnection(EditorInfo)} to return true if
11097     * a call on that method would return a non-null InputConnection, and
11098     * they are really a first-class editor that the user would normally
11099     * start typing on when the go into a window containing your view.
11100     *
11101     * <p>The default implementation always returns false.  This does
11102     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
11103     * will not be called or the user can not otherwise perform edits on your
11104     * view; it is just a hint to the system that this is not the primary
11105     * purpose of this view.
11106     *
11107     * @return Returns true if this view is a text editor, else false.
11108     */
11109    public boolean onCheckIsTextEditor() {
11110        return false;
11111    }
11112
11113    /**
11114     * Create a new InputConnection for an InputMethod to interact
11115     * with the view.  The default implementation returns null, since it doesn't
11116     * support input methods.  You can override this to implement such support.
11117     * This is only needed for views that take focus and text input.
11118     *
11119     * <p>When implementing this, you probably also want to implement
11120     * {@link #onCheckIsTextEditor()} to indicate you will return a
11121     * non-null InputConnection.</p>
11122     *
11123     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
11124     * object correctly and in its entirety, so that the connected IME can rely
11125     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
11126     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
11127     * must be filled in with the correct cursor position for IMEs to work correctly
11128     * with your application.</p>
11129     *
11130     * @param outAttrs Fill in with attribute information about the connection.
11131     */
11132    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
11133        return null;
11134    }
11135
11136    /**
11137     * Called by the {@link android.view.inputmethod.InputMethodManager}
11138     * when a view who is not the current
11139     * input connection target is trying to make a call on the manager.  The
11140     * default implementation returns false; you can override this to return
11141     * true for certain views if you are performing InputConnection proxying
11142     * to them.
11143     * @param view The View that is making the InputMethodManager call.
11144     * @return Return true to allow the call, false to reject.
11145     */
11146    public boolean checkInputConnectionProxy(View view) {
11147        return false;
11148    }
11149
11150    /**
11151     * Show the context menu for this view. It is not safe to hold on to the
11152     * menu after returning from this method.
11153     *
11154     * You should normally not overload this method. Overload
11155     * {@link #onCreateContextMenu(ContextMenu)} or define an
11156     * {@link OnCreateContextMenuListener} to add items to the context menu.
11157     *
11158     * @param menu The context menu to populate
11159     */
11160    public void createContextMenu(ContextMenu menu) {
11161        ContextMenuInfo menuInfo = getContextMenuInfo();
11162
11163        // Sets the current menu info so all items added to menu will have
11164        // my extra info set.
11165        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
11166
11167        onCreateContextMenu(menu);
11168        ListenerInfo li = mListenerInfo;
11169        if (li != null && li.mOnCreateContextMenuListener != null) {
11170            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
11171        }
11172
11173        // Clear the extra information so subsequent items that aren't mine don't
11174        // have my extra info.
11175        ((MenuBuilder)menu).setCurrentMenuInfo(null);
11176
11177        if (mParent != null) {
11178            mParent.createContextMenu(menu);
11179        }
11180    }
11181
11182    /**
11183     * Views should implement this if they have extra information to associate
11184     * with the context menu. The return result is supplied as a parameter to
11185     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
11186     * callback.
11187     *
11188     * @return Extra information about the item for which the context menu
11189     *         should be shown. This information will vary across different
11190     *         subclasses of View.
11191     */
11192    protected ContextMenuInfo getContextMenuInfo() {
11193        return null;
11194    }
11195
11196    /**
11197     * Views should implement this if the view itself is going to add items to
11198     * the context menu.
11199     *
11200     * @param menu the context menu to populate
11201     */
11202    protected void onCreateContextMenu(ContextMenu menu) {
11203    }
11204
11205    /**
11206     * Implement this method to handle trackball motion events.  The
11207     * <em>relative</em> movement of the trackball since the last event
11208     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
11209     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
11210     * that a movement of 1 corresponds to the user pressing one DPAD key (so
11211     * they will often be fractional values, representing the more fine-grained
11212     * movement information available from a trackball).
11213     *
11214     * @param event The motion event.
11215     * @return True if the event was handled, false otherwise.
11216     */
11217    public boolean onTrackballEvent(MotionEvent event) {
11218        return false;
11219    }
11220
11221    /**
11222     * Implement this method to handle generic motion events.
11223     * <p>
11224     * Generic motion events describe joystick movements, mouse hovers, track pad
11225     * touches, scroll wheel movements and other input events.  The
11226     * {@link MotionEvent#getSource() source} of the motion event specifies
11227     * the class of input that was received.  Implementations of this method
11228     * must examine the bits in the source before processing the event.
11229     * The following code example shows how this is done.
11230     * </p><p>
11231     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11232     * are delivered to the view under the pointer.  All other generic motion events are
11233     * delivered to the focused view.
11234     * </p>
11235     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
11236     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
11237     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
11238     *             // process the joystick movement...
11239     *             return true;
11240     *         }
11241     *     }
11242     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
11243     *         switch (event.getAction()) {
11244     *             case MotionEvent.ACTION_HOVER_MOVE:
11245     *                 // process the mouse hover movement...
11246     *                 return true;
11247     *             case MotionEvent.ACTION_SCROLL:
11248     *                 // process the scroll wheel movement...
11249     *                 return true;
11250     *         }
11251     *     }
11252     *     return super.onGenericMotionEvent(event);
11253     * }</pre>
11254     *
11255     * @param event The generic motion event being processed.
11256     * @return True if the event was handled, false otherwise.
11257     */
11258    public boolean onGenericMotionEvent(MotionEvent event) {
11259        return false;
11260    }
11261
11262    /**
11263     * Implement this method to handle hover events.
11264     * <p>
11265     * This method is called whenever a pointer is hovering into, over, or out of the
11266     * bounds of a view and the view is not currently being touched.
11267     * Hover events are represented as pointer events with action
11268     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
11269     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
11270     * </p>
11271     * <ul>
11272     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
11273     * when the pointer enters the bounds of the view.</li>
11274     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
11275     * when the pointer has already entered the bounds of the view and has moved.</li>
11276     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
11277     * when the pointer has exited the bounds of the view or when the pointer is
11278     * about to go down due to a button click, tap, or similar user action that
11279     * causes the view to be touched.</li>
11280     * </ul>
11281     * <p>
11282     * The view should implement this method to return true to indicate that it is
11283     * handling the hover event, such as by changing its drawable state.
11284     * </p><p>
11285     * The default implementation calls {@link #setHovered} to update the hovered state
11286     * of the view when a hover enter or hover exit event is received, if the view
11287     * is enabled and is clickable.  The default implementation also sends hover
11288     * accessibility events.
11289     * </p>
11290     *
11291     * @param event The motion event that describes the hover.
11292     * @return True if the view handled the hover event.
11293     *
11294     * @see #isHovered
11295     * @see #setHovered
11296     * @see #onHoverChanged
11297     */
11298    public boolean onHoverEvent(MotionEvent event) {
11299        // The root view may receive hover (or touch) events that are outside the bounds of
11300        // the window.  This code ensures that we only send accessibility events for
11301        // hovers that are actually within the bounds of the root view.
11302        final int action = event.getActionMasked();
11303        if (!mSendingHoverAccessibilityEvents) {
11304            if ((action == MotionEvent.ACTION_HOVER_ENTER
11305                    || action == MotionEvent.ACTION_HOVER_MOVE)
11306                    && !hasHoveredChild()
11307                    && pointInView(event.getX(), event.getY())) {
11308                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
11309                mSendingHoverAccessibilityEvents = true;
11310            }
11311        } else {
11312            if (action == MotionEvent.ACTION_HOVER_EXIT
11313                    || (action == MotionEvent.ACTION_MOVE
11314                            && !pointInView(event.getX(), event.getY()))) {
11315                mSendingHoverAccessibilityEvents = false;
11316                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
11317            }
11318        }
11319
11320        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
11321                && event.isFromSource(InputDevice.SOURCE_MOUSE)
11322                && isOnScrollbar(event.getX(), event.getY())) {
11323            awakenScrollBars();
11324        }
11325        if (isHoverable()) {
11326            switch (action) {
11327                case MotionEvent.ACTION_HOVER_ENTER:
11328                    setHovered(true);
11329                    break;
11330                case MotionEvent.ACTION_HOVER_EXIT:
11331                    setHovered(false);
11332                    break;
11333            }
11334
11335            // Dispatch the event to onGenericMotionEvent before returning true.
11336            // This is to provide compatibility with existing applications that
11337            // handled HOVER_MOVE events in onGenericMotionEvent and that would
11338            // break because of the new default handling for hoverable views
11339            // in onHoverEvent.
11340            // Note that onGenericMotionEvent will be called by default when
11341            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
11342            dispatchGenericMotionEventInternal(event);
11343            // The event was already handled by calling setHovered(), so always
11344            // return true.
11345            return true;
11346        }
11347
11348        return false;
11349    }
11350
11351    /**
11352     * Returns true if the view should handle {@link #onHoverEvent}
11353     * by calling {@link #setHovered} to change its hovered state.
11354     *
11355     * @return True if the view is hoverable.
11356     */
11357    private boolean isHoverable() {
11358        final int viewFlags = mViewFlags;
11359        if ((viewFlags & ENABLED_MASK) == DISABLED) {
11360            return false;
11361        }
11362
11363        return (viewFlags & CLICKABLE) == CLICKABLE
11364                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
11365                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
11366    }
11367
11368    /**
11369     * Returns true if the view is currently hovered.
11370     *
11371     * @return True if the view is currently hovered.
11372     *
11373     * @see #setHovered
11374     * @see #onHoverChanged
11375     */
11376    @ViewDebug.ExportedProperty
11377    public boolean isHovered() {
11378        return (mPrivateFlags & PFLAG_HOVERED) != 0;
11379    }
11380
11381    /**
11382     * Sets whether the view is currently hovered.
11383     * <p>
11384     * Calling this method also changes the drawable state of the view.  This
11385     * enables the view to react to hover by using different drawable resources
11386     * to change its appearance.
11387     * </p><p>
11388     * The {@link #onHoverChanged} method is called when the hovered state changes.
11389     * </p>
11390     *
11391     * @param hovered True if the view is hovered.
11392     *
11393     * @see #isHovered
11394     * @see #onHoverChanged
11395     */
11396    public void setHovered(boolean hovered) {
11397        if (hovered) {
11398            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
11399                mPrivateFlags |= PFLAG_HOVERED;
11400                refreshDrawableState();
11401                onHoverChanged(true);
11402            }
11403        } else {
11404            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
11405                mPrivateFlags &= ~PFLAG_HOVERED;
11406                refreshDrawableState();
11407                onHoverChanged(false);
11408            }
11409        }
11410    }
11411
11412    /**
11413     * Implement this method to handle hover state changes.
11414     * <p>
11415     * This method is called whenever the hover state changes as a result of a
11416     * call to {@link #setHovered}.
11417     * </p>
11418     *
11419     * @param hovered The current hover state, as returned by {@link #isHovered}.
11420     *
11421     * @see #isHovered
11422     * @see #setHovered
11423     */
11424    public void onHoverChanged(boolean hovered) {
11425    }
11426
11427    /**
11428     * Handles scroll bar dragging by mouse input.
11429     *
11430     * @hide
11431     * @param event The motion event.
11432     *
11433     * @return true if the event was handled as a scroll bar dragging, false otherwise.
11434     */
11435    protected boolean handleScrollBarDragging(MotionEvent event) {
11436        if (mScrollCache == null) {
11437            return false;
11438        }
11439        final float x = event.getX();
11440        final float y = event.getY();
11441        final int action = event.getAction();
11442        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
11443                && action != MotionEvent.ACTION_DOWN)
11444                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
11445                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
11446            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11447            return false;
11448        }
11449
11450        switch (action) {
11451            case MotionEvent.ACTION_MOVE:
11452                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
11453                    return false;
11454                }
11455                if (mScrollCache.mScrollBarDraggingState
11456                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
11457                    final Rect bounds = mScrollCache.mScrollBarBounds;
11458                    getVerticalScrollBarBounds(bounds);
11459                    final int range = computeVerticalScrollRange();
11460                    final int offset = computeVerticalScrollOffset();
11461                    final int extent = computeVerticalScrollExtent();
11462
11463                    final int thumbLength = ScrollBarUtils.getThumbLength(
11464                            bounds.height(), bounds.width(), extent, range);
11465                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11466                            bounds.height(), thumbLength, extent, range, offset);
11467
11468                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
11469                    final float maxThumbOffset = bounds.height() - thumbLength;
11470                    final float newThumbOffset =
11471                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11472                    final int height = getHeight();
11473                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11474                            && height > 0 && extent > 0) {
11475                        final int newY = Math.round((range - extent)
11476                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
11477                        if (newY != getScrollY()) {
11478                            mScrollCache.mScrollBarDraggingPos = y;
11479                            setScrollY(newY);
11480                        }
11481                    }
11482                    return true;
11483                }
11484                if (mScrollCache.mScrollBarDraggingState
11485                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
11486                    final Rect bounds = mScrollCache.mScrollBarBounds;
11487                    getHorizontalScrollBarBounds(bounds);
11488                    final int range = computeHorizontalScrollRange();
11489                    final int offset = computeHorizontalScrollOffset();
11490                    final int extent = computeHorizontalScrollExtent();
11491
11492                    final int thumbLength = ScrollBarUtils.getThumbLength(
11493                            bounds.width(), bounds.height(), extent, range);
11494                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11495                            bounds.width(), thumbLength, extent, range, offset);
11496
11497                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
11498                    final float maxThumbOffset = bounds.width() - thumbLength;
11499                    final float newThumbOffset =
11500                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11501                    final int width = getWidth();
11502                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11503                            && width > 0 && extent > 0) {
11504                        final int newX = Math.round((range - extent)
11505                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
11506                        if (newX != getScrollX()) {
11507                            mScrollCache.mScrollBarDraggingPos = x;
11508                            setScrollX(newX);
11509                        }
11510                    }
11511                    return true;
11512                }
11513            case MotionEvent.ACTION_DOWN:
11514                if (mScrollCache.state == ScrollabilityCache.OFF) {
11515                    return false;
11516                }
11517                if (isOnVerticalScrollbarThumb(x, y)) {
11518                    mScrollCache.mScrollBarDraggingState =
11519                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
11520                    mScrollCache.mScrollBarDraggingPos = y;
11521                    return true;
11522                }
11523                if (isOnHorizontalScrollbarThumb(x, y)) {
11524                    mScrollCache.mScrollBarDraggingState =
11525                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
11526                    mScrollCache.mScrollBarDraggingPos = x;
11527                    return true;
11528                }
11529        }
11530        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11531        return false;
11532    }
11533
11534    /**
11535     * Implement this method to handle touch screen motion events.
11536     * <p>
11537     * If this method is used to detect click actions, it is recommended that
11538     * the actions be performed by implementing and calling
11539     * {@link #performClick()}. This will ensure consistent system behavior,
11540     * including:
11541     * <ul>
11542     * <li>obeying click sound preferences
11543     * <li>dispatching OnClickListener calls
11544     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
11545     * accessibility features are enabled
11546     * </ul>
11547     *
11548     * @param event The motion event.
11549     * @return True if the event was handled, false otherwise.
11550     */
11551    public boolean onTouchEvent(MotionEvent event) {
11552        final float x = event.getX();
11553        final float y = event.getY();
11554        final int viewFlags = mViewFlags;
11555        final int action = event.getAction();
11556
11557        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
11558                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
11559                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
11560
11561        if ((viewFlags & ENABLED_MASK) == DISABLED) {
11562            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
11563                setPressed(false);
11564            }
11565            // A disabled view that is clickable still consumes the touch
11566            // events, it just doesn't respond to them.
11567            return clickable;
11568        }
11569        if (mTouchDelegate != null) {
11570            if (mTouchDelegate.onTouchEvent(event)) {
11571                return true;
11572            }
11573        }
11574
11575        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
11576            switch (action) {
11577                case MotionEvent.ACTION_UP:
11578                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
11579                        handleTooltipUp();
11580                    }
11581                    if (!clickable) {
11582                        removeTapCallback();
11583                        removeLongPressCallback();
11584                        mInContextButtonPress = false;
11585                        mHasPerformedLongPress = false;
11586                        mIgnoreNextUpEvent = false;
11587                        break;
11588                    }
11589                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
11590                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
11591                        // take focus if we don't have it already and we should in
11592                        // touch mode.
11593                        boolean focusTaken = false;
11594                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
11595                            focusTaken = requestFocus();
11596                        }
11597
11598                        if (prepressed) {
11599                            // The button is being released before we actually
11600                            // showed it as pressed.  Make it show the pressed
11601                            // state now (before scheduling the click) to ensure
11602                            // the user sees it.
11603                            setPressed(true, x, y);
11604                        }
11605
11606                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
11607                            // This is a tap, so remove the longpress check
11608                            removeLongPressCallback();
11609
11610                            // Only perform take click actions if we were in the pressed state
11611                            if (!focusTaken) {
11612                                // Use a Runnable and post this rather than calling
11613                                // performClick directly. This lets other visual state
11614                                // of the view update before click actions start.
11615                                if (mPerformClick == null) {
11616                                    mPerformClick = new PerformClick();
11617                                }
11618                                if (!post(mPerformClick)) {
11619                                    performClick();
11620                                }
11621                            }
11622                        }
11623
11624                        if (mUnsetPressedState == null) {
11625                            mUnsetPressedState = new UnsetPressedState();
11626                        }
11627
11628                        if (prepressed) {
11629                            postDelayed(mUnsetPressedState,
11630                                    ViewConfiguration.getPressedStateDuration());
11631                        } else if (!post(mUnsetPressedState)) {
11632                            // If the post failed, unpress right now
11633                            mUnsetPressedState.run();
11634                        }
11635
11636                        removeTapCallback();
11637                    }
11638                    mIgnoreNextUpEvent = false;
11639                    break;
11640
11641                case MotionEvent.ACTION_DOWN:
11642                    mHasPerformedLongPress = false;
11643
11644                    if (!clickable) {
11645                        checkForLongClick(0, x, y);
11646                        break;
11647                    }
11648
11649                    if (performButtonActionOnTouchDown(event)) {
11650                        break;
11651                    }
11652
11653                    // Walk up the hierarchy to determine if we're inside a scrolling container.
11654                    boolean isInScrollingContainer = isInScrollingContainer();
11655
11656                    // For views inside a scrolling container, delay the pressed feedback for
11657                    // a short period in case this is a scroll.
11658                    if (isInScrollingContainer) {
11659                        mPrivateFlags |= PFLAG_PREPRESSED;
11660                        if (mPendingCheckForTap == null) {
11661                            mPendingCheckForTap = new CheckForTap();
11662                        }
11663                        mPendingCheckForTap.x = event.getX();
11664                        mPendingCheckForTap.y = event.getY();
11665                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
11666                    } else {
11667                        // Not inside a scrolling container, so show the feedback right away
11668                        setPressed(true, x, y);
11669                        checkForLongClick(0, x, y);
11670                    }
11671                    break;
11672
11673                case MotionEvent.ACTION_CANCEL:
11674                    if (clickable) {
11675                        setPressed(false);
11676                    }
11677                    removeTapCallback();
11678                    removeLongPressCallback();
11679                    mInContextButtonPress = false;
11680                    mHasPerformedLongPress = false;
11681                    mIgnoreNextUpEvent = false;
11682                    break;
11683
11684                case MotionEvent.ACTION_MOVE:
11685                    if (clickable) {
11686                        drawableHotspotChanged(x, y);
11687                    }
11688
11689                    // Be lenient about moving outside of buttons
11690                    if (!pointInView(x, y, mTouchSlop)) {
11691                        // Outside button
11692                        // Remove any future long press/tap checks
11693                        removeTapCallback();
11694                        removeLongPressCallback();
11695                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
11696                            setPressed(false);
11697                        }
11698                    }
11699                    break;
11700            }
11701
11702            return true;
11703        }
11704
11705        return false;
11706    }
11707
11708    /**
11709     * @hide
11710     */
11711    public boolean isInScrollingContainer() {
11712        ViewParent p = getParent();
11713        while (p != null && p instanceof ViewGroup) {
11714            if (((ViewGroup) p).shouldDelayChildPressedState()) {
11715                return true;
11716            }
11717            p = p.getParent();
11718        }
11719        return false;
11720    }
11721
11722    /**
11723     * Remove the longpress detection timer.
11724     */
11725    private void removeLongPressCallback() {
11726        if (mPendingCheckForLongPress != null) {
11727            removeCallbacks(mPendingCheckForLongPress);
11728        }
11729    }
11730
11731    /**
11732     * Remove the pending click action
11733     */
11734    private void removePerformClickCallback() {
11735        if (mPerformClick != null) {
11736            removeCallbacks(mPerformClick);
11737        }
11738    }
11739
11740    /**
11741     * Remove the prepress detection timer.
11742     */
11743    private void removeUnsetPressCallback() {
11744        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
11745            setPressed(false);
11746            removeCallbacks(mUnsetPressedState);
11747        }
11748    }
11749
11750    /**
11751     * Remove the tap detection timer.
11752     */
11753    private void removeTapCallback() {
11754        if (mPendingCheckForTap != null) {
11755            mPrivateFlags &= ~PFLAG_PREPRESSED;
11756            removeCallbacks(mPendingCheckForTap);
11757        }
11758    }
11759
11760    /**
11761     * Cancels a pending long press.  Your subclass can use this if you
11762     * want the context menu to come up if the user presses and holds
11763     * at the same place, but you don't want it to come up if they press
11764     * and then move around enough to cause scrolling.
11765     */
11766    public void cancelLongPress() {
11767        removeLongPressCallback();
11768
11769        /*
11770         * The prepressed state handled by the tap callback is a display
11771         * construct, but the tap callback will post a long press callback
11772         * less its own timeout. Remove it here.
11773         */
11774        removeTapCallback();
11775    }
11776
11777    /**
11778     * Remove the pending callback for sending a
11779     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
11780     */
11781    private void removeSendViewScrolledAccessibilityEventCallback() {
11782        if (mSendViewScrolledAccessibilityEvent != null) {
11783            removeCallbacks(mSendViewScrolledAccessibilityEvent);
11784            mSendViewScrolledAccessibilityEvent.mIsPending = false;
11785        }
11786    }
11787
11788    /**
11789     * Sets the TouchDelegate for this View.
11790     */
11791    public void setTouchDelegate(TouchDelegate delegate) {
11792        mTouchDelegate = delegate;
11793    }
11794
11795    /**
11796     * Gets the TouchDelegate for this View.
11797     */
11798    public TouchDelegate getTouchDelegate() {
11799        return mTouchDelegate;
11800    }
11801
11802    /**
11803     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
11804     *
11805     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
11806     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
11807     * available. This method should only be called for touch events.
11808     *
11809     * <p class="note">This api is not intended for most applications. Buffered dispatch
11810     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
11811     * streams will not improve your input latency. Side effects include: increased latency,
11812     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
11813     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
11814     * you.</p>
11815     */
11816    public final void requestUnbufferedDispatch(MotionEvent event) {
11817        final int action = event.getAction();
11818        if (mAttachInfo == null
11819                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
11820                || !event.isTouchEvent()) {
11821            return;
11822        }
11823        mAttachInfo.mUnbufferedDispatchRequested = true;
11824    }
11825
11826    /**
11827     * Set flags controlling behavior of this view.
11828     *
11829     * @param flags Constant indicating the value which should be set
11830     * @param mask Constant indicating the bit range that should be changed
11831     */
11832    void setFlags(int flags, int mask) {
11833        final boolean accessibilityEnabled =
11834                AccessibilityManager.getInstance(mContext).isEnabled();
11835        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
11836
11837        int old = mViewFlags;
11838        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
11839
11840        int changed = mViewFlags ^ old;
11841        if (changed == 0) {
11842            return;
11843        }
11844        int privateFlags = mPrivateFlags;
11845
11846        /* Check if the FOCUSABLE bit has changed */
11847        if (((changed & FOCUSABLE_MASK) != 0) &&
11848                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
11849            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
11850                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
11851                /* Give up focus if we are no longer focusable */
11852                clearFocus();
11853            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
11854                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
11855                /*
11856                 * Tell the view system that we are now available to take focus
11857                 * if no one else already has it.
11858                 */
11859                if (mParent != null) mParent.focusableViewAvailable(this);
11860            }
11861        }
11862
11863        final int newVisibility = flags & VISIBILITY_MASK;
11864        if (newVisibility == VISIBLE) {
11865            if ((changed & VISIBILITY_MASK) != 0) {
11866                /*
11867                 * If this view is becoming visible, invalidate it in case it changed while
11868                 * it was not visible. Marking it drawn ensures that the invalidation will
11869                 * go through.
11870                 */
11871                mPrivateFlags |= PFLAG_DRAWN;
11872                invalidate(true);
11873
11874                needGlobalAttributesUpdate(true);
11875
11876                // a view becoming visible is worth notifying the parent
11877                // about in case nothing has focus.  even if this specific view
11878                // isn't focusable, it may contain something that is, so let
11879                // the root view try to give this focus if nothing else does.
11880                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
11881                    mParent.focusableViewAvailable(this);
11882                }
11883            }
11884        }
11885
11886        /* Check if the GONE bit has changed */
11887        if ((changed & GONE) != 0) {
11888            needGlobalAttributesUpdate(false);
11889            requestLayout();
11890
11891            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
11892                if (hasFocus()) clearFocus();
11893                clearAccessibilityFocus();
11894                destroyDrawingCache();
11895                if (mParent instanceof View) {
11896                    // GONE views noop invalidation, so invalidate the parent
11897                    ((View) mParent).invalidate(true);
11898                }
11899                // Mark the view drawn to ensure that it gets invalidated properly the next
11900                // time it is visible and gets invalidated
11901                mPrivateFlags |= PFLAG_DRAWN;
11902            }
11903            if (mAttachInfo != null) {
11904                mAttachInfo.mViewVisibilityChanged = true;
11905            }
11906        }
11907
11908        /* Check if the VISIBLE bit has changed */
11909        if ((changed & INVISIBLE) != 0) {
11910            needGlobalAttributesUpdate(false);
11911            /*
11912             * If this view is becoming invisible, set the DRAWN flag so that
11913             * the next invalidate() will not be skipped.
11914             */
11915            mPrivateFlags |= PFLAG_DRAWN;
11916
11917            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
11918                // root view becoming invisible shouldn't clear focus and accessibility focus
11919                if (getRootView() != this) {
11920                    if (hasFocus()) clearFocus();
11921                    clearAccessibilityFocus();
11922                }
11923            }
11924            if (mAttachInfo != null) {
11925                mAttachInfo.mViewVisibilityChanged = true;
11926            }
11927        }
11928
11929        if ((changed & VISIBILITY_MASK) != 0) {
11930            // If the view is invisible, cleanup its display list to free up resources
11931            if (newVisibility != VISIBLE && mAttachInfo != null) {
11932                cleanupDraw();
11933            }
11934
11935            if (mParent instanceof ViewGroup) {
11936                ((ViewGroup) mParent).onChildVisibilityChanged(this,
11937                        (changed & VISIBILITY_MASK), newVisibility);
11938                ((View) mParent).invalidate(true);
11939            } else if (mParent != null) {
11940                mParent.invalidateChild(this, null);
11941            }
11942
11943            if (mAttachInfo != null) {
11944                dispatchVisibilityChanged(this, newVisibility);
11945
11946                // Aggregated visibility changes are dispatched to attached views
11947                // in visible windows where the parent is currently shown/drawn
11948                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
11949                // discounting clipping or overlapping. This makes it a good place
11950                // to change animation states.
11951                if (mParent != null && getWindowVisibility() == VISIBLE &&
11952                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
11953                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
11954                }
11955                notifySubtreeAccessibilityStateChangedIfNeeded();
11956            }
11957        }
11958
11959        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
11960            destroyDrawingCache();
11961        }
11962
11963        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
11964            destroyDrawingCache();
11965            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11966            invalidateParentCaches();
11967        }
11968
11969        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
11970            destroyDrawingCache();
11971            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11972        }
11973
11974        if ((changed & DRAW_MASK) != 0) {
11975            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
11976                if (mBackground != null
11977                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
11978                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11979                } else {
11980                    mPrivateFlags |= PFLAG_SKIP_DRAW;
11981                }
11982            } else {
11983                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
11984            }
11985            requestLayout();
11986            invalidate(true);
11987        }
11988
11989        if ((changed & KEEP_SCREEN_ON) != 0) {
11990            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
11991                mParent.recomputeViewAttributes(this);
11992            }
11993        }
11994
11995        if (accessibilityEnabled) {
11996            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
11997                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
11998                    || (changed & CONTEXT_CLICKABLE) != 0) {
11999                if (oldIncludeForAccessibility != includeForAccessibility()) {
12000                    notifySubtreeAccessibilityStateChangedIfNeeded();
12001                } else {
12002                    notifyViewAccessibilityStateChangedIfNeeded(
12003                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12004                }
12005            } else if ((changed & ENABLED_MASK) != 0) {
12006                notifyViewAccessibilityStateChangedIfNeeded(
12007                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12008            }
12009        }
12010    }
12011
12012    /**
12013     * Change the view's z order in the tree, so it's on top of other sibling
12014     * views. This ordering change may affect layout, if the parent container
12015     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
12016     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
12017     * method should be followed by calls to {@link #requestLayout()} and
12018     * {@link View#invalidate()} on the view's parent to force the parent to redraw
12019     * with the new child ordering.
12020     *
12021     * @see ViewGroup#bringChildToFront(View)
12022     */
12023    public void bringToFront() {
12024        if (mParent != null) {
12025            mParent.bringChildToFront(this);
12026        }
12027    }
12028
12029    /**
12030     * This is called in response to an internal scroll in this view (i.e., the
12031     * view scrolled its own contents). This is typically as a result of
12032     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
12033     * called.
12034     *
12035     * @param l Current horizontal scroll origin.
12036     * @param t Current vertical scroll origin.
12037     * @param oldl Previous horizontal scroll origin.
12038     * @param oldt Previous vertical scroll origin.
12039     */
12040    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
12041        notifySubtreeAccessibilityStateChangedIfNeeded();
12042
12043        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
12044            postSendViewScrolledAccessibilityEventCallback();
12045        }
12046
12047        mBackgroundSizeChanged = true;
12048        if (mForegroundInfo != null) {
12049            mForegroundInfo.mBoundsChanged = true;
12050        }
12051
12052        final AttachInfo ai = mAttachInfo;
12053        if (ai != null) {
12054            ai.mViewScrollChanged = true;
12055        }
12056
12057        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
12058            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
12059        }
12060    }
12061
12062    /**
12063     * Interface definition for a callback to be invoked when the scroll
12064     * X or Y positions of a view change.
12065     * <p>
12066     * <b>Note:</b> Some views handle scrolling independently from View and may
12067     * have their own separate listeners for scroll-type events. For example,
12068     * {@link android.widget.ListView ListView} allows clients to register an
12069     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
12070     * to listen for changes in list scroll position.
12071     *
12072     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
12073     */
12074    public interface OnScrollChangeListener {
12075        /**
12076         * Called when the scroll position of a view changes.
12077         *
12078         * @param v The view whose scroll position has changed.
12079         * @param scrollX Current horizontal scroll origin.
12080         * @param scrollY Current vertical scroll origin.
12081         * @param oldScrollX Previous horizontal scroll origin.
12082         * @param oldScrollY Previous vertical scroll origin.
12083         */
12084        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
12085    }
12086
12087    /**
12088     * Interface definition for a callback to be invoked when the layout bounds of a view
12089     * changes due to layout processing.
12090     */
12091    public interface OnLayoutChangeListener {
12092        /**
12093         * Called when the layout bounds of a view changes due to layout processing.
12094         *
12095         * @param v The view whose bounds have changed.
12096         * @param left The new value of the view's left property.
12097         * @param top The new value of the view's top property.
12098         * @param right The new value of the view's right property.
12099         * @param bottom The new value of the view's bottom property.
12100         * @param oldLeft The previous value of the view's left property.
12101         * @param oldTop The previous value of the view's top property.
12102         * @param oldRight The previous value of the view's right property.
12103         * @param oldBottom The previous value of the view's bottom property.
12104         */
12105        void onLayoutChange(View v, int left, int top, int right, int bottom,
12106            int oldLeft, int oldTop, int oldRight, int oldBottom);
12107    }
12108
12109    /**
12110     * This is called during layout when the size of this view has changed. If
12111     * you were just added to the view hierarchy, you're called with the old
12112     * values of 0.
12113     *
12114     * @param w Current width of this view.
12115     * @param h Current height of this view.
12116     * @param oldw Old width of this view.
12117     * @param oldh Old height of this view.
12118     */
12119    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
12120    }
12121
12122    /**
12123     * Called by draw to draw the child views. This may be overridden
12124     * by derived classes to gain control just before its children are drawn
12125     * (but after its own view has been drawn).
12126     * @param canvas the canvas on which to draw the view
12127     */
12128    protected void dispatchDraw(Canvas canvas) {
12129
12130    }
12131
12132    /**
12133     * Gets the parent of this view. Note that the parent is a
12134     * ViewParent and not necessarily a View.
12135     *
12136     * @return Parent of this view.
12137     */
12138    public final ViewParent getParent() {
12139        return mParent;
12140    }
12141
12142    /**
12143     * Set the horizontal scrolled position of your view. This will cause a call to
12144     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12145     * invalidated.
12146     * @param value the x position to scroll to
12147     */
12148    public void setScrollX(int value) {
12149        scrollTo(value, mScrollY);
12150    }
12151
12152    /**
12153     * Set the vertical scrolled position of your view. This will cause a call to
12154     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12155     * invalidated.
12156     * @param value the y position to scroll to
12157     */
12158    public void setScrollY(int value) {
12159        scrollTo(mScrollX, value);
12160    }
12161
12162    /**
12163     * Return the scrolled left position of this view. This is the left edge of
12164     * the displayed part of your view. You do not need to draw any pixels
12165     * farther left, since those are outside of the frame of your view on
12166     * screen.
12167     *
12168     * @return The left edge of the displayed part of your view, in pixels.
12169     */
12170    public final int getScrollX() {
12171        return mScrollX;
12172    }
12173
12174    /**
12175     * Return the scrolled top position of this view. This is the top edge of
12176     * the displayed part of your view. You do not need to draw any pixels above
12177     * it, since those are outside of the frame of your view on screen.
12178     *
12179     * @return The top edge of the displayed part of your view, in pixels.
12180     */
12181    public final int getScrollY() {
12182        return mScrollY;
12183    }
12184
12185    /**
12186     * Return the width of the your view.
12187     *
12188     * @return The width of your view, in pixels.
12189     */
12190    @ViewDebug.ExportedProperty(category = "layout")
12191    public final int getWidth() {
12192        return mRight - mLeft;
12193    }
12194
12195    /**
12196     * Return the height of your view.
12197     *
12198     * @return The height of your view, in pixels.
12199     */
12200    @ViewDebug.ExportedProperty(category = "layout")
12201    public final int getHeight() {
12202        return mBottom - mTop;
12203    }
12204
12205    /**
12206     * Return the visible drawing bounds of your view. Fills in the output
12207     * rectangle with the values from getScrollX(), getScrollY(),
12208     * getWidth(), and getHeight(). These bounds do not account for any
12209     * transformation properties currently set on the view, such as
12210     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
12211     *
12212     * @param outRect The (scrolled) drawing bounds of the view.
12213     */
12214    public void getDrawingRect(Rect outRect) {
12215        outRect.left = mScrollX;
12216        outRect.top = mScrollY;
12217        outRect.right = mScrollX + (mRight - mLeft);
12218        outRect.bottom = mScrollY + (mBottom - mTop);
12219    }
12220
12221    /**
12222     * Like {@link #getMeasuredWidthAndState()}, but only returns the
12223     * raw width component (that is the result is masked by
12224     * {@link #MEASURED_SIZE_MASK}).
12225     *
12226     * @return The raw measured width of this view.
12227     */
12228    public final int getMeasuredWidth() {
12229        return mMeasuredWidth & MEASURED_SIZE_MASK;
12230    }
12231
12232    /**
12233     * Return the full width measurement information for this view as computed
12234     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
12235     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
12236     * This should be used during measurement and layout calculations only. Use
12237     * {@link #getWidth()} to see how wide a view is after layout.
12238     *
12239     * @return The measured width of this view as a bit mask.
12240     */
12241    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
12242            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
12243                    name = "MEASURED_STATE_TOO_SMALL"),
12244    })
12245    public final int getMeasuredWidthAndState() {
12246        return mMeasuredWidth;
12247    }
12248
12249    /**
12250     * Like {@link #getMeasuredHeightAndState()}, but only returns the
12251     * raw height component (that is the result is masked by
12252     * {@link #MEASURED_SIZE_MASK}).
12253     *
12254     * @return The raw measured height of this view.
12255     */
12256    public final int getMeasuredHeight() {
12257        return mMeasuredHeight & MEASURED_SIZE_MASK;
12258    }
12259
12260    /**
12261     * Return the full height measurement information for this view as computed
12262     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
12263     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
12264     * This should be used during measurement and layout calculations only. Use
12265     * {@link #getHeight()} to see how wide a view is after layout.
12266     *
12267     * @return The measured height of this view as a bit mask.
12268     */
12269    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
12270            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
12271                    name = "MEASURED_STATE_TOO_SMALL"),
12272    })
12273    public final int getMeasuredHeightAndState() {
12274        return mMeasuredHeight;
12275    }
12276
12277    /**
12278     * Return only the state bits of {@link #getMeasuredWidthAndState()}
12279     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
12280     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
12281     * and the height component is at the shifted bits
12282     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
12283     */
12284    public final int getMeasuredState() {
12285        return (mMeasuredWidth&MEASURED_STATE_MASK)
12286                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
12287                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
12288    }
12289
12290    /**
12291     * The transform matrix of this view, which is calculated based on the current
12292     * rotation, scale, and pivot properties.
12293     *
12294     * @see #getRotation()
12295     * @see #getScaleX()
12296     * @see #getScaleY()
12297     * @see #getPivotX()
12298     * @see #getPivotY()
12299     * @return The current transform matrix for the view
12300     */
12301    public Matrix getMatrix() {
12302        ensureTransformationInfo();
12303        final Matrix matrix = mTransformationInfo.mMatrix;
12304        mRenderNode.getMatrix(matrix);
12305        return matrix;
12306    }
12307
12308    /**
12309     * Returns true if the transform matrix is the identity matrix.
12310     * Recomputes the matrix if necessary.
12311     *
12312     * @return True if the transform matrix is the identity matrix, false otherwise.
12313     */
12314    final boolean hasIdentityMatrix() {
12315        return mRenderNode.hasIdentityMatrix();
12316    }
12317
12318    void ensureTransformationInfo() {
12319        if (mTransformationInfo == null) {
12320            mTransformationInfo = new TransformationInfo();
12321        }
12322    }
12323
12324    /**
12325     * Utility method to retrieve the inverse of the current mMatrix property.
12326     * We cache the matrix to avoid recalculating it when transform properties
12327     * have not changed.
12328     *
12329     * @return The inverse of the current matrix of this view.
12330     * @hide
12331     */
12332    public final Matrix getInverseMatrix() {
12333        ensureTransformationInfo();
12334        if (mTransformationInfo.mInverseMatrix == null) {
12335            mTransformationInfo.mInverseMatrix = new Matrix();
12336        }
12337        final Matrix matrix = mTransformationInfo.mInverseMatrix;
12338        mRenderNode.getInverseMatrix(matrix);
12339        return matrix;
12340    }
12341
12342    /**
12343     * Gets the distance along the Z axis from the camera to this view.
12344     *
12345     * @see #setCameraDistance(float)
12346     *
12347     * @return The distance along the Z axis.
12348     */
12349    public float getCameraDistance() {
12350        final float dpi = mResources.getDisplayMetrics().densityDpi;
12351        return -(mRenderNode.getCameraDistance() * dpi);
12352    }
12353
12354    /**
12355     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
12356     * views are drawn) from the camera to this view. The camera's distance
12357     * affects 3D transformations, for instance rotations around the X and Y
12358     * axis. If the rotationX or rotationY properties are changed and this view is
12359     * large (more than half the size of the screen), it is recommended to always
12360     * use a camera distance that's greater than the height (X axis rotation) or
12361     * the width (Y axis rotation) of this view.</p>
12362     *
12363     * <p>The distance of the camera from the view plane can have an affect on the
12364     * perspective distortion of the view when it is rotated around the x or y axis.
12365     * For example, a large distance will result in a large viewing angle, and there
12366     * will not be much perspective distortion of the view as it rotates. A short
12367     * distance may cause much more perspective distortion upon rotation, and can
12368     * also result in some drawing artifacts if the rotated view ends up partially
12369     * behind the camera (which is why the recommendation is to use a distance at
12370     * least as far as the size of the view, if the view is to be rotated.)</p>
12371     *
12372     * <p>The distance is expressed in "depth pixels." The default distance depends
12373     * on the screen density. For instance, on a medium density display, the
12374     * default distance is 1280. On a high density display, the default distance
12375     * is 1920.</p>
12376     *
12377     * <p>If you want to specify a distance that leads to visually consistent
12378     * results across various densities, use the following formula:</p>
12379     * <pre>
12380     * float scale = context.getResources().getDisplayMetrics().density;
12381     * view.setCameraDistance(distance * scale);
12382     * </pre>
12383     *
12384     * <p>The density scale factor of a high density display is 1.5,
12385     * and 1920 = 1280 * 1.5.</p>
12386     *
12387     * @param distance The distance in "depth pixels", if negative the opposite
12388     *        value is used
12389     *
12390     * @see #setRotationX(float)
12391     * @see #setRotationY(float)
12392     */
12393    public void setCameraDistance(float distance) {
12394        final float dpi = mResources.getDisplayMetrics().densityDpi;
12395
12396        invalidateViewProperty(true, false);
12397        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
12398        invalidateViewProperty(false, false);
12399
12400        invalidateParentIfNeededAndWasQuickRejected();
12401    }
12402
12403    /**
12404     * The degrees that the view is rotated around the pivot point.
12405     *
12406     * @see #setRotation(float)
12407     * @see #getPivotX()
12408     * @see #getPivotY()
12409     *
12410     * @return The degrees of rotation.
12411     */
12412    @ViewDebug.ExportedProperty(category = "drawing")
12413    public float getRotation() {
12414        return mRenderNode.getRotation();
12415    }
12416
12417    /**
12418     * Sets the degrees that the view is rotated around the pivot point. Increasing values
12419     * result in clockwise rotation.
12420     *
12421     * @param rotation The degrees of rotation.
12422     *
12423     * @see #getRotation()
12424     * @see #getPivotX()
12425     * @see #getPivotY()
12426     * @see #setRotationX(float)
12427     * @see #setRotationY(float)
12428     *
12429     * @attr ref android.R.styleable#View_rotation
12430     */
12431    public void setRotation(float rotation) {
12432        if (rotation != getRotation()) {
12433            // Double-invalidation is necessary to capture view's old and new areas
12434            invalidateViewProperty(true, false);
12435            mRenderNode.setRotation(rotation);
12436            invalidateViewProperty(false, true);
12437
12438            invalidateParentIfNeededAndWasQuickRejected();
12439            notifySubtreeAccessibilityStateChangedIfNeeded();
12440        }
12441    }
12442
12443    /**
12444     * The degrees that the view is rotated around the vertical axis through the pivot point.
12445     *
12446     * @see #getPivotX()
12447     * @see #getPivotY()
12448     * @see #setRotationY(float)
12449     *
12450     * @return The degrees of Y rotation.
12451     */
12452    @ViewDebug.ExportedProperty(category = "drawing")
12453    public float getRotationY() {
12454        return mRenderNode.getRotationY();
12455    }
12456
12457    /**
12458     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
12459     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
12460     * down the y axis.
12461     *
12462     * When rotating large views, it is recommended to adjust the camera distance
12463     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12464     *
12465     * @param rotationY The degrees of Y rotation.
12466     *
12467     * @see #getRotationY()
12468     * @see #getPivotX()
12469     * @see #getPivotY()
12470     * @see #setRotation(float)
12471     * @see #setRotationX(float)
12472     * @see #setCameraDistance(float)
12473     *
12474     * @attr ref android.R.styleable#View_rotationY
12475     */
12476    public void setRotationY(float rotationY) {
12477        if (rotationY != getRotationY()) {
12478            invalidateViewProperty(true, false);
12479            mRenderNode.setRotationY(rotationY);
12480            invalidateViewProperty(false, true);
12481
12482            invalidateParentIfNeededAndWasQuickRejected();
12483            notifySubtreeAccessibilityStateChangedIfNeeded();
12484        }
12485    }
12486
12487    /**
12488     * The degrees that the view is rotated around the horizontal axis through the pivot point.
12489     *
12490     * @see #getPivotX()
12491     * @see #getPivotY()
12492     * @see #setRotationX(float)
12493     *
12494     * @return The degrees of X rotation.
12495     */
12496    @ViewDebug.ExportedProperty(category = "drawing")
12497    public float getRotationX() {
12498        return mRenderNode.getRotationX();
12499    }
12500
12501    /**
12502     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
12503     * Increasing values result in clockwise rotation from the viewpoint of looking down the
12504     * x axis.
12505     *
12506     * When rotating large views, it is recommended to adjust the camera distance
12507     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12508     *
12509     * @param rotationX The degrees of X rotation.
12510     *
12511     * @see #getRotationX()
12512     * @see #getPivotX()
12513     * @see #getPivotY()
12514     * @see #setRotation(float)
12515     * @see #setRotationY(float)
12516     * @see #setCameraDistance(float)
12517     *
12518     * @attr ref android.R.styleable#View_rotationX
12519     */
12520    public void setRotationX(float rotationX) {
12521        if (rotationX != getRotationX()) {
12522            invalidateViewProperty(true, false);
12523            mRenderNode.setRotationX(rotationX);
12524            invalidateViewProperty(false, true);
12525
12526            invalidateParentIfNeededAndWasQuickRejected();
12527            notifySubtreeAccessibilityStateChangedIfNeeded();
12528        }
12529    }
12530
12531    /**
12532     * The amount that the view is scaled in x around the pivot point, as a proportion of
12533     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
12534     *
12535     * <p>By default, this is 1.0f.
12536     *
12537     * @see #getPivotX()
12538     * @see #getPivotY()
12539     * @return The scaling factor.
12540     */
12541    @ViewDebug.ExportedProperty(category = "drawing")
12542    public float getScaleX() {
12543        return mRenderNode.getScaleX();
12544    }
12545
12546    /**
12547     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
12548     * the view's unscaled width. A value of 1 means that no scaling is applied.
12549     *
12550     * @param scaleX The scaling factor.
12551     * @see #getPivotX()
12552     * @see #getPivotY()
12553     *
12554     * @attr ref android.R.styleable#View_scaleX
12555     */
12556    public void setScaleX(float scaleX) {
12557        if (scaleX != getScaleX()) {
12558            invalidateViewProperty(true, false);
12559            mRenderNode.setScaleX(scaleX);
12560            invalidateViewProperty(false, true);
12561
12562            invalidateParentIfNeededAndWasQuickRejected();
12563            notifySubtreeAccessibilityStateChangedIfNeeded();
12564        }
12565    }
12566
12567    /**
12568     * The amount that the view is scaled in y around the pivot point, as a proportion of
12569     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
12570     *
12571     * <p>By default, this is 1.0f.
12572     *
12573     * @see #getPivotX()
12574     * @see #getPivotY()
12575     * @return The scaling factor.
12576     */
12577    @ViewDebug.ExportedProperty(category = "drawing")
12578    public float getScaleY() {
12579        return mRenderNode.getScaleY();
12580    }
12581
12582    /**
12583     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
12584     * the view's unscaled width. A value of 1 means that no scaling is applied.
12585     *
12586     * @param scaleY The scaling factor.
12587     * @see #getPivotX()
12588     * @see #getPivotY()
12589     *
12590     * @attr ref android.R.styleable#View_scaleY
12591     */
12592    public void setScaleY(float scaleY) {
12593        if (scaleY != getScaleY()) {
12594            invalidateViewProperty(true, false);
12595            mRenderNode.setScaleY(scaleY);
12596            invalidateViewProperty(false, true);
12597
12598            invalidateParentIfNeededAndWasQuickRejected();
12599            notifySubtreeAccessibilityStateChangedIfNeeded();
12600        }
12601    }
12602
12603    /**
12604     * The x location of the point around which the view is {@link #setRotation(float) rotated}
12605     * and {@link #setScaleX(float) scaled}.
12606     *
12607     * @see #getRotation()
12608     * @see #getScaleX()
12609     * @see #getScaleY()
12610     * @see #getPivotY()
12611     * @return The x location of the pivot point.
12612     *
12613     * @attr ref android.R.styleable#View_transformPivotX
12614     */
12615    @ViewDebug.ExportedProperty(category = "drawing")
12616    public float getPivotX() {
12617        return mRenderNode.getPivotX();
12618    }
12619
12620    /**
12621     * Sets the x location of the point around which the view is
12622     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
12623     * By default, the pivot point is centered on the object.
12624     * Setting this property disables this behavior and causes the view to use only the
12625     * explicitly set pivotX and pivotY values.
12626     *
12627     * @param pivotX The x location of the pivot point.
12628     * @see #getRotation()
12629     * @see #getScaleX()
12630     * @see #getScaleY()
12631     * @see #getPivotY()
12632     *
12633     * @attr ref android.R.styleable#View_transformPivotX
12634     */
12635    public void setPivotX(float pivotX) {
12636        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
12637            invalidateViewProperty(true, false);
12638            mRenderNode.setPivotX(pivotX);
12639            invalidateViewProperty(false, true);
12640
12641            invalidateParentIfNeededAndWasQuickRejected();
12642        }
12643    }
12644
12645    /**
12646     * The y location of the point around which the view is {@link #setRotation(float) rotated}
12647     * and {@link #setScaleY(float) scaled}.
12648     *
12649     * @see #getRotation()
12650     * @see #getScaleX()
12651     * @see #getScaleY()
12652     * @see #getPivotY()
12653     * @return The y location of the pivot point.
12654     *
12655     * @attr ref android.R.styleable#View_transformPivotY
12656     */
12657    @ViewDebug.ExportedProperty(category = "drawing")
12658    public float getPivotY() {
12659        return mRenderNode.getPivotY();
12660    }
12661
12662    /**
12663     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
12664     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
12665     * Setting this property disables this behavior and causes the view to use only the
12666     * explicitly set pivotX and pivotY values.
12667     *
12668     * @param pivotY The y location of the pivot point.
12669     * @see #getRotation()
12670     * @see #getScaleX()
12671     * @see #getScaleY()
12672     * @see #getPivotY()
12673     *
12674     * @attr ref android.R.styleable#View_transformPivotY
12675     */
12676    public void setPivotY(float pivotY) {
12677        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
12678            invalidateViewProperty(true, false);
12679            mRenderNode.setPivotY(pivotY);
12680            invalidateViewProperty(false, true);
12681
12682            invalidateParentIfNeededAndWasQuickRejected();
12683        }
12684    }
12685
12686    /**
12687     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
12688     * completely transparent and 1 means the view is completely opaque.
12689     *
12690     * <p>By default this is 1.0f.
12691     * @return The opacity of the view.
12692     */
12693    @ViewDebug.ExportedProperty(category = "drawing")
12694    public float getAlpha() {
12695        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
12696    }
12697
12698    /**
12699     * Sets the behavior for overlapping rendering for this view (see {@link
12700     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
12701     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
12702     * providing the value which is then used internally. That is, when {@link
12703     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
12704     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
12705     * instead.
12706     *
12707     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
12708     * instead of that returned by {@link #hasOverlappingRendering()}.
12709     *
12710     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
12711     */
12712    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
12713        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
12714        if (hasOverlappingRendering) {
12715            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12716        } else {
12717            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12718        }
12719    }
12720
12721    /**
12722     * Returns the value for overlapping rendering that is used internally. This is either
12723     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
12724     * the return value of {@link #hasOverlappingRendering()}, otherwise.
12725     *
12726     * @return The value for overlapping rendering being used internally.
12727     */
12728    public final boolean getHasOverlappingRendering() {
12729        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
12730                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
12731                hasOverlappingRendering();
12732    }
12733
12734    /**
12735     * Returns whether this View has content which overlaps.
12736     *
12737     * <p>This function, intended to be overridden by specific View types, is an optimization when
12738     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
12739     * an offscreen buffer and then composited into place, which can be expensive. If the view has
12740     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
12741     * directly. An example of overlapping rendering is a TextView with a background image, such as
12742     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
12743     * ImageView with only the foreground image. The default implementation returns true; subclasses
12744     * should override if they have cases which can be optimized.</p>
12745     *
12746     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
12747     * necessitates that a View return true if it uses the methods internally without passing the
12748     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
12749     *
12750     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
12751     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
12752     *
12753     * @return true if the content in this view might overlap, false otherwise.
12754     */
12755    @ViewDebug.ExportedProperty(category = "drawing")
12756    public boolean hasOverlappingRendering() {
12757        return true;
12758    }
12759
12760    /**
12761     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
12762     * completely transparent and 1 means the view is completely opaque.
12763     *
12764     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
12765     * can have significant performance implications, especially for large views. It is best to use
12766     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
12767     *
12768     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
12769     * strongly recommended for performance reasons to either override
12770     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
12771     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
12772     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
12773     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
12774     * of rendering cost, even for simple or small views. Starting with
12775     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
12776     * applied to the view at the rendering level.</p>
12777     *
12778     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
12779     * responsible for applying the opacity itself.</p>
12780     *
12781     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
12782     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
12783     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
12784     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
12785     *
12786     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
12787     * value will clip a View to its bounds, unless the View returns <code>false</code> from
12788     * {@link #hasOverlappingRendering}.</p>
12789     *
12790     * @param alpha The opacity of the view.
12791     *
12792     * @see #hasOverlappingRendering()
12793     * @see #setLayerType(int, android.graphics.Paint)
12794     *
12795     * @attr ref android.R.styleable#View_alpha
12796     */
12797    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
12798        ensureTransformationInfo();
12799        if (mTransformationInfo.mAlpha != alpha) {
12800            // Report visibility changes, which can affect children, to accessibility
12801            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
12802                notifySubtreeAccessibilityStateChangedIfNeeded();
12803            }
12804            mTransformationInfo.mAlpha = alpha;
12805            if (onSetAlpha((int) (alpha * 255))) {
12806                mPrivateFlags |= PFLAG_ALPHA_SET;
12807                // subclass is handling alpha - don't optimize rendering cache invalidation
12808                invalidateParentCaches();
12809                invalidate(true);
12810            } else {
12811                mPrivateFlags &= ~PFLAG_ALPHA_SET;
12812                invalidateViewProperty(true, false);
12813                mRenderNode.setAlpha(getFinalAlpha());
12814            }
12815        }
12816    }
12817
12818    /**
12819     * Faster version of setAlpha() which performs the same steps except there are
12820     * no calls to invalidate(). The caller of this function should perform proper invalidation
12821     * on the parent and this object. The return value indicates whether the subclass handles
12822     * alpha (the return value for onSetAlpha()).
12823     *
12824     * @param alpha The new value for the alpha property
12825     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
12826     *         the new value for the alpha property is different from the old value
12827     */
12828    boolean setAlphaNoInvalidation(float alpha) {
12829        ensureTransformationInfo();
12830        if (mTransformationInfo.mAlpha != alpha) {
12831            mTransformationInfo.mAlpha = alpha;
12832            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
12833            if (subclassHandlesAlpha) {
12834                mPrivateFlags |= PFLAG_ALPHA_SET;
12835                return true;
12836            } else {
12837                mPrivateFlags &= ~PFLAG_ALPHA_SET;
12838                mRenderNode.setAlpha(getFinalAlpha());
12839            }
12840        }
12841        return false;
12842    }
12843
12844    /**
12845     * This property is hidden and intended only for use by the Fade transition, which
12846     * animates it to produce a visual translucency that does not side-effect (or get
12847     * affected by) the real alpha property. This value is composited with the other
12848     * alpha value (and the AlphaAnimation value, when that is present) to produce
12849     * a final visual translucency result, which is what is passed into the DisplayList.
12850     *
12851     * @hide
12852     */
12853    public void setTransitionAlpha(float alpha) {
12854        ensureTransformationInfo();
12855        if (mTransformationInfo.mTransitionAlpha != alpha) {
12856            mTransformationInfo.mTransitionAlpha = alpha;
12857            mPrivateFlags &= ~PFLAG_ALPHA_SET;
12858            invalidateViewProperty(true, false);
12859            mRenderNode.setAlpha(getFinalAlpha());
12860        }
12861    }
12862
12863    /**
12864     * Calculates the visual alpha of this view, which is a combination of the actual
12865     * alpha value and the transitionAlpha value (if set).
12866     */
12867    private float getFinalAlpha() {
12868        if (mTransformationInfo != null) {
12869            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
12870        }
12871        return 1;
12872    }
12873
12874    /**
12875     * This property is hidden and intended only for use by the Fade transition, which
12876     * animates it to produce a visual translucency that does not side-effect (or get
12877     * affected by) the real alpha property. This value is composited with the other
12878     * alpha value (and the AlphaAnimation value, when that is present) to produce
12879     * a final visual translucency result, which is what is passed into the DisplayList.
12880     *
12881     * @hide
12882     */
12883    @ViewDebug.ExportedProperty(category = "drawing")
12884    public float getTransitionAlpha() {
12885        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
12886    }
12887
12888    /**
12889     * Top position of this view relative to its parent.
12890     *
12891     * @return The top of this view, in pixels.
12892     */
12893    @ViewDebug.CapturedViewProperty
12894    public final int getTop() {
12895        return mTop;
12896    }
12897
12898    /**
12899     * Sets the top position of this view relative to its parent. This method is meant to be called
12900     * by the layout system and should not generally be called otherwise, because the property
12901     * may be changed at any time by the layout.
12902     *
12903     * @param top The top of this view, in pixels.
12904     */
12905    public final void setTop(int top) {
12906        if (top != mTop) {
12907            final boolean matrixIsIdentity = hasIdentityMatrix();
12908            if (matrixIsIdentity) {
12909                if (mAttachInfo != null) {
12910                    int minTop;
12911                    int yLoc;
12912                    if (top < mTop) {
12913                        minTop = top;
12914                        yLoc = top - mTop;
12915                    } else {
12916                        minTop = mTop;
12917                        yLoc = 0;
12918                    }
12919                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
12920                }
12921            } else {
12922                // Double-invalidation is necessary to capture view's old and new areas
12923                invalidate(true);
12924            }
12925
12926            int width = mRight - mLeft;
12927            int oldHeight = mBottom - mTop;
12928
12929            mTop = top;
12930            mRenderNode.setTop(mTop);
12931
12932            sizeChange(width, mBottom - mTop, width, oldHeight);
12933
12934            if (!matrixIsIdentity) {
12935                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12936                invalidate(true);
12937            }
12938            mBackgroundSizeChanged = true;
12939            if (mForegroundInfo != null) {
12940                mForegroundInfo.mBoundsChanged = true;
12941            }
12942            invalidateParentIfNeeded();
12943            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12944                // View was rejected last time it was drawn by its parent; this may have changed
12945                invalidateParentIfNeeded();
12946            }
12947        }
12948    }
12949
12950    /**
12951     * Bottom position of this view relative to its parent.
12952     *
12953     * @return The bottom of this view, in pixels.
12954     */
12955    @ViewDebug.CapturedViewProperty
12956    public final int getBottom() {
12957        return mBottom;
12958    }
12959
12960    /**
12961     * True if this view has changed since the last time being drawn.
12962     *
12963     * @return The dirty state of this view.
12964     */
12965    public boolean isDirty() {
12966        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
12967    }
12968
12969    /**
12970     * Sets the bottom position of this view relative to its parent. This method is meant to be
12971     * called by the layout system and should not generally be called otherwise, because the
12972     * property may be changed at any time by the layout.
12973     *
12974     * @param bottom The bottom of this view, in pixels.
12975     */
12976    public final void setBottom(int bottom) {
12977        if (bottom != mBottom) {
12978            final boolean matrixIsIdentity = hasIdentityMatrix();
12979            if (matrixIsIdentity) {
12980                if (mAttachInfo != null) {
12981                    int maxBottom;
12982                    if (bottom < mBottom) {
12983                        maxBottom = mBottom;
12984                    } else {
12985                        maxBottom = bottom;
12986                    }
12987                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
12988                }
12989            } else {
12990                // Double-invalidation is necessary to capture view's old and new areas
12991                invalidate(true);
12992            }
12993
12994            int width = mRight - mLeft;
12995            int oldHeight = mBottom - mTop;
12996
12997            mBottom = bottom;
12998            mRenderNode.setBottom(mBottom);
12999
13000            sizeChange(width, mBottom - mTop, width, oldHeight);
13001
13002            if (!matrixIsIdentity) {
13003                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13004                invalidate(true);
13005            }
13006            mBackgroundSizeChanged = true;
13007            if (mForegroundInfo != null) {
13008                mForegroundInfo.mBoundsChanged = true;
13009            }
13010            invalidateParentIfNeeded();
13011            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13012                // View was rejected last time it was drawn by its parent; this may have changed
13013                invalidateParentIfNeeded();
13014            }
13015        }
13016    }
13017
13018    /**
13019     * Left position of this view relative to its parent.
13020     *
13021     * @return The left edge of this view, in pixels.
13022     */
13023    @ViewDebug.CapturedViewProperty
13024    public final int getLeft() {
13025        return mLeft;
13026    }
13027
13028    /**
13029     * Sets the left position of this view relative to its parent. This method is meant to be called
13030     * by the layout system and should not generally be called otherwise, because the property
13031     * may be changed at any time by the layout.
13032     *
13033     * @param left The left of this view, in pixels.
13034     */
13035    public final void setLeft(int left) {
13036        if (left != mLeft) {
13037            final boolean matrixIsIdentity = hasIdentityMatrix();
13038            if (matrixIsIdentity) {
13039                if (mAttachInfo != null) {
13040                    int minLeft;
13041                    int xLoc;
13042                    if (left < mLeft) {
13043                        minLeft = left;
13044                        xLoc = left - mLeft;
13045                    } else {
13046                        minLeft = mLeft;
13047                        xLoc = 0;
13048                    }
13049                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
13050                }
13051            } else {
13052                // Double-invalidation is necessary to capture view's old and new areas
13053                invalidate(true);
13054            }
13055
13056            int oldWidth = mRight - mLeft;
13057            int height = mBottom - mTop;
13058
13059            mLeft = left;
13060            mRenderNode.setLeft(left);
13061
13062            sizeChange(mRight - mLeft, height, oldWidth, height);
13063
13064            if (!matrixIsIdentity) {
13065                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13066                invalidate(true);
13067            }
13068            mBackgroundSizeChanged = true;
13069            if (mForegroundInfo != null) {
13070                mForegroundInfo.mBoundsChanged = true;
13071            }
13072            invalidateParentIfNeeded();
13073            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13074                // View was rejected last time it was drawn by its parent; this may have changed
13075                invalidateParentIfNeeded();
13076            }
13077        }
13078    }
13079
13080    /**
13081     * Right position of this view relative to its parent.
13082     *
13083     * @return The right edge of this view, in pixels.
13084     */
13085    @ViewDebug.CapturedViewProperty
13086    public final int getRight() {
13087        return mRight;
13088    }
13089
13090    /**
13091     * Sets the right position of this view relative to its parent. This method is meant to be called
13092     * by the layout system and should not generally be called otherwise, because the property
13093     * may be changed at any time by the layout.
13094     *
13095     * @param right The right of this view, in pixels.
13096     */
13097    public final void setRight(int right) {
13098        if (right != mRight) {
13099            final boolean matrixIsIdentity = hasIdentityMatrix();
13100            if (matrixIsIdentity) {
13101                if (mAttachInfo != null) {
13102                    int maxRight;
13103                    if (right < mRight) {
13104                        maxRight = mRight;
13105                    } else {
13106                        maxRight = right;
13107                    }
13108                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
13109                }
13110            } else {
13111                // Double-invalidation is necessary to capture view's old and new areas
13112                invalidate(true);
13113            }
13114
13115            int oldWidth = mRight - mLeft;
13116            int height = mBottom - mTop;
13117
13118            mRight = right;
13119            mRenderNode.setRight(mRight);
13120
13121            sizeChange(mRight - mLeft, height, oldWidth, height);
13122
13123            if (!matrixIsIdentity) {
13124                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13125                invalidate(true);
13126            }
13127            mBackgroundSizeChanged = true;
13128            if (mForegroundInfo != null) {
13129                mForegroundInfo.mBoundsChanged = true;
13130            }
13131            invalidateParentIfNeeded();
13132            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13133                // View was rejected last time it was drawn by its parent; this may have changed
13134                invalidateParentIfNeeded();
13135            }
13136        }
13137    }
13138
13139    /**
13140     * The visual x position of this view, in pixels. This is equivalent to the
13141     * {@link #setTranslationX(float) translationX} property plus the current
13142     * {@link #getLeft() left} property.
13143     *
13144     * @return The visual x position of this view, in pixels.
13145     */
13146    @ViewDebug.ExportedProperty(category = "drawing")
13147    public float getX() {
13148        return mLeft + getTranslationX();
13149    }
13150
13151    /**
13152     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
13153     * {@link #setTranslationX(float) translationX} property to be the difference between
13154     * the x value passed in and the current {@link #getLeft() left} property.
13155     *
13156     * @param x The visual x position of this view, in pixels.
13157     */
13158    public void setX(float x) {
13159        setTranslationX(x - mLeft);
13160    }
13161
13162    /**
13163     * The visual y position of this view, in pixels. This is equivalent to the
13164     * {@link #setTranslationY(float) translationY} property plus the current
13165     * {@link #getTop() top} property.
13166     *
13167     * @return The visual y position of this view, in pixels.
13168     */
13169    @ViewDebug.ExportedProperty(category = "drawing")
13170    public float getY() {
13171        return mTop + getTranslationY();
13172    }
13173
13174    /**
13175     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
13176     * {@link #setTranslationY(float) translationY} property to be the difference between
13177     * the y value passed in and the current {@link #getTop() top} property.
13178     *
13179     * @param y The visual y position of this view, in pixels.
13180     */
13181    public void setY(float y) {
13182        setTranslationY(y - mTop);
13183    }
13184
13185    /**
13186     * The visual z position of this view, in pixels. This is equivalent to the
13187     * {@link #setTranslationZ(float) translationZ} property plus the current
13188     * {@link #getElevation() elevation} property.
13189     *
13190     * @return The visual z position of this view, in pixels.
13191     */
13192    @ViewDebug.ExportedProperty(category = "drawing")
13193    public float getZ() {
13194        return getElevation() + getTranslationZ();
13195    }
13196
13197    /**
13198     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
13199     * {@link #setTranslationZ(float) translationZ} property to be the difference between
13200     * the x value passed in and the current {@link #getElevation() elevation} property.
13201     *
13202     * @param z The visual z position of this view, in pixels.
13203     */
13204    public void setZ(float z) {
13205        setTranslationZ(z - getElevation());
13206    }
13207
13208    /**
13209     * The base elevation of this view relative to its parent, in pixels.
13210     *
13211     * @return The base depth position of the view, in pixels.
13212     */
13213    @ViewDebug.ExportedProperty(category = "drawing")
13214    public float getElevation() {
13215        return mRenderNode.getElevation();
13216    }
13217
13218    /**
13219     * Sets the base elevation of this view, in pixels.
13220     *
13221     * @attr ref android.R.styleable#View_elevation
13222     */
13223    public void setElevation(float elevation) {
13224        if (elevation != getElevation()) {
13225            invalidateViewProperty(true, false);
13226            mRenderNode.setElevation(elevation);
13227            invalidateViewProperty(false, true);
13228
13229            invalidateParentIfNeededAndWasQuickRejected();
13230        }
13231    }
13232
13233    /**
13234     * The horizontal location of this view relative to its {@link #getLeft() left} position.
13235     * This position is post-layout, in addition to wherever the object's
13236     * layout placed it.
13237     *
13238     * @return The horizontal position of this view relative to its left position, in pixels.
13239     */
13240    @ViewDebug.ExportedProperty(category = "drawing")
13241    public float getTranslationX() {
13242        return mRenderNode.getTranslationX();
13243    }
13244
13245    /**
13246     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
13247     * This effectively positions the object post-layout, in addition to wherever the object's
13248     * layout placed it.
13249     *
13250     * @param translationX The horizontal position of this view relative to its left position,
13251     * in pixels.
13252     *
13253     * @attr ref android.R.styleable#View_translationX
13254     */
13255    public void setTranslationX(float translationX) {
13256        if (translationX != getTranslationX()) {
13257            invalidateViewProperty(true, false);
13258            mRenderNode.setTranslationX(translationX);
13259            invalidateViewProperty(false, true);
13260
13261            invalidateParentIfNeededAndWasQuickRejected();
13262            notifySubtreeAccessibilityStateChangedIfNeeded();
13263        }
13264    }
13265
13266    /**
13267     * The vertical location of this view relative to its {@link #getTop() top} position.
13268     * This position is post-layout, in addition to wherever the object's
13269     * layout placed it.
13270     *
13271     * @return The vertical position of this view relative to its top position,
13272     * in pixels.
13273     */
13274    @ViewDebug.ExportedProperty(category = "drawing")
13275    public float getTranslationY() {
13276        return mRenderNode.getTranslationY();
13277    }
13278
13279    /**
13280     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
13281     * This effectively positions the object post-layout, in addition to wherever the object's
13282     * layout placed it.
13283     *
13284     * @param translationY The vertical position of this view relative to its top position,
13285     * in pixels.
13286     *
13287     * @attr ref android.R.styleable#View_translationY
13288     */
13289    public void setTranslationY(float translationY) {
13290        if (translationY != getTranslationY()) {
13291            invalidateViewProperty(true, false);
13292            mRenderNode.setTranslationY(translationY);
13293            invalidateViewProperty(false, true);
13294
13295            invalidateParentIfNeededAndWasQuickRejected();
13296            notifySubtreeAccessibilityStateChangedIfNeeded();
13297        }
13298    }
13299
13300    /**
13301     * The depth location of this view relative to its {@link #getElevation() elevation}.
13302     *
13303     * @return The depth of this view relative to its elevation.
13304     */
13305    @ViewDebug.ExportedProperty(category = "drawing")
13306    public float getTranslationZ() {
13307        return mRenderNode.getTranslationZ();
13308    }
13309
13310    /**
13311     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
13312     *
13313     * @attr ref android.R.styleable#View_translationZ
13314     */
13315    public void setTranslationZ(float translationZ) {
13316        if (translationZ != getTranslationZ()) {
13317            invalidateViewProperty(true, false);
13318            mRenderNode.setTranslationZ(translationZ);
13319            invalidateViewProperty(false, true);
13320
13321            invalidateParentIfNeededAndWasQuickRejected();
13322        }
13323    }
13324
13325    /** @hide */
13326    public void setAnimationMatrix(Matrix matrix) {
13327        invalidateViewProperty(true, false);
13328        mRenderNode.setAnimationMatrix(matrix);
13329        invalidateViewProperty(false, true);
13330
13331        invalidateParentIfNeededAndWasQuickRejected();
13332    }
13333
13334    /**
13335     * Returns the current StateListAnimator if exists.
13336     *
13337     * @return StateListAnimator or null if it does not exists
13338     * @see    #setStateListAnimator(android.animation.StateListAnimator)
13339     */
13340    public StateListAnimator getStateListAnimator() {
13341        return mStateListAnimator;
13342    }
13343
13344    /**
13345     * Attaches the provided StateListAnimator to this View.
13346     * <p>
13347     * Any previously attached StateListAnimator will be detached.
13348     *
13349     * @param stateListAnimator The StateListAnimator to update the view
13350     * @see {@link android.animation.StateListAnimator}
13351     */
13352    public void setStateListAnimator(StateListAnimator stateListAnimator) {
13353        if (mStateListAnimator == stateListAnimator) {
13354            return;
13355        }
13356        if (mStateListAnimator != null) {
13357            mStateListAnimator.setTarget(null);
13358        }
13359        mStateListAnimator = stateListAnimator;
13360        if (stateListAnimator != null) {
13361            stateListAnimator.setTarget(this);
13362            if (isAttachedToWindow()) {
13363                stateListAnimator.setState(getDrawableState());
13364            }
13365        }
13366    }
13367
13368    /**
13369     * Returns whether the Outline should be used to clip the contents of the View.
13370     * <p>
13371     * Note that this flag will only be respected if the View's Outline returns true from
13372     * {@link Outline#canClip()}.
13373     *
13374     * @see #setOutlineProvider(ViewOutlineProvider)
13375     * @see #setClipToOutline(boolean)
13376     */
13377    public final boolean getClipToOutline() {
13378        return mRenderNode.getClipToOutline();
13379    }
13380
13381    /**
13382     * Sets whether the View's Outline should be used to clip the contents of the View.
13383     * <p>
13384     * Only a single non-rectangular clip can be applied on a View at any time.
13385     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
13386     * circular reveal} animation take priority over Outline clipping, and
13387     * child Outline clipping takes priority over Outline clipping done by a
13388     * parent.
13389     * <p>
13390     * Note that this flag will only be respected if the View's Outline returns true from
13391     * {@link Outline#canClip()}.
13392     *
13393     * @see #setOutlineProvider(ViewOutlineProvider)
13394     * @see #getClipToOutline()
13395     */
13396    public void setClipToOutline(boolean clipToOutline) {
13397        damageInParent();
13398        if (getClipToOutline() != clipToOutline) {
13399            mRenderNode.setClipToOutline(clipToOutline);
13400        }
13401    }
13402
13403    // correspond to the enum values of View_outlineProvider
13404    private static final int PROVIDER_BACKGROUND = 0;
13405    private static final int PROVIDER_NONE = 1;
13406    private static final int PROVIDER_BOUNDS = 2;
13407    private static final int PROVIDER_PADDED_BOUNDS = 3;
13408    private void setOutlineProviderFromAttribute(int providerInt) {
13409        switch (providerInt) {
13410            case PROVIDER_BACKGROUND:
13411                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
13412                break;
13413            case PROVIDER_NONE:
13414                setOutlineProvider(null);
13415                break;
13416            case PROVIDER_BOUNDS:
13417                setOutlineProvider(ViewOutlineProvider.BOUNDS);
13418                break;
13419            case PROVIDER_PADDED_BOUNDS:
13420                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
13421                break;
13422        }
13423    }
13424
13425    /**
13426     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
13427     * the shape of the shadow it casts, and enables outline clipping.
13428     * <p>
13429     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
13430     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
13431     * outline provider with this method allows this behavior to be overridden.
13432     * <p>
13433     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
13434     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
13435     * <p>
13436     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
13437     *
13438     * @see #setClipToOutline(boolean)
13439     * @see #getClipToOutline()
13440     * @see #getOutlineProvider()
13441     */
13442    public void setOutlineProvider(ViewOutlineProvider provider) {
13443        mOutlineProvider = provider;
13444        invalidateOutline();
13445    }
13446
13447    /**
13448     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
13449     * that defines the shape of the shadow it casts, and enables outline clipping.
13450     *
13451     * @see #setOutlineProvider(ViewOutlineProvider)
13452     */
13453    public ViewOutlineProvider getOutlineProvider() {
13454        return mOutlineProvider;
13455    }
13456
13457    /**
13458     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
13459     *
13460     * @see #setOutlineProvider(ViewOutlineProvider)
13461     */
13462    public void invalidateOutline() {
13463        rebuildOutline();
13464
13465        notifySubtreeAccessibilityStateChangedIfNeeded();
13466        invalidateViewProperty(false, false);
13467    }
13468
13469    /**
13470     * Internal version of {@link #invalidateOutline()} which invalidates the
13471     * outline without invalidating the view itself. This is intended to be called from
13472     * within methods in the View class itself which are the result of the view being
13473     * invalidated already. For example, when we are drawing the background of a View,
13474     * we invalidate the outline in case it changed in the meantime, but we do not
13475     * need to invalidate the view because we're already drawing the background as part
13476     * of drawing the view in response to an earlier invalidation of the view.
13477     */
13478    private void rebuildOutline() {
13479        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
13480        if (mAttachInfo == null) return;
13481
13482        if (mOutlineProvider == null) {
13483            // no provider, remove outline
13484            mRenderNode.setOutline(null);
13485        } else {
13486            final Outline outline = mAttachInfo.mTmpOutline;
13487            outline.setEmpty();
13488            outline.setAlpha(1.0f);
13489
13490            mOutlineProvider.getOutline(this, outline);
13491            mRenderNode.setOutline(outline);
13492        }
13493    }
13494
13495    /**
13496     * HierarchyViewer only
13497     *
13498     * @hide
13499     */
13500    @ViewDebug.ExportedProperty(category = "drawing")
13501    public boolean hasShadow() {
13502        return mRenderNode.hasShadow();
13503    }
13504
13505
13506    /** @hide */
13507    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
13508        mRenderNode.setRevealClip(shouldClip, x, y, radius);
13509        invalidateViewProperty(false, false);
13510    }
13511
13512    /**
13513     * Hit rectangle in parent's coordinates
13514     *
13515     * @param outRect The hit rectangle of the view.
13516     */
13517    public void getHitRect(Rect outRect) {
13518        if (hasIdentityMatrix() || mAttachInfo == null) {
13519            outRect.set(mLeft, mTop, mRight, mBottom);
13520        } else {
13521            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
13522            tmpRect.set(0, 0, getWidth(), getHeight());
13523            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
13524            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
13525                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
13526        }
13527    }
13528
13529    /**
13530     * Determines whether the given point, in local coordinates is inside the view.
13531     */
13532    /*package*/ final boolean pointInView(float localX, float localY) {
13533        return pointInView(localX, localY, 0);
13534    }
13535
13536    /**
13537     * Utility method to determine whether the given point, in local coordinates,
13538     * is inside the view, where the area of the view is expanded by the slop factor.
13539     * This method is called while processing touch-move events to determine if the event
13540     * is still within the view.
13541     *
13542     * @hide
13543     */
13544    public boolean pointInView(float localX, float localY, float slop) {
13545        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
13546                localY < ((mBottom - mTop) + slop);
13547    }
13548
13549    /**
13550     * When a view has focus and the user navigates away from it, the next view is searched for
13551     * starting from the rectangle filled in by this method.
13552     *
13553     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
13554     * of the view.  However, if your view maintains some idea of internal selection,
13555     * such as a cursor, or a selected row or column, you should override this method and
13556     * fill in a more specific rectangle.
13557     *
13558     * @param r The rectangle to fill in, in this view's coordinates.
13559     */
13560    public void getFocusedRect(Rect r) {
13561        getDrawingRect(r);
13562    }
13563
13564    /**
13565     * If some part of this view is not clipped by any of its parents, then
13566     * return that area in r in global (root) coordinates. To convert r to local
13567     * coordinates (without taking possible View rotations into account), offset
13568     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
13569     * If the view is completely clipped or translated out, return false.
13570     *
13571     * @param r If true is returned, r holds the global coordinates of the
13572     *        visible portion of this view.
13573     * @param globalOffset If true is returned, globalOffset holds the dx,dy
13574     *        between this view and its root. globalOffet may be null.
13575     * @return true if r is non-empty (i.e. part of the view is visible at the
13576     *         root level.
13577     */
13578    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
13579        int width = mRight - mLeft;
13580        int height = mBottom - mTop;
13581        if (width > 0 && height > 0) {
13582            r.set(0, 0, width, height);
13583            if (globalOffset != null) {
13584                globalOffset.set(-mScrollX, -mScrollY);
13585            }
13586            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
13587        }
13588        return false;
13589    }
13590
13591    public final boolean getGlobalVisibleRect(Rect r) {
13592        return getGlobalVisibleRect(r, null);
13593    }
13594
13595    public final boolean getLocalVisibleRect(Rect r) {
13596        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
13597        if (getGlobalVisibleRect(r, offset)) {
13598            r.offset(-offset.x, -offset.y); // make r local
13599            return true;
13600        }
13601        return false;
13602    }
13603
13604    /**
13605     * Offset this view's vertical location by the specified number of pixels.
13606     *
13607     * @param offset the number of pixels to offset the view by
13608     */
13609    public void offsetTopAndBottom(int offset) {
13610        if (offset != 0) {
13611            final boolean matrixIsIdentity = hasIdentityMatrix();
13612            if (matrixIsIdentity) {
13613                if (isHardwareAccelerated()) {
13614                    invalidateViewProperty(false, false);
13615                } else {
13616                    final ViewParent p = mParent;
13617                    if (p != null && mAttachInfo != null) {
13618                        final Rect r = mAttachInfo.mTmpInvalRect;
13619                        int minTop;
13620                        int maxBottom;
13621                        int yLoc;
13622                        if (offset < 0) {
13623                            minTop = mTop + offset;
13624                            maxBottom = mBottom;
13625                            yLoc = offset;
13626                        } else {
13627                            minTop = mTop;
13628                            maxBottom = mBottom + offset;
13629                            yLoc = 0;
13630                        }
13631                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
13632                        p.invalidateChild(this, r);
13633                    }
13634                }
13635            } else {
13636                invalidateViewProperty(false, false);
13637            }
13638
13639            mTop += offset;
13640            mBottom += offset;
13641            mRenderNode.offsetTopAndBottom(offset);
13642            if (isHardwareAccelerated()) {
13643                invalidateViewProperty(false, false);
13644                invalidateParentIfNeededAndWasQuickRejected();
13645            } else {
13646                if (!matrixIsIdentity) {
13647                    invalidateViewProperty(false, true);
13648                }
13649                invalidateParentIfNeeded();
13650            }
13651            notifySubtreeAccessibilityStateChangedIfNeeded();
13652        }
13653    }
13654
13655    /**
13656     * Offset this view's horizontal location by the specified amount of pixels.
13657     *
13658     * @param offset the number of pixels to offset the view by
13659     */
13660    public void offsetLeftAndRight(int offset) {
13661        if (offset != 0) {
13662            final boolean matrixIsIdentity = hasIdentityMatrix();
13663            if (matrixIsIdentity) {
13664                if (isHardwareAccelerated()) {
13665                    invalidateViewProperty(false, false);
13666                } else {
13667                    final ViewParent p = mParent;
13668                    if (p != null && mAttachInfo != null) {
13669                        final Rect r = mAttachInfo.mTmpInvalRect;
13670                        int minLeft;
13671                        int maxRight;
13672                        if (offset < 0) {
13673                            minLeft = mLeft + offset;
13674                            maxRight = mRight;
13675                        } else {
13676                            minLeft = mLeft;
13677                            maxRight = mRight + offset;
13678                        }
13679                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
13680                        p.invalidateChild(this, r);
13681                    }
13682                }
13683            } else {
13684                invalidateViewProperty(false, false);
13685            }
13686
13687            mLeft += offset;
13688            mRight += offset;
13689            mRenderNode.offsetLeftAndRight(offset);
13690            if (isHardwareAccelerated()) {
13691                invalidateViewProperty(false, false);
13692                invalidateParentIfNeededAndWasQuickRejected();
13693            } else {
13694                if (!matrixIsIdentity) {
13695                    invalidateViewProperty(false, true);
13696                }
13697                invalidateParentIfNeeded();
13698            }
13699            notifySubtreeAccessibilityStateChangedIfNeeded();
13700        }
13701    }
13702
13703    /**
13704     * Get the LayoutParams associated with this view. All views should have
13705     * layout parameters. These supply parameters to the <i>parent</i> of this
13706     * view specifying how it should be arranged. There are many subclasses of
13707     * ViewGroup.LayoutParams, and these correspond to the different subclasses
13708     * of ViewGroup that are responsible for arranging their children.
13709     *
13710     * This method may return null if this View is not attached to a parent
13711     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
13712     * was not invoked successfully. When a View is attached to a parent
13713     * ViewGroup, this method must not return null.
13714     *
13715     * @return The LayoutParams associated with this view, or null if no
13716     *         parameters have been set yet
13717     */
13718    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
13719    public ViewGroup.LayoutParams getLayoutParams() {
13720        return mLayoutParams;
13721    }
13722
13723    /**
13724     * Set the layout parameters associated with this view. These supply
13725     * parameters to the <i>parent</i> of this view specifying how it should be
13726     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
13727     * correspond to the different subclasses of ViewGroup that are responsible
13728     * for arranging their children.
13729     *
13730     * @param params The layout parameters for this view, cannot be null
13731     */
13732    public void setLayoutParams(ViewGroup.LayoutParams params) {
13733        if (params == null) {
13734            throw new NullPointerException("Layout parameters cannot be null");
13735        }
13736        mLayoutParams = params;
13737        resolveLayoutParams();
13738        if (mParent instanceof ViewGroup) {
13739            ((ViewGroup) mParent).onSetLayoutParams(this, params);
13740        }
13741        requestLayout();
13742    }
13743
13744    /**
13745     * Resolve the layout parameters depending on the resolved layout direction
13746     *
13747     * @hide
13748     */
13749    public void resolveLayoutParams() {
13750        if (mLayoutParams != null) {
13751            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
13752        }
13753    }
13754
13755    /**
13756     * Set the scrolled position of your view. This will cause a call to
13757     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13758     * invalidated.
13759     * @param x the x position to scroll to
13760     * @param y the y position to scroll to
13761     */
13762    public void scrollTo(int x, int y) {
13763        if (mScrollX != x || mScrollY != y) {
13764            int oldX = mScrollX;
13765            int oldY = mScrollY;
13766            mScrollX = x;
13767            mScrollY = y;
13768            invalidateParentCaches();
13769            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
13770            if (!awakenScrollBars()) {
13771                postInvalidateOnAnimation();
13772            }
13773        }
13774    }
13775
13776    /**
13777     * Move the scrolled position of your view. This will cause a call to
13778     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13779     * invalidated.
13780     * @param x the amount of pixels to scroll by horizontally
13781     * @param y the amount of pixels to scroll by vertically
13782     */
13783    public void scrollBy(int x, int y) {
13784        scrollTo(mScrollX + x, mScrollY + y);
13785    }
13786
13787    /**
13788     * <p>Trigger the scrollbars to draw. When invoked this method starts an
13789     * animation to fade the scrollbars out after a default delay. If a subclass
13790     * provides animated scrolling, the start delay should equal the duration
13791     * of the scrolling animation.</p>
13792     *
13793     * <p>The animation starts only if at least one of the scrollbars is
13794     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
13795     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13796     * this method returns true, and false otherwise. If the animation is
13797     * started, this method calls {@link #invalidate()}; in that case the
13798     * caller should not call {@link #invalidate()}.</p>
13799     *
13800     * <p>This method should be invoked every time a subclass directly updates
13801     * the scroll parameters.</p>
13802     *
13803     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
13804     * and {@link #scrollTo(int, int)}.</p>
13805     *
13806     * @return true if the animation is played, false otherwise
13807     *
13808     * @see #awakenScrollBars(int)
13809     * @see #scrollBy(int, int)
13810     * @see #scrollTo(int, int)
13811     * @see #isHorizontalScrollBarEnabled()
13812     * @see #isVerticalScrollBarEnabled()
13813     * @see #setHorizontalScrollBarEnabled(boolean)
13814     * @see #setVerticalScrollBarEnabled(boolean)
13815     */
13816    protected boolean awakenScrollBars() {
13817        return mScrollCache != null &&
13818                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
13819    }
13820
13821    /**
13822     * Trigger the scrollbars to draw.
13823     * This method differs from awakenScrollBars() only in its default duration.
13824     * initialAwakenScrollBars() will show the scroll bars for longer than
13825     * usual to give the user more of a chance to notice them.
13826     *
13827     * @return true if the animation is played, false otherwise.
13828     */
13829    private boolean initialAwakenScrollBars() {
13830        return mScrollCache != null &&
13831                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
13832    }
13833
13834    /**
13835     * <p>
13836     * Trigger the scrollbars to draw. When invoked this method starts an
13837     * animation to fade the scrollbars out after a fixed delay. If a subclass
13838     * provides animated scrolling, the start delay should equal the duration of
13839     * the scrolling animation.
13840     * </p>
13841     *
13842     * <p>
13843     * The animation starts only if at least one of the scrollbars is enabled,
13844     * as specified by {@link #isHorizontalScrollBarEnabled()} and
13845     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13846     * this method returns true, and false otherwise. If the animation is
13847     * started, this method calls {@link #invalidate()}; in that case the caller
13848     * should not call {@link #invalidate()}.
13849     * </p>
13850     *
13851     * <p>
13852     * This method should be invoked every time a subclass directly updates the
13853     * scroll parameters.
13854     * </p>
13855     *
13856     * @param startDelay the delay, in milliseconds, after which the animation
13857     *        should start; when the delay is 0, the animation starts
13858     *        immediately
13859     * @return true if the animation is played, false otherwise
13860     *
13861     * @see #scrollBy(int, int)
13862     * @see #scrollTo(int, int)
13863     * @see #isHorizontalScrollBarEnabled()
13864     * @see #isVerticalScrollBarEnabled()
13865     * @see #setHorizontalScrollBarEnabled(boolean)
13866     * @see #setVerticalScrollBarEnabled(boolean)
13867     */
13868    protected boolean awakenScrollBars(int startDelay) {
13869        return awakenScrollBars(startDelay, true);
13870    }
13871
13872    /**
13873     * <p>
13874     * Trigger the scrollbars to draw. When invoked this method starts an
13875     * animation to fade the scrollbars out after a fixed delay. If a subclass
13876     * provides animated scrolling, the start delay should equal the duration of
13877     * the scrolling animation.
13878     * </p>
13879     *
13880     * <p>
13881     * The animation starts only if at least one of the scrollbars is enabled,
13882     * as specified by {@link #isHorizontalScrollBarEnabled()} and
13883     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
13884     * this method returns true, and false otherwise. If the animation is
13885     * started, this method calls {@link #invalidate()} if the invalidate parameter
13886     * is set to true; in that case the caller
13887     * should not call {@link #invalidate()}.
13888     * </p>
13889     *
13890     * <p>
13891     * This method should be invoked every time a subclass directly updates the
13892     * scroll parameters.
13893     * </p>
13894     *
13895     * @param startDelay the delay, in milliseconds, after which the animation
13896     *        should start; when the delay is 0, the animation starts
13897     *        immediately
13898     *
13899     * @param invalidate Whether this method should call invalidate
13900     *
13901     * @return true if the animation is played, false otherwise
13902     *
13903     * @see #scrollBy(int, int)
13904     * @see #scrollTo(int, int)
13905     * @see #isHorizontalScrollBarEnabled()
13906     * @see #isVerticalScrollBarEnabled()
13907     * @see #setHorizontalScrollBarEnabled(boolean)
13908     * @see #setVerticalScrollBarEnabled(boolean)
13909     */
13910    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
13911        final ScrollabilityCache scrollCache = mScrollCache;
13912
13913        if (scrollCache == null || !scrollCache.fadeScrollBars) {
13914            return false;
13915        }
13916
13917        if (scrollCache.scrollBar == null) {
13918            scrollCache.scrollBar = new ScrollBarDrawable();
13919            scrollCache.scrollBar.setState(getDrawableState());
13920            scrollCache.scrollBar.setCallback(this);
13921        }
13922
13923        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
13924
13925            if (invalidate) {
13926                // Invalidate to show the scrollbars
13927                postInvalidateOnAnimation();
13928            }
13929
13930            if (scrollCache.state == ScrollabilityCache.OFF) {
13931                // FIXME: this is copied from WindowManagerService.
13932                // We should get this value from the system when it
13933                // is possible to do so.
13934                final int KEY_REPEAT_FIRST_DELAY = 750;
13935                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
13936            }
13937
13938            // Tell mScrollCache when we should start fading. This may
13939            // extend the fade start time if one was already scheduled
13940            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
13941            scrollCache.fadeStartTime = fadeStartTime;
13942            scrollCache.state = ScrollabilityCache.ON;
13943
13944            // Schedule our fader to run, unscheduling any old ones first
13945            if (mAttachInfo != null) {
13946                mAttachInfo.mHandler.removeCallbacks(scrollCache);
13947                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
13948            }
13949
13950            return true;
13951        }
13952
13953        return false;
13954    }
13955
13956    /**
13957     * Do not invalidate views which are not visible and which are not running an animation. They
13958     * will not get drawn and they should not set dirty flags as if they will be drawn
13959     */
13960    private boolean skipInvalidate() {
13961        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
13962                (!(mParent instanceof ViewGroup) ||
13963                        !((ViewGroup) mParent).isViewTransitioning(this));
13964    }
13965
13966    /**
13967     * Mark the area defined by dirty as needing to be drawn. If the view is
13968     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13969     * point in the future.
13970     * <p>
13971     * This must be called from a UI thread. To call from a non-UI thread, call
13972     * {@link #postInvalidate()}.
13973     * <p>
13974     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
13975     * {@code dirty}.
13976     *
13977     * @param dirty the rectangle representing the bounds of the dirty region
13978     */
13979    public void invalidate(Rect dirty) {
13980        final int scrollX = mScrollX;
13981        final int scrollY = mScrollY;
13982        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
13983                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
13984    }
13985
13986    /**
13987     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
13988     * coordinates of the dirty rect are relative to the view. If the view is
13989     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
13990     * point in the future.
13991     * <p>
13992     * This must be called from a UI thread. To call from a non-UI thread, call
13993     * {@link #postInvalidate()}.
13994     *
13995     * @param l the left position of the dirty region
13996     * @param t the top position of the dirty region
13997     * @param r the right position of the dirty region
13998     * @param b the bottom position of the dirty region
13999     */
14000    public void invalidate(int l, int t, int r, int b) {
14001        final int scrollX = mScrollX;
14002        final int scrollY = mScrollY;
14003        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
14004    }
14005
14006    /**
14007     * Invalidate the whole view. If the view is visible,
14008     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
14009     * the future.
14010     * <p>
14011     * This must be called from a UI thread. To call from a non-UI thread, call
14012     * {@link #postInvalidate()}.
14013     */
14014    public void invalidate() {
14015        invalidate(true);
14016    }
14017
14018    /**
14019     * This is where the invalidate() work actually happens. A full invalidate()
14020     * causes the drawing cache to be invalidated, but this function can be
14021     * called with invalidateCache set to false to skip that invalidation step
14022     * for cases that do not need it (for example, a component that remains at
14023     * the same dimensions with the same content).
14024     *
14025     * @param invalidateCache Whether the drawing cache for this view should be
14026     *            invalidated as well. This is usually true for a full
14027     *            invalidate, but may be set to false if the View's contents or
14028     *            dimensions have not changed.
14029     */
14030    void invalidate(boolean invalidateCache) {
14031        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
14032    }
14033
14034    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
14035            boolean fullInvalidate) {
14036        if (mGhostView != null) {
14037            mGhostView.invalidate(true);
14038            return;
14039        }
14040
14041        if (skipInvalidate()) {
14042            return;
14043        }
14044
14045        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
14046                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
14047                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
14048                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
14049            if (fullInvalidate) {
14050                mLastIsOpaque = isOpaque();
14051                mPrivateFlags &= ~PFLAG_DRAWN;
14052            }
14053
14054            mPrivateFlags |= PFLAG_DIRTY;
14055
14056            if (invalidateCache) {
14057                mPrivateFlags |= PFLAG_INVALIDATED;
14058                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14059            }
14060
14061            // Propagate the damage rectangle to the parent view.
14062            final AttachInfo ai = mAttachInfo;
14063            final ViewParent p = mParent;
14064            if (p != null && ai != null && l < r && t < b) {
14065                final Rect damage = ai.mTmpInvalRect;
14066                damage.set(l, t, r, b);
14067                p.invalidateChild(this, damage);
14068            }
14069
14070            // Damage the entire projection receiver, if necessary.
14071            if (mBackground != null && mBackground.isProjected()) {
14072                final View receiver = getProjectionReceiver();
14073                if (receiver != null) {
14074                    receiver.damageInParent();
14075                }
14076            }
14077        }
14078    }
14079
14080    /**
14081     * @return this view's projection receiver, or {@code null} if none exists
14082     */
14083    private View getProjectionReceiver() {
14084        ViewParent p = getParent();
14085        while (p != null && p instanceof View) {
14086            final View v = (View) p;
14087            if (v.isProjectionReceiver()) {
14088                return v;
14089            }
14090            p = p.getParent();
14091        }
14092
14093        return null;
14094    }
14095
14096    /**
14097     * @return whether the view is a projection receiver
14098     */
14099    private boolean isProjectionReceiver() {
14100        return mBackground != null;
14101    }
14102
14103    /**
14104     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
14105     * set any flags or handle all of the cases handled by the default invalidation methods.
14106     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
14107     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
14108     * walk up the hierarchy, transforming the dirty rect as necessary.
14109     *
14110     * The method also handles normal invalidation logic if display list properties are not
14111     * being used in this view. The invalidateParent and forceRedraw flags are used by that
14112     * backup approach, to handle these cases used in the various property-setting methods.
14113     *
14114     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
14115     * are not being used in this view
14116     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
14117     * list properties are not being used in this view
14118     */
14119    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
14120        if (!isHardwareAccelerated()
14121                || !mRenderNode.isValid()
14122                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
14123            if (invalidateParent) {
14124                invalidateParentCaches();
14125            }
14126            if (forceRedraw) {
14127                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14128            }
14129            invalidate(false);
14130        } else {
14131            damageInParent();
14132        }
14133    }
14134
14135    /**
14136     * Tells the parent view to damage this view's bounds.
14137     *
14138     * @hide
14139     */
14140    protected void damageInParent() {
14141        final AttachInfo ai = mAttachInfo;
14142        final ViewParent p = mParent;
14143        if (p != null && ai != null) {
14144            final Rect r = ai.mTmpInvalRect;
14145            r.set(0, 0, mRight - mLeft, mBottom - mTop);
14146            if (mParent instanceof ViewGroup) {
14147                ((ViewGroup) mParent).damageChild(this, r);
14148            } else {
14149                mParent.invalidateChild(this, r);
14150            }
14151        }
14152    }
14153
14154    /**
14155     * Utility method to transform a given Rect by the current matrix of this view.
14156     */
14157    void transformRect(final Rect rect) {
14158        if (!getMatrix().isIdentity()) {
14159            RectF boundingRect = mAttachInfo.mTmpTransformRect;
14160            boundingRect.set(rect);
14161            getMatrix().mapRect(boundingRect);
14162            rect.set((int) Math.floor(boundingRect.left),
14163                    (int) Math.floor(boundingRect.top),
14164                    (int) Math.ceil(boundingRect.right),
14165                    (int) Math.ceil(boundingRect.bottom));
14166        }
14167    }
14168
14169    /**
14170     * Used to indicate that the parent of this view should clear its caches. This functionality
14171     * is used to force the parent to rebuild its display list (when hardware-accelerated),
14172     * which is necessary when various parent-managed properties of the view change, such as
14173     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
14174     * clears the parent caches and does not causes an invalidate event.
14175     *
14176     * @hide
14177     */
14178    protected void invalidateParentCaches() {
14179        if (mParent instanceof View) {
14180            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
14181        }
14182    }
14183
14184    /**
14185     * Used to indicate that the parent of this view should be invalidated. This functionality
14186     * is used to force the parent to rebuild its display list (when hardware-accelerated),
14187     * which is necessary when various parent-managed properties of the view change, such as
14188     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
14189     * an invalidation event to the parent.
14190     *
14191     * @hide
14192     */
14193    protected void invalidateParentIfNeeded() {
14194        if (isHardwareAccelerated() && mParent instanceof View) {
14195            ((View) mParent).invalidate(true);
14196        }
14197    }
14198
14199    /**
14200     * @hide
14201     */
14202    protected void invalidateParentIfNeededAndWasQuickRejected() {
14203        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
14204            // View was rejected last time it was drawn by its parent; this may have changed
14205            invalidateParentIfNeeded();
14206        }
14207    }
14208
14209    /**
14210     * Indicates whether this View is opaque. An opaque View guarantees that it will
14211     * draw all the pixels overlapping its bounds using a fully opaque color.
14212     *
14213     * Subclasses of View should override this method whenever possible to indicate
14214     * whether an instance is opaque. Opaque Views are treated in a special way by
14215     * the View hierarchy, possibly allowing it to perform optimizations during
14216     * invalidate/draw passes.
14217     *
14218     * @return True if this View is guaranteed to be fully opaque, false otherwise.
14219     */
14220    @ViewDebug.ExportedProperty(category = "drawing")
14221    public boolean isOpaque() {
14222        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
14223                getFinalAlpha() >= 1.0f;
14224    }
14225
14226    /**
14227     * @hide
14228     */
14229    protected void computeOpaqueFlags() {
14230        // Opaque if:
14231        //   - Has a background
14232        //   - Background is opaque
14233        //   - Doesn't have scrollbars or scrollbars overlay
14234
14235        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
14236            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
14237        } else {
14238            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
14239        }
14240
14241        final int flags = mViewFlags;
14242        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
14243                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
14244                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
14245            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
14246        } else {
14247            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
14248        }
14249    }
14250
14251    /**
14252     * @hide
14253     */
14254    protected boolean hasOpaqueScrollbars() {
14255        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
14256    }
14257
14258    /**
14259     * @return A handler associated with the thread running the View. This
14260     * handler can be used to pump events in the UI events queue.
14261     */
14262    public Handler getHandler() {
14263        final AttachInfo attachInfo = mAttachInfo;
14264        if (attachInfo != null) {
14265            return attachInfo.mHandler;
14266        }
14267        return null;
14268    }
14269
14270    /**
14271     * Returns the queue of runnable for this view.
14272     *
14273     * @return the queue of runnables for this view
14274     */
14275    private HandlerActionQueue getRunQueue() {
14276        if (mRunQueue == null) {
14277            mRunQueue = new HandlerActionQueue();
14278        }
14279        return mRunQueue;
14280    }
14281
14282    /**
14283     * Gets the view root associated with the View.
14284     * @return The view root, or null if none.
14285     * @hide
14286     */
14287    public ViewRootImpl getViewRootImpl() {
14288        if (mAttachInfo != null) {
14289            return mAttachInfo.mViewRootImpl;
14290        }
14291        return null;
14292    }
14293
14294    /**
14295     * @hide
14296     */
14297    public ThreadedRenderer getThreadedRenderer() {
14298        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
14299    }
14300
14301    /**
14302     * <p>Causes the Runnable to be added to the message queue.
14303     * The runnable will be run on the user interface thread.</p>
14304     *
14305     * @param action The Runnable that will be executed.
14306     *
14307     * @return Returns true if the Runnable was successfully placed in to the
14308     *         message queue.  Returns false on failure, usually because the
14309     *         looper processing the message queue is exiting.
14310     *
14311     * @see #postDelayed
14312     * @see #removeCallbacks
14313     */
14314    public boolean post(Runnable action) {
14315        final AttachInfo attachInfo = mAttachInfo;
14316        if (attachInfo != null) {
14317            return attachInfo.mHandler.post(action);
14318        }
14319
14320        // Postpone the runnable until we know on which thread it needs to run.
14321        // Assume that the runnable will be successfully placed after attach.
14322        getRunQueue().post(action);
14323        return true;
14324    }
14325
14326    /**
14327     * <p>Causes the Runnable to be added to the message queue, to be run
14328     * after the specified amount of time elapses.
14329     * The runnable will be run on the user interface thread.</p>
14330     *
14331     * @param action The Runnable that will be executed.
14332     * @param delayMillis The delay (in milliseconds) until the Runnable
14333     *        will be executed.
14334     *
14335     * @return true if the Runnable was successfully placed in to the
14336     *         message queue.  Returns false on failure, usually because the
14337     *         looper processing the message queue is exiting.  Note that a
14338     *         result of true does not mean the Runnable will be processed --
14339     *         if the looper is quit before the delivery time of the message
14340     *         occurs then the message will be dropped.
14341     *
14342     * @see #post
14343     * @see #removeCallbacks
14344     */
14345    public boolean postDelayed(Runnable action, long delayMillis) {
14346        final AttachInfo attachInfo = mAttachInfo;
14347        if (attachInfo != null) {
14348            return attachInfo.mHandler.postDelayed(action, delayMillis);
14349        }
14350
14351        // Postpone the runnable until we know on which thread it needs to run.
14352        // Assume that the runnable will be successfully placed after attach.
14353        getRunQueue().postDelayed(action, delayMillis);
14354        return true;
14355    }
14356
14357    /**
14358     * <p>Causes the Runnable to execute on the next animation time step.
14359     * The runnable will be run on the user interface thread.</p>
14360     *
14361     * @param action The Runnable that will be executed.
14362     *
14363     * @see #postOnAnimationDelayed
14364     * @see #removeCallbacks
14365     */
14366    public void postOnAnimation(Runnable action) {
14367        final AttachInfo attachInfo = mAttachInfo;
14368        if (attachInfo != null) {
14369            attachInfo.mViewRootImpl.mChoreographer.postCallback(
14370                    Choreographer.CALLBACK_ANIMATION, action, null);
14371        } else {
14372            // Postpone the runnable until we know
14373            // on which thread it needs to run.
14374            getRunQueue().post(action);
14375        }
14376    }
14377
14378    /**
14379     * <p>Causes the Runnable to execute on the next animation time step,
14380     * after the specified amount of time elapses.
14381     * The runnable will be run on the user interface thread.</p>
14382     *
14383     * @param action The Runnable that will be executed.
14384     * @param delayMillis The delay (in milliseconds) until the Runnable
14385     *        will be executed.
14386     *
14387     * @see #postOnAnimation
14388     * @see #removeCallbacks
14389     */
14390    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
14391        final AttachInfo attachInfo = mAttachInfo;
14392        if (attachInfo != null) {
14393            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
14394                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
14395        } else {
14396            // Postpone the runnable until we know
14397            // on which thread it needs to run.
14398            getRunQueue().postDelayed(action, delayMillis);
14399        }
14400    }
14401
14402    /**
14403     * <p>Removes the specified Runnable from the message queue.</p>
14404     *
14405     * @param action The Runnable to remove from the message handling queue
14406     *
14407     * @return true if this view could ask the Handler to remove the Runnable,
14408     *         false otherwise. When the returned value is true, the Runnable
14409     *         may or may not have been actually removed from the message queue
14410     *         (for instance, if the Runnable was not in the queue already.)
14411     *
14412     * @see #post
14413     * @see #postDelayed
14414     * @see #postOnAnimation
14415     * @see #postOnAnimationDelayed
14416     */
14417    public boolean removeCallbacks(Runnable action) {
14418        if (action != null) {
14419            final AttachInfo attachInfo = mAttachInfo;
14420            if (attachInfo != null) {
14421                attachInfo.mHandler.removeCallbacks(action);
14422                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14423                        Choreographer.CALLBACK_ANIMATION, action, null);
14424            }
14425            getRunQueue().removeCallbacks(action);
14426        }
14427        return true;
14428    }
14429
14430    /**
14431     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
14432     * Use this to invalidate the View from a non-UI thread.</p>
14433     *
14434     * <p>This method can be invoked from outside of the UI thread
14435     * only when this View is attached to a window.</p>
14436     *
14437     * @see #invalidate()
14438     * @see #postInvalidateDelayed(long)
14439     */
14440    public void postInvalidate() {
14441        postInvalidateDelayed(0);
14442    }
14443
14444    /**
14445     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14446     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
14447     *
14448     * <p>This method can be invoked from outside of the UI thread
14449     * only when this View is attached to a window.</p>
14450     *
14451     * @param left The left coordinate of the rectangle to invalidate.
14452     * @param top The top coordinate of the rectangle to invalidate.
14453     * @param right The right coordinate of the rectangle to invalidate.
14454     * @param bottom The bottom coordinate of the rectangle to invalidate.
14455     *
14456     * @see #invalidate(int, int, int, int)
14457     * @see #invalidate(Rect)
14458     * @see #postInvalidateDelayed(long, int, int, int, int)
14459     */
14460    public void postInvalidate(int left, int top, int right, int bottom) {
14461        postInvalidateDelayed(0, left, top, right, bottom);
14462    }
14463
14464    /**
14465     * <p>Cause an invalidate to happen on a subsequent cycle through the event
14466     * loop. Waits for the specified amount of time.</p>
14467     *
14468     * <p>This method can be invoked from outside of the UI thread
14469     * only when this View is attached to a window.</p>
14470     *
14471     * @param delayMilliseconds the duration in milliseconds to delay the
14472     *         invalidation by
14473     *
14474     * @see #invalidate()
14475     * @see #postInvalidate()
14476     */
14477    public void postInvalidateDelayed(long delayMilliseconds) {
14478        // We try only with the AttachInfo because there's no point in invalidating
14479        // if we are not attached to our window
14480        final AttachInfo attachInfo = mAttachInfo;
14481        if (attachInfo != null) {
14482            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
14483        }
14484    }
14485
14486    /**
14487     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14488     * through the event loop. Waits for the specified amount of time.</p>
14489     *
14490     * <p>This method can be invoked from outside of the UI thread
14491     * only when this View is attached to a window.</p>
14492     *
14493     * @param delayMilliseconds the duration in milliseconds to delay the
14494     *         invalidation by
14495     * @param left The left coordinate of the rectangle to invalidate.
14496     * @param top The top coordinate of the rectangle to invalidate.
14497     * @param right The right coordinate of the rectangle to invalidate.
14498     * @param bottom The bottom coordinate of the rectangle to invalidate.
14499     *
14500     * @see #invalidate(int, int, int, int)
14501     * @see #invalidate(Rect)
14502     * @see #postInvalidate(int, int, int, int)
14503     */
14504    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
14505            int right, int bottom) {
14506
14507        // We try only with the AttachInfo because there's no point in invalidating
14508        // if we are not attached to our window
14509        final AttachInfo attachInfo = mAttachInfo;
14510        if (attachInfo != null) {
14511            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14512            info.target = this;
14513            info.left = left;
14514            info.top = top;
14515            info.right = right;
14516            info.bottom = bottom;
14517
14518            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
14519        }
14520    }
14521
14522    /**
14523     * <p>Cause an invalidate to happen on the next animation time step, typically the
14524     * next display frame.</p>
14525     *
14526     * <p>This method can be invoked from outside of the UI thread
14527     * only when this View is attached to a window.</p>
14528     *
14529     * @see #invalidate()
14530     */
14531    public void postInvalidateOnAnimation() {
14532        // We try only with the AttachInfo because there's no point in invalidating
14533        // if we are not attached to our window
14534        final AttachInfo attachInfo = mAttachInfo;
14535        if (attachInfo != null) {
14536            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
14537        }
14538    }
14539
14540    /**
14541     * <p>Cause an invalidate of the specified area to happen on the next animation
14542     * time step, typically the next display frame.</p>
14543     *
14544     * <p>This method can be invoked from outside of the UI thread
14545     * only when this View is attached to a window.</p>
14546     *
14547     * @param left The left coordinate of the rectangle to invalidate.
14548     * @param top The top coordinate of the rectangle to invalidate.
14549     * @param right The right coordinate of the rectangle to invalidate.
14550     * @param bottom The bottom coordinate of the rectangle to invalidate.
14551     *
14552     * @see #invalidate(int, int, int, int)
14553     * @see #invalidate(Rect)
14554     */
14555    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
14556        // We try only with the AttachInfo because there's no point in invalidating
14557        // if we are not attached to our window
14558        final AttachInfo attachInfo = mAttachInfo;
14559        if (attachInfo != null) {
14560            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14561            info.target = this;
14562            info.left = left;
14563            info.top = top;
14564            info.right = right;
14565            info.bottom = bottom;
14566
14567            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
14568        }
14569    }
14570
14571    /**
14572     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
14573     * This event is sent at most once every
14574     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
14575     */
14576    private void postSendViewScrolledAccessibilityEventCallback() {
14577        if (mSendViewScrolledAccessibilityEvent == null) {
14578            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
14579        }
14580        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
14581            mSendViewScrolledAccessibilityEvent.mIsPending = true;
14582            postDelayed(mSendViewScrolledAccessibilityEvent,
14583                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
14584        }
14585    }
14586
14587    /**
14588     * Called by a parent to request that a child update its values for mScrollX
14589     * and mScrollY if necessary. This will typically be done if the child is
14590     * animating a scroll using a {@link android.widget.Scroller Scroller}
14591     * object.
14592     */
14593    public void computeScroll() {
14594    }
14595
14596    /**
14597     * <p>Indicate whether the horizontal edges are faded when the view is
14598     * scrolled horizontally.</p>
14599     *
14600     * @return true if the horizontal edges should are faded on scroll, false
14601     *         otherwise
14602     *
14603     * @see #setHorizontalFadingEdgeEnabled(boolean)
14604     *
14605     * @attr ref android.R.styleable#View_requiresFadingEdge
14606     */
14607    public boolean isHorizontalFadingEdgeEnabled() {
14608        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
14609    }
14610
14611    /**
14612     * <p>Define whether the horizontal edges should be faded when this view
14613     * is scrolled horizontally.</p>
14614     *
14615     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
14616     *                                    be faded when the view is scrolled
14617     *                                    horizontally
14618     *
14619     * @see #isHorizontalFadingEdgeEnabled()
14620     *
14621     * @attr ref android.R.styleable#View_requiresFadingEdge
14622     */
14623    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
14624        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
14625            if (horizontalFadingEdgeEnabled) {
14626                initScrollCache();
14627            }
14628
14629            mViewFlags ^= FADING_EDGE_HORIZONTAL;
14630        }
14631    }
14632
14633    /**
14634     * <p>Indicate whether the vertical edges are faded when the view is
14635     * scrolled horizontally.</p>
14636     *
14637     * @return true if the vertical edges should are faded on scroll, false
14638     *         otherwise
14639     *
14640     * @see #setVerticalFadingEdgeEnabled(boolean)
14641     *
14642     * @attr ref android.R.styleable#View_requiresFadingEdge
14643     */
14644    public boolean isVerticalFadingEdgeEnabled() {
14645        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
14646    }
14647
14648    /**
14649     * <p>Define whether the vertical edges should be faded when this view
14650     * is scrolled vertically.</p>
14651     *
14652     * @param verticalFadingEdgeEnabled true if the vertical edges should
14653     *                                  be faded when the view is scrolled
14654     *                                  vertically
14655     *
14656     * @see #isVerticalFadingEdgeEnabled()
14657     *
14658     * @attr ref android.R.styleable#View_requiresFadingEdge
14659     */
14660    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
14661        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
14662            if (verticalFadingEdgeEnabled) {
14663                initScrollCache();
14664            }
14665
14666            mViewFlags ^= FADING_EDGE_VERTICAL;
14667        }
14668    }
14669
14670    /**
14671     * Returns the strength, or intensity, of the top faded edge. The strength is
14672     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14673     * returns 0.0 or 1.0 but no value in between.
14674     *
14675     * Subclasses should override this method to provide a smoother fade transition
14676     * when scrolling occurs.
14677     *
14678     * @return the intensity of the top fade as a float between 0.0f and 1.0f
14679     */
14680    protected float getTopFadingEdgeStrength() {
14681        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
14682    }
14683
14684    /**
14685     * Returns the strength, or intensity, of the bottom faded edge. The strength is
14686     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14687     * returns 0.0 or 1.0 but no value in between.
14688     *
14689     * Subclasses should override this method to provide a smoother fade transition
14690     * when scrolling occurs.
14691     *
14692     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
14693     */
14694    protected float getBottomFadingEdgeStrength() {
14695        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
14696                computeVerticalScrollRange() ? 1.0f : 0.0f;
14697    }
14698
14699    /**
14700     * Returns the strength, or intensity, of the left faded edge. The strength is
14701     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14702     * returns 0.0 or 1.0 but no value in between.
14703     *
14704     * Subclasses should override this method to provide a smoother fade transition
14705     * when scrolling occurs.
14706     *
14707     * @return the intensity of the left fade as a float between 0.0f and 1.0f
14708     */
14709    protected float getLeftFadingEdgeStrength() {
14710        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
14711    }
14712
14713    /**
14714     * Returns the strength, or intensity, of the right faded edge. The strength is
14715     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14716     * returns 0.0 or 1.0 but no value in between.
14717     *
14718     * Subclasses should override this method to provide a smoother fade transition
14719     * when scrolling occurs.
14720     *
14721     * @return the intensity of the right fade as a float between 0.0f and 1.0f
14722     */
14723    protected float getRightFadingEdgeStrength() {
14724        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
14725                computeHorizontalScrollRange() ? 1.0f : 0.0f;
14726    }
14727
14728    /**
14729     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
14730     * scrollbar is not drawn by default.</p>
14731     *
14732     * @return true if the horizontal scrollbar should be painted, false
14733     *         otherwise
14734     *
14735     * @see #setHorizontalScrollBarEnabled(boolean)
14736     */
14737    public boolean isHorizontalScrollBarEnabled() {
14738        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14739    }
14740
14741    /**
14742     * <p>Define whether the horizontal scrollbar should be drawn or not. The
14743     * scrollbar is not drawn by default.</p>
14744     *
14745     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
14746     *                                   be painted
14747     *
14748     * @see #isHorizontalScrollBarEnabled()
14749     */
14750    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
14751        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
14752            mViewFlags ^= SCROLLBARS_HORIZONTAL;
14753            computeOpaqueFlags();
14754            resolvePadding();
14755        }
14756    }
14757
14758    /**
14759     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
14760     * scrollbar is not drawn by default.</p>
14761     *
14762     * @return true if the vertical scrollbar should be painted, false
14763     *         otherwise
14764     *
14765     * @see #setVerticalScrollBarEnabled(boolean)
14766     */
14767    public boolean isVerticalScrollBarEnabled() {
14768        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
14769    }
14770
14771    /**
14772     * <p>Define whether the vertical scrollbar should be drawn or not. The
14773     * scrollbar is not drawn by default.</p>
14774     *
14775     * @param verticalScrollBarEnabled true if the vertical scrollbar should
14776     *                                 be painted
14777     *
14778     * @see #isVerticalScrollBarEnabled()
14779     */
14780    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
14781        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
14782            mViewFlags ^= SCROLLBARS_VERTICAL;
14783            computeOpaqueFlags();
14784            resolvePadding();
14785        }
14786    }
14787
14788    /**
14789     * @hide
14790     */
14791    protected void recomputePadding() {
14792        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14793    }
14794
14795    /**
14796     * Define whether scrollbars will fade when the view is not scrolling.
14797     *
14798     * @param fadeScrollbars whether to enable fading
14799     *
14800     * @attr ref android.R.styleable#View_fadeScrollbars
14801     */
14802    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
14803        initScrollCache();
14804        final ScrollabilityCache scrollabilityCache = mScrollCache;
14805        scrollabilityCache.fadeScrollBars = fadeScrollbars;
14806        if (fadeScrollbars) {
14807            scrollabilityCache.state = ScrollabilityCache.OFF;
14808        } else {
14809            scrollabilityCache.state = ScrollabilityCache.ON;
14810        }
14811    }
14812
14813    /**
14814     *
14815     * Returns true if scrollbars will fade when this view is not scrolling
14816     *
14817     * @return true if scrollbar fading is enabled
14818     *
14819     * @attr ref android.R.styleable#View_fadeScrollbars
14820     */
14821    public boolean isScrollbarFadingEnabled() {
14822        return mScrollCache != null && mScrollCache.fadeScrollBars;
14823    }
14824
14825    /**
14826     *
14827     * Returns the delay before scrollbars fade.
14828     *
14829     * @return the delay before scrollbars fade
14830     *
14831     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14832     */
14833    public int getScrollBarDefaultDelayBeforeFade() {
14834        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
14835                mScrollCache.scrollBarDefaultDelayBeforeFade;
14836    }
14837
14838    /**
14839     * Define the delay before scrollbars fade.
14840     *
14841     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
14842     *
14843     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
14844     */
14845    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
14846        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
14847    }
14848
14849    /**
14850     *
14851     * Returns the scrollbar fade duration.
14852     *
14853     * @return the scrollbar fade duration, in milliseconds
14854     *
14855     * @attr ref android.R.styleable#View_scrollbarFadeDuration
14856     */
14857    public int getScrollBarFadeDuration() {
14858        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
14859                mScrollCache.scrollBarFadeDuration;
14860    }
14861
14862    /**
14863     * Define the scrollbar fade duration.
14864     *
14865     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
14866     *
14867     * @attr ref android.R.styleable#View_scrollbarFadeDuration
14868     */
14869    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
14870        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
14871    }
14872
14873    /**
14874     *
14875     * Returns the scrollbar size.
14876     *
14877     * @return the scrollbar size
14878     *
14879     * @attr ref android.R.styleable#View_scrollbarSize
14880     */
14881    public int getScrollBarSize() {
14882        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
14883                mScrollCache.scrollBarSize;
14884    }
14885
14886    /**
14887     * Define the scrollbar size.
14888     *
14889     * @param scrollBarSize - the scrollbar size
14890     *
14891     * @attr ref android.R.styleable#View_scrollbarSize
14892     */
14893    public void setScrollBarSize(int scrollBarSize) {
14894        getScrollCache().scrollBarSize = scrollBarSize;
14895    }
14896
14897    /**
14898     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
14899     * inset. When inset, they add to the padding of the view. And the scrollbars
14900     * can be drawn inside the padding area or on the edge of the view. For example,
14901     * if a view has a background drawable and you want to draw the scrollbars
14902     * inside the padding specified by the drawable, you can use
14903     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
14904     * appear at the edge of the view, ignoring the padding, then you can use
14905     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
14906     * @param style the style of the scrollbars. Should be one of
14907     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
14908     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
14909     * @see #SCROLLBARS_INSIDE_OVERLAY
14910     * @see #SCROLLBARS_INSIDE_INSET
14911     * @see #SCROLLBARS_OUTSIDE_OVERLAY
14912     * @see #SCROLLBARS_OUTSIDE_INSET
14913     *
14914     * @attr ref android.R.styleable#View_scrollbarStyle
14915     */
14916    public void setScrollBarStyle(@ScrollBarStyle int style) {
14917        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
14918            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
14919            computeOpaqueFlags();
14920            resolvePadding();
14921        }
14922    }
14923
14924    /**
14925     * <p>Returns the current scrollbar style.</p>
14926     * @return the current scrollbar style
14927     * @see #SCROLLBARS_INSIDE_OVERLAY
14928     * @see #SCROLLBARS_INSIDE_INSET
14929     * @see #SCROLLBARS_OUTSIDE_OVERLAY
14930     * @see #SCROLLBARS_OUTSIDE_INSET
14931     *
14932     * @attr ref android.R.styleable#View_scrollbarStyle
14933     */
14934    @ViewDebug.ExportedProperty(mapping = {
14935            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
14936            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
14937            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
14938            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
14939    })
14940    @ScrollBarStyle
14941    public int getScrollBarStyle() {
14942        return mViewFlags & SCROLLBARS_STYLE_MASK;
14943    }
14944
14945    /**
14946     * <p>Compute the horizontal range that the horizontal scrollbar
14947     * represents.</p>
14948     *
14949     * <p>The range is expressed in arbitrary units that must be the same as the
14950     * units used by {@link #computeHorizontalScrollExtent()} and
14951     * {@link #computeHorizontalScrollOffset()}.</p>
14952     *
14953     * <p>The default range is the drawing width of this view.</p>
14954     *
14955     * @return the total horizontal range represented by the horizontal
14956     *         scrollbar
14957     *
14958     * @see #computeHorizontalScrollExtent()
14959     * @see #computeHorizontalScrollOffset()
14960     * @see android.widget.ScrollBarDrawable
14961     */
14962    protected int computeHorizontalScrollRange() {
14963        return getWidth();
14964    }
14965
14966    /**
14967     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
14968     * within the horizontal range. This value is used to compute the position
14969     * of the thumb within the scrollbar's track.</p>
14970     *
14971     * <p>The range is expressed in arbitrary units that must be the same as the
14972     * units used by {@link #computeHorizontalScrollRange()} and
14973     * {@link #computeHorizontalScrollExtent()}.</p>
14974     *
14975     * <p>The default offset is the scroll offset of this view.</p>
14976     *
14977     * @return the horizontal offset of the scrollbar's thumb
14978     *
14979     * @see #computeHorizontalScrollRange()
14980     * @see #computeHorizontalScrollExtent()
14981     * @see android.widget.ScrollBarDrawable
14982     */
14983    protected int computeHorizontalScrollOffset() {
14984        return mScrollX;
14985    }
14986
14987    /**
14988     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
14989     * within the horizontal range. This value is used to compute the length
14990     * of the thumb within the scrollbar's track.</p>
14991     *
14992     * <p>The range is expressed in arbitrary units that must be the same as the
14993     * units used by {@link #computeHorizontalScrollRange()} and
14994     * {@link #computeHorizontalScrollOffset()}.</p>
14995     *
14996     * <p>The default extent is the drawing width of this view.</p>
14997     *
14998     * @return the horizontal extent of the scrollbar's thumb
14999     *
15000     * @see #computeHorizontalScrollRange()
15001     * @see #computeHorizontalScrollOffset()
15002     * @see android.widget.ScrollBarDrawable
15003     */
15004    protected int computeHorizontalScrollExtent() {
15005        return getWidth();
15006    }
15007
15008    /**
15009     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
15010     *
15011     * <p>The range is expressed in arbitrary units that must be the same as the
15012     * units used by {@link #computeVerticalScrollExtent()} and
15013     * {@link #computeVerticalScrollOffset()}.</p>
15014     *
15015     * @return the total vertical range represented by the vertical scrollbar
15016     *
15017     * <p>The default range is the drawing height of this view.</p>
15018     *
15019     * @see #computeVerticalScrollExtent()
15020     * @see #computeVerticalScrollOffset()
15021     * @see android.widget.ScrollBarDrawable
15022     */
15023    protected int computeVerticalScrollRange() {
15024        return getHeight();
15025    }
15026
15027    /**
15028     * <p>Compute the vertical offset of the vertical scrollbar's thumb
15029     * within the horizontal range. This value is used to compute the position
15030     * of the thumb within the scrollbar's track.</p>
15031     *
15032     * <p>The range is expressed in arbitrary units that must be the same as the
15033     * units used by {@link #computeVerticalScrollRange()} and
15034     * {@link #computeVerticalScrollExtent()}.</p>
15035     *
15036     * <p>The default offset is the scroll offset of this view.</p>
15037     *
15038     * @return the vertical offset of the scrollbar's thumb
15039     *
15040     * @see #computeVerticalScrollRange()
15041     * @see #computeVerticalScrollExtent()
15042     * @see android.widget.ScrollBarDrawable
15043     */
15044    protected int computeVerticalScrollOffset() {
15045        return mScrollY;
15046    }
15047
15048    /**
15049     * <p>Compute the vertical extent of the vertical scrollbar's thumb
15050     * within the vertical range. This value is used to compute the length
15051     * of the thumb within the scrollbar's track.</p>
15052     *
15053     * <p>The range is expressed in arbitrary units that must be the same as the
15054     * units used by {@link #computeVerticalScrollRange()} and
15055     * {@link #computeVerticalScrollOffset()}.</p>
15056     *
15057     * <p>The default extent is the drawing height of this view.</p>
15058     *
15059     * @return the vertical extent of the scrollbar's thumb
15060     *
15061     * @see #computeVerticalScrollRange()
15062     * @see #computeVerticalScrollOffset()
15063     * @see android.widget.ScrollBarDrawable
15064     */
15065    protected int computeVerticalScrollExtent() {
15066        return getHeight();
15067    }
15068
15069    /**
15070     * Check if this view can be scrolled horizontally in a certain direction.
15071     *
15072     * @param direction Negative to check scrolling left, positive to check scrolling right.
15073     * @return true if this view can be scrolled in the specified direction, false otherwise.
15074     */
15075    public boolean canScrollHorizontally(int direction) {
15076        final int offset = computeHorizontalScrollOffset();
15077        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
15078        if (range == 0) return false;
15079        if (direction < 0) {
15080            return offset > 0;
15081        } else {
15082            return offset < range - 1;
15083        }
15084    }
15085
15086    /**
15087     * Check if this view can be scrolled vertically in a certain direction.
15088     *
15089     * @param direction Negative to check scrolling up, positive to check scrolling down.
15090     * @return true if this view can be scrolled in the specified direction, false otherwise.
15091     */
15092    public boolean canScrollVertically(int direction) {
15093        final int offset = computeVerticalScrollOffset();
15094        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
15095        if (range == 0) return false;
15096        if (direction < 0) {
15097            return offset > 0;
15098        } else {
15099            return offset < range - 1;
15100        }
15101    }
15102
15103    void getScrollIndicatorBounds(@NonNull Rect out) {
15104        out.left = mScrollX;
15105        out.right = mScrollX + mRight - mLeft;
15106        out.top = mScrollY;
15107        out.bottom = mScrollY + mBottom - mTop;
15108    }
15109
15110    private void onDrawScrollIndicators(Canvas c) {
15111        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
15112            // No scroll indicators enabled.
15113            return;
15114        }
15115
15116        final Drawable dr = mScrollIndicatorDrawable;
15117        if (dr == null) {
15118            // Scroll indicators aren't supported here.
15119            return;
15120        }
15121
15122        final int h = dr.getIntrinsicHeight();
15123        final int w = dr.getIntrinsicWidth();
15124        final Rect rect = mAttachInfo.mTmpInvalRect;
15125        getScrollIndicatorBounds(rect);
15126
15127        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
15128            final boolean canScrollUp = canScrollVertically(-1);
15129            if (canScrollUp) {
15130                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
15131                dr.draw(c);
15132            }
15133        }
15134
15135        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
15136            final boolean canScrollDown = canScrollVertically(1);
15137            if (canScrollDown) {
15138                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
15139                dr.draw(c);
15140            }
15141        }
15142
15143        final int leftRtl;
15144        final int rightRtl;
15145        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15146            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
15147            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
15148        } else {
15149            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
15150            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
15151        }
15152
15153        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
15154        if ((mPrivateFlags3 & leftMask) != 0) {
15155            final boolean canScrollLeft = canScrollHorizontally(-1);
15156            if (canScrollLeft) {
15157                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
15158                dr.draw(c);
15159            }
15160        }
15161
15162        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
15163        if ((mPrivateFlags3 & rightMask) != 0) {
15164            final boolean canScrollRight = canScrollHorizontally(1);
15165            if (canScrollRight) {
15166                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
15167                dr.draw(c);
15168            }
15169        }
15170    }
15171
15172    private void getHorizontalScrollBarBounds(Rect bounds) {
15173        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
15174        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
15175                && !isVerticalScrollBarHidden();
15176        final int size = getHorizontalScrollbarHeight();
15177        final int verticalScrollBarGap = drawVerticalScrollBar ?
15178                getVerticalScrollbarWidth() : 0;
15179        final int width = mRight - mLeft;
15180        final int height = mBottom - mTop;
15181        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
15182        bounds.left = mScrollX + (mPaddingLeft & inside);
15183        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
15184        bounds.bottom = bounds.top + size;
15185    }
15186
15187    private void getVerticalScrollBarBounds(Rect bounds) {
15188        if (mRoundScrollbarRenderer == null) {
15189            getStraightVerticalScrollBarBounds(bounds);
15190        } else {
15191            getRoundVerticalScrollBarBounds(bounds);
15192        }
15193    }
15194
15195    private void getRoundVerticalScrollBarBounds(Rect bounds) {
15196        final int width = mRight - mLeft;
15197        final int height = mBottom - mTop;
15198        // Do not take padding into account as we always want the scrollbars
15199        // to hug the screen for round wearable devices.
15200        bounds.left = mScrollX;
15201        bounds.top = mScrollY;
15202        bounds.right = bounds.left + width;
15203        bounds.bottom = mScrollY + height;
15204    }
15205
15206    private void getStraightVerticalScrollBarBounds(Rect bounds) {
15207        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
15208        final int size = getVerticalScrollbarWidth();
15209        int verticalScrollbarPosition = mVerticalScrollbarPosition;
15210        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
15211            verticalScrollbarPosition = isLayoutRtl() ?
15212                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
15213        }
15214        final int width = mRight - mLeft;
15215        final int height = mBottom - mTop;
15216        switch (verticalScrollbarPosition) {
15217            default:
15218            case SCROLLBAR_POSITION_RIGHT:
15219                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
15220                break;
15221            case SCROLLBAR_POSITION_LEFT:
15222                bounds.left = mScrollX + (mUserPaddingLeft & inside);
15223                break;
15224        }
15225        bounds.top = mScrollY + (mPaddingTop & inside);
15226        bounds.right = bounds.left + size;
15227        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
15228    }
15229
15230    /**
15231     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
15232     * scrollbars are painted only if they have been awakened first.</p>
15233     *
15234     * @param canvas the canvas on which to draw the scrollbars
15235     *
15236     * @see #awakenScrollBars(int)
15237     */
15238    protected final void onDrawScrollBars(Canvas canvas) {
15239        // scrollbars are drawn only when the animation is running
15240        final ScrollabilityCache cache = mScrollCache;
15241
15242        if (cache != null) {
15243
15244            int state = cache.state;
15245
15246            if (state == ScrollabilityCache.OFF) {
15247                return;
15248            }
15249
15250            boolean invalidate = false;
15251
15252            if (state == ScrollabilityCache.FADING) {
15253                // We're fading -- get our fade interpolation
15254                if (cache.interpolatorValues == null) {
15255                    cache.interpolatorValues = new float[1];
15256                }
15257
15258                float[] values = cache.interpolatorValues;
15259
15260                // Stops the animation if we're done
15261                if (cache.scrollBarInterpolator.timeToValues(values) ==
15262                        Interpolator.Result.FREEZE_END) {
15263                    cache.state = ScrollabilityCache.OFF;
15264                } else {
15265                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
15266                }
15267
15268                // This will make the scroll bars inval themselves after
15269                // drawing. We only want this when we're fading so that
15270                // we prevent excessive redraws
15271                invalidate = true;
15272            } else {
15273                // We're just on -- but we may have been fading before so
15274                // reset alpha
15275                cache.scrollBar.mutate().setAlpha(255);
15276            }
15277
15278            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
15279            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
15280                    && !isVerticalScrollBarHidden();
15281
15282            // Fork out the scroll bar drawing for round wearable devices.
15283            if (mRoundScrollbarRenderer != null) {
15284                if (drawVerticalScrollBar) {
15285                    final Rect bounds = cache.mScrollBarBounds;
15286                    getVerticalScrollBarBounds(bounds);
15287                    mRoundScrollbarRenderer.drawRoundScrollbars(
15288                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
15289                    if (invalidate) {
15290                        invalidate();
15291                    }
15292                }
15293                // Do not draw horizontal scroll bars for round wearable devices.
15294            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
15295                final ScrollBarDrawable scrollBar = cache.scrollBar;
15296
15297                if (drawHorizontalScrollBar) {
15298                    scrollBar.setParameters(computeHorizontalScrollRange(),
15299                            computeHorizontalScrollOffset(),
15300                            computeHorizontalScrollExtent(), false);
15301                    final Rect bounds = cache.mScrollBarBounds;
15302                    getHorizontalScrollBarBounds(bounds);
15303                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
15304                            bounds.right, bounds.bottom);
15305                    if (invalidate) {
15306                        invalidate(bounds);
15307                    }
15308                }
15309
15310                if (drawVerticalScrollBar) {
15311                    scrollBar.setParameters(computeVerticalScrollRange(),
15312                            computeVerticalScrollOffset(),
15313                            computeVerticalScrollExtent(), true);
15314                    final Rect bounds = cache.mScrollBarBounds;
15315                    getVerticalScrollBarBounds(bounds);
15316                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
15317                            bounds.right, bounds.bottom);
15318                    if (invalidate) {
15319                        invalidate(bounds);
15320                    }
15321                }
15322            }
15323        }
15324    }
15325
15326    /**
15327     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
15328     * FastScroller is visible.
15329     * @return whether to temporarily hide the vertical scrollbar
15330     * @hide
15331     */
15332    protected boolean isVerticalScrollBarHidden() {
15333        return false;
15334    }
15335
15336    /**
15337     * <p>Draw the horizontal scrollbar if
15338     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
15339     *
15340     * @param canvas the canvas on which to draw the scrollbar
15341     * @param scrollBar the scrollbar's drawable
15342     *
15343     * @see #isHorizontalScrollBarEnabled()
15344     * @see #computeHorizontalScrollRange()
15345     * @see #computeHorizontalScrollExtent()
15346     * @see #computeHorizontalScrollOffset()
15347     * @see android.widget.ScrollBarDrawable
15348     * @hide
15349     */
15350    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
15351            int l, int t, int r, int b) {
15352        scrollBar.setBounds(l, t, r, b);
15353        scrollBar.draw(canvas);
15354    }
15355
15356    /**
15357     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
15358     * returns true.</p>
15359     *
15360     * @param canvas the canvas on which to draw the scrollbar
15361     * @param scrollBar the scrollbar's drawable
15362     *
15363     * @see #isVerticalScrollBarEnabled()
15364     * @see #computeVerticalScrollRange()
15365     * @see #computeVerticalScrollExtent()
15366     * @see #computeVerticalScrollOffset()
15367     * @see android.widget.ScrollBarDrawable
15368     * @hide
15369     */
15370    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
15371            int l, int t, int r, int b) {
15372        scrollBar.setBounds(l, t, r, b);
15373        scrollBar.draw(canvas);
15374    }
15375
15376    /**
15377     * Implement this to do your drawing.
15378     *
15379     * @param canvas the canvas on which the background will be drawn
15380     */
15381    protected void onDraw(Canvas canvas) {
15382    }
15383
15384    /*
15385     * Caller is responsible for calling requestLayout if necessary.
15386     * (This allows addViewInLayout to not request a new layout.)
15387     */
15388    void assignParent(ViewParent parent) {
15389        if (mParent == null) {
15390            mParent = parent;
15391        } else if (parent == null) {
15392            mParent = null;
15393        } else {
15394            throw new RuntimeException("view " + this + " being added, but"
15395                    + " it already has a parent");
15396        }
15397    }
15398
15399    /**
15400     * This is called when the view is attached to a window.  At this point it
15401     * has a Surface and will start drawing.  Note that this function is
15402     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
15403     * however it may be called any time before the first onDraw -- including
15404     * before or after {@link #onMeasure(int, int)}.
15405     *
15406     * @see #onDetachedFromWindow()
15407     */
15408    @CallSuper
15409    protected void onAttachedToWindow() {
15410        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
15411            mParent.requestTransparentRegion(this);
15412        }
15413
15414        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15415
15416        jumpDrawablesToCurrentState();
15417
15418        resetSubtreeAccessibilityStateChanged();
15419
15420        // rebuild, since Outline not maintained while View is detached
15421        rebuildOutline();
15422
15423        if (isFocused()) {
15424            InputMethodManager imm = InputMethodManager.peekInstance();
15425            if (imm != null) {
15426                imm.focusIn(this);
15427            }
15428        }
15429    }
15430
15431    /**
15432     * Resolve all RTL related properties.
15433     *
15434     * @return true if resolution of RTL properties has been done
15435     *
15436     * @hide
15437     */
15438    public boolean resolveRtlPropertiesIfNeeded() {
15439        if (!needRtlPropertiesResolution()) return false;
15440
15441        // Order is important here: LayoutDirection MUST be resolved first
15442        if (!isLayoutDirectionResolved()) {
15443            resolveLayoutDirection();
15444            resolveLayoutParams();
15445        }
15446        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
15447        if (!isTextDirectionResolved()) {
15448            resolveTextDirection();
15449        }
15450        if (!isTextAlignmentResolved()) {
15451            resolveTextAlignment();
15452        }
15453        // Should resolve Drawables before Padding because we need the layout direction of the
15454        // Drawable to correctly resolve Padding.
15455        if (!areDrawablesResolved()) {
15456            resolveDrawables();
15457        }
15458        if (!isPaddingResolved()) {
15459            resolvePadding();
15460        }
15461        onRtlPropertiesChanged(getLayoutDirection());
15462        return true;
15463    }
15464
15465    /**
15466     * Reset resolution of all RTL related properties.
15467     *
15468     * @hide
15469     */
15470    public void resetRtlProperties() {
15471        resetResolvedLayoutDirection();
15472        resetResolvedTextDirection();
15473        resetResolvedTextAlignment();
15474        resetResolvedPadding();
15475        resetResolvedDrawables();
15476    }
15477
15478    /**
15479     * @see #onScreenStateChanged(int)
15480     */
15481    void dispatchScreenStateChanged(int screenState) {
15482        onScreenStateChanged(screenState);
15483    }
15484
15485    /**
15486     * This method is called whenever the state of the screen this view is
15487     * attached to changes. A state change will usually occurs when the screen
15488     * turns on or off (whether it happens automatically or the user does it
15489     * manually.)
15490     *
15491     * @param screenState The new state of the screen. Can be either
15492     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
15493     */
15494    public void onScreenStateChanged(int screenState) {
15495    }
15496
15497    /**
15498     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
15499     */
15500    private boolean hasRtlSupport() {
15501        return mContext.getApplicationInfo().hasRtlSupport();
15502    }
15503
15504    /**
15505     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
15506     * RTL not supported)
15507     */
15508    private boolean isRtlCompatibilityMode() {
15509        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
15510        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
15511    }
15512
15513    /**
15514     * @return true if RTL properties need resolution.
15515     *
15516     */
15517    private boolean needRtlPropertiesResolution() {
15518        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
15519    }
15520
15521    /**
15522     * Called when any RTL property (layout direction or text direction or text alignment) has
15523     * been changed.
15524     *
15525     * Subclasses need to override this method to take care of cached information that depends on the
15526     * resolved layout direction, or to inform child views that inherit their layout direction.
15527     *
15528     * The default implementation does nothing.
15529     *
15530     * @param layoutDirection the direction of the layout
15531     *
15532     * @see #LAYOUT_DIRECTION_LTR
15533     * @see #LAYOUT_DIRECTION_RTL
15534     */
15535    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
15536    }
15537
15538    /**
15539     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
15540     * that the parent directionality can and will be resolved before its children.
15541     *
15542     * @return true if resolution has been done, false otherwise.
15543     *
15544     * @hide
15545     */
15546    public boolean resolveLayoutDirection() {
15547        // Clear any previous layout direction resolution
15548        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15549
15550        if (hasRtlSupport()) {
15551            // Set resolved depending on layout direction
15552            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
15553                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
15554                case LAYOUT_DIRECTION_INHERIT:
15555                    // We cannot resolve yet. LTR is by default and let the resolution happen again
15556                    // later to get the correct resolved value
15557                    if (!canResolveLayoutDirection()) return false;
15558
15559                    // Parent has not yet resolved, LTR is still the default
15560                    try {
15561                        if (!mParent.isLayoutDirectionResolved()) return false;
15562
15563                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15564                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15565                        }
15566                    } catch (AbstractMethodError e) {
15567                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15568                                " does not fully implement ViewParent", e);
15569                    }
15570                    break;
15571                case LAYOUT_DIRECTION_RTL:
15572                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15573                    break;
15574                case LAYOUT_DIRECTION_LOCALE:
15575                    if((LAYOUT_DIRECTION_RTL ==
15576                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
15577                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15578                    }
15579                    break;
15580                default:
15581                    // Nothing to do, LTR by default
15582            }
15583        }
15584
15585        // Set to resolved
15586        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15587        return true;
15588    }
15589
15590    /**
15591     * Check if layout direction resolution can be done.
15592     *
15593     * @return true if layout direction resolution can be done otherwise return false.
15594     */
15595    public boolean canResolveLayoutDirection() {
15596        switch (getRawLayoutDirection()) {
15597            case LAYOUT_DIRECTION_INHERIT:
15598                if (mParent != null) {
15599                    try {
15600                        return mParent.canResolveLayoutDirection();
15601                    } catch (AbstractMethodError e) {
15602                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15603                                " does not fully implement ViewParent", e);
15604                    }
15605                }
15606                return false;
15607
15608            default:
15609                return true;
15610        }
15611    }
15612
15613    /**
15614     * Reset the resolved layout direction. Layout direction will be resolved during a call to
15615     * {@link #onMeasure(int, int)}.
15616     *
15617     * @hide
15618     */
15619    public void resetResolvedLayoutDirection() {
15620        // Reset the current resolved bits
15621        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15622    }
15623
15624    /**
15625     * @return true if the layout direction is inherited.
15626     *
15627     * @hide
15628     */
15629    public boolean isLayoutDirectionInherited() {
15630        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
15631    }
15632
15633    /**
15634     * @return true if layout direction has been resolved.
15635     */
15636    public boolean isLayoutDirectionResolved() {
15637        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15638    }
15639
15640    /**
15641     * Return if padding has been resolved
15642     *
15643     * @hide
15644     */
15645    boolean isPaddingResolved() {
15646        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
15647    }
15648
15649    /**
15650     * Resolves padding depending on layout direction, if applicable, and
15651     * recomputes internal padding values to adjust for scroll bars.
15652     *
15653     * @hide
15654     */
15655    public void resolvePadding() {
15656        final int resolvedLayoutDirection = getLayoutDirection();
15657
15658        if (!isRtlCompatibilityMode()) {
15659            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
15660            // If start / end padding are defined, they will be resolved (hence overriding) to
15661            // left / right or right / left depending on the resolved layout direction.
15662            // If start / end padding are not defined, use the left / right ones.
15663            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
15664                Rect padding = sThreadLocal.get();
15665                if (padding == null) {
15666                    padding = new Rect();
15667                    sThreadLocal.set(padding);
15668                }
15669                mBackground.getPadding(padding);
15670                if (!mLeftPaddingDefined) {
15671                    mUserPaddingLeftInitial = padding.left;
15672                }
15673                if (!mRightPaddingDefined) {
15674                    mUserPaddingRightInitial = padding.right;
15675                }
15676            }
15677            switch (resolvedLayoutDirection) {
15678                case LAYOUT_DIRECTION_RTL:
15679                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15680                        mUserPaddingRight = mUserPaddingStart;
15681                    } else {
15682                        mUserPaddingRight = mUserPaddingRightInitial;
15683                    }
15684                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15685                        mUserPaddingLeft = mUserPaddingEnd;
15686                    } else {
15687                        mUserPaddingLeft = mUserPaddingLeftInitial;
15688                    }
15689                    break;
15690                case LAYOUT_DIRECTION_LTR:
15691                default:
15692                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15693                        mUserPaddingLeft = mUserPaddingStart;
15694                    } else {
15695                        mUserPaddingLeft = mUserPaddingLeftInitial;
15696                    }
15697                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15698                        mUserPaddingRight = mUserPaddingEnd;
15699                    } else {
15700                        mUserPaddingRight = mUserPaddingRightInitial;
15701                    }
15702            }
15703
15704            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
15705        }
15706
15707        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15708        onRtlPropertiesChanged(resolvedLayoutDirection);
15709
15710        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
15711    }
15712
15713    /**
15714     * Reset the resolved layout direction.
15715     *
15716     * @hide
15717     */
15718    public void resetResolvedPadding() {
15719        resetResolvedPaddingInternal();
15720    }
15721
15722    /**
15723     * Used when we only want to reset *this* view's padding and not trigger overrides
15724     * in ViewGroup that reset children too.
15725     */
15726    void resetResolvedPaddingInternal() {
15727        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
15728    }
15729
15730    /**
15731     * This is called when the view is detached from a window.  At this point it
15732     * no longer has a surface for drawing.
15733     *
15734     * @see #onAttachedToWindow()
15735     */
15736    @CallSuper
15737    protected void onDetachedFromWindow() {
15738    }
15739
15740    /**
15741     * This is a framework-internal mirror of onDetachedFromWindow() that's called
15742     * after onDetachedFromWindow().
15743     *
15744     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
15745     * The super method should be called at the end of the overridden method to ensure
15746     * subclasses are destroyed first
15747     *
15748     * @hide
15749     */
15750    @CallSuper
15751    protected void onDetachedFromWindowInternal() {
15752        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
15753        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15754        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
15755
15756        removeUnsetPressCallback();
15757        removeLongPressCallback();
15758        removePerformClickCallback();
15759        removeSendViewScrolledAccessibilityEventCallback();
15760        stopNestedScroll();
15761
15762        // Anything that started animating right before detach should already
15763        // be in its final state when re-attached.
15764        jumpDrawablesToCurrentState();
15765
15766        destroyDrawingCache();
15767
15768        cleanupDraw();
15769        mCurrentAnimation = null;
15770
15771        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
15772            hideTooltip();
15773        }
15774    }
15775
15776    private void cleanupDraw() {
15777        resetDisplayList();
15778        if (mAttachInfo != null) {
15779            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
15780        }
15781    }
15782
15783    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
15784    }
15785
15786    /**
15787     * @return The number of times this view has been attached to a window
15788     */
15789    protected int getWindowAttachCount() {
15790        return mWindowAttachCount;
15791    }
15792
15793    /**
15794     * Retrieve a unique token identifying the window this view is attached to.
15795     * @return Return the window's token for use in
15796     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
15797     */
15798    public IBinder getWindowToken() {
15799        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
15800    }
15801
15802    /**
15803     * Retrieve the {@link WindowId} for the window this view is
15804     * currently attached to.
15805     */
15806    public WindowId getWindowId() {
15807        if (mAttachInfo == null) {
15808            return null;
15809        }
15810        if (mAttachInfo.mWindowId == null) {
15811            try {
15812                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
15813                        mAttachInfo.mWindowToken);
15814                mAttachInfo.mWindowId = new WindowId(
15815                        mAttachInfo.mIWindowId);
15816            } catch (RemoteException e) {
15817            }
15818        }
15819        return mAttachInfo.mWindowId;
15820    }
15821
15822    /**
15823     * Retrieve a unique token identifying the top-level "real" window of
15824     * the window that this view is attached to.  That is, this is like
15825     * {@link #getWindowToken}, except if the window this view in is a panel
15826     * window (attached to another containing window), then the token of
15827     * the containing window is returned instead.
15828     *
15829     * @return Returns the associated window token, either
15830     * {@link #getWindowToken()} or the containing window's token.
15831     */
15832    public IBinder getApplicationWindowToken() {
15833        AttachInfo ai = mAttachInfo;
15834        if (ai != null) {
15835            IBinder appWindowToken = ai.mPanelParentWindowToken;
15836            if (appWindowToken == null) {
15837                appWindowToken = ai.mWindowToken;
15838            }
15839            return appWindowToken;
15840        }
15841        return null;
15842    }
15843
15844    /**
15845     * Gets the logical display to which the view's window has been attached.
15846     *
15847     * @return The logical display, or null if the view is not currently attached to a window.
15848     */
15849    public Display getDisplay() {
15850        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
15851    }
15852
15853    /**
15854     * Retrieve private session object this view hierarchy is using to
15855     * communicate with the window manager.
15856     * @return the session object to communicate with the window manager
15857     */
15858    /*package*/ IWindowSession getWindowSession() {
15859        return mAttachInfo != null ? mAttachInfo.mSession : null;
15860    }
15861
15862    /**
15863     * Return the visibility value of the least visible component passed.
15864     */
15865    int combineVisibility(int vis1, int vis2) {
15866        // This works because VISIBLE < INVISIBLE < GONE.
15867        return Math.max(vis1, vis2);
15868    }
15869
15870    /**
15871     * @param info the {@link android.view.View.AttachInfo} to associated with
15872     *        this view
15873     */
15874    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
15875        mAttachInfo = info;
15876        if (mOverlay != null) {
15877            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
15878        }
15879        mWindowAttachCount++;
15880        // We will need to evaluate the drawable state at least once.
15881        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15882        if (mFloatingTreeObserver != null) {
15883            info.mTreeObserver.merge(mFloatingTreeObserver);
15884            mFloatingTreeObserver = null;
15885        }
15886
15887        registerPendingFrameMetricsObservers();
15888
15889        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
15890            mAttachInfo.mScrollContainers.add(this);
15891            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
15892        }
15893        // Transfer all pending runnables.
15894        if (mRunQueue != null) {
15895            mRunQueue.executeActions(info.mHandler);
15896            mRunQueue = null;
15897        }
15898        performCollectViewAttributes(mAttachInfo, visibility);
15899        onAttachedToWindow();
15900
15901        ListenerInfo li = mListenerInfo;
15902        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15903                li != null ? li.mOnAttachStateChangeListeners : null;
15904        if (listeners != null && listeners.size() > 0) {
15905            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15906            // perform the dispatching. The iterator is a safe guard against listeners that
15907            // could mutate the list by calling the various add/remove methods. This prevents
15908            // the array from being modified while we iterate it.
15909            for (OnAttachStateChangeListener listener : listeners) {
15910                listener.onViewAttachedToWindow(this);
15911            }
15912        }
15913
15914        int vis = info.mWindowVisibility;
15915        if (vis != GONE) {
15916            onWindowVisibilityChanged(vis);
15917            if (isShown()) {
15918                // Calling onVisibilityAggregated directly here since the subtree will also
15919                // receive dispatchAttachedToWindow and this same call
15920                onVisibilityAggregated(vis == VISIBLE);
15921            }
15922        }
15923
15924        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
15925        // As all views in the subtree will already receive dispatchAttachedToWindow
15926        // traversing the subtree again here is not desired.
15927        onVisibilityChanged(this, visibility);
15928
15929        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
15930            // If nobody has evaluated the drawable state yet, then do it now.
15931            refreshDrawableState();
15932        }
15933        needGlobalAttributesUpdate(false);
15934    }
15935
15936    void dispatchDetachedFromWindow() {
15937        AttachInfo info = mAttachInfo;
15938        if (info != null) {
15939            int vis = info.mWindowVisibility;
15940            if (vis != GONE) {
15941                onWindowVisibilityChanged(GONE);
15942                if (isShown()) {
15943                    // Invoking onVisibilityAggregated directly here since the subtree
15944                    // will also receive detached from window
15945                    onVisibilityAggregated(false);
15946                }
15947            }
15948        }
15949
15950        onDetachedFromWindow();
15951        onDetachedFromWindowInternal();
15952
15953        InputMethodManager imm = InputMethodManager.peekInstance();
15954        if (imm != null) {
15955            imm.onViewDetachedFromWindow(this);
15956        }
15957
15958        ListenerInfo li = mListenerInfo;
15959        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
15960                li != null ? li.mOnAttachStateChangeListeners : null;
15961        if (listeners != null && listeners.size() > 0) {
15962            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
15963            // perform the dispatching. The iterator is a safe guard against listeners that
15964            // could mutate the list by calling the various add/remove methods. This prevents
15965            // the array from being modified while we iterate it.
15966            for (OnAttachStateChangeListener listener : listeners) {
15967                listener.onViewDetachedFromWindow(this);
15968            }
15969        }
15970
15971        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
15972            mAttachInfo.mScrollContainers.remove(this);
15973            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
15974        }
15975
15976        mAttachInfo = null;
15977        if (mOverlay != null) {
15978            mOverlay.getOverlayView().dispatchDetachedFromWindow();
15979        }
15980    }
15981
15982    /**
15983     * Cancel any deferred high-level input events that were previously posted to the event queue.
15984     *
15985     * <p>Many views post high-level events such as click handlers to the event queue
15986     * to run deferred in order to preserve a desired user experience - clearing visible
15987     * pressed states before executing, etc. This method will abort any events of this nature
15988     * that are currently in flight.</p>
15989     *
15990     * <p>Custom views that generate their own high-level deferred input events should override
15991     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
15992     *
15993     * <p>This will also cancel pending input events for any child views.</p>
15994     *
15995     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
15996     * This will not impact newer events posted after this call that may occur as a result of
15997     * lower-level input events still waiting in the queue. If you are trying to prevent
15998     * double-submitted  events for the duration of some sort of asynchronous transaction
15999     * you should also take other steps to protect against unexpected double inputs e.g. calling
16000     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
16001     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
16002     */
16003    public final void cancelPendingInputEvents() {
16004        dispatchCancelPendingInputEvents();
16005    }
16006
16007    /**
16008     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
16009     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
16010     */
16011    void dispatchCancelPendingInputEvents() {
16012        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
16013        onCancelPendingInputEvents();
16014        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
16015            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
16016                    " did not call through to super.onCancelPendingInputEvents()");
16017        }
16018    }
16019
16020    /**
16021     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
16022     * a parent view.
16023     *
16024     * <p>This method is responsible for removing any pending high-level input events that were
16025     * posted to the event queue to run later. Custom view classes that post their own deferred
16026     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
16027     * {@link android.os.Handler} should override this method, call
16028     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
16029     * </p>
16030     */
16031    public void onCancelPendingInputEvents() {
16032        removePerformClickCallback();
16033        cancelLongPress();
16034        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
16035    }
16036
16037    /**
16038     * Store this view hierarchy's frozen state into the given container.
16039     *
16040     * @param container The SparseArray in which to save the view's state.
16041     *
16042     * @see #restoreHierarchyState(android.util.SparseArray)
16043     * @see #dispatchSaveInstanceState(android.util.SparseArray)
16044     * @see #onSaveInstanceState()
16045     */
16046    public void saveHierarchyState(SparseArray<Parcelable> container) {
16047        dispatchSaveInstanceState(container);
16048    }
16049
16050    /**
16051     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
16052     * this view and its children. May be overridden to modify how freezing happens to a
16053     * view's children; for example, some views may want to not store state for their children.
16054     *
16055     * @param container The SparseArray in which to save the view's state.
16056     *
16057     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
16058     * @see #saveHierarchyState(android.util.SparseArray)
16059     * @see #onSaveInstanceState()
16060     */
16061    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
16062        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
16063            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
16064            Parcelable state = onSaveInstanceState();
16065            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
16066                throw new IllegalStateException(
16067                        "Derived class did not call super.onSaveInstanceState()");
16068            }
16069            if (state != null) {
16070                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
16071                // + ": " + state);
16072                container.put(mID, state);
16073            }
16074        }
16075    }
16076
16077    /**
16078     * Hook allowing a view to generate a representation of its internal state
16079     * that can later be used to create a new instance with that same state.
16080     * This state should only contain information that is not persistent or can
16081     * not be reconstructed later. For example, you will never store your
16082     * current position on screen because that will be computed again when a
16083     * new instance of the view is placed in its view hierarchy.
16084     * <p>
16085     * Some examples of things you may store here: the current cursor position
16086     * in a text view (but usually not the text itself since that is stored in a
16087     * content provider or other persistent storage), the currently selected
16088     * item in a list view.
16089     *
16090     * @return Returns a Parcelable object containing the view's current dynamic
16091     *         state, or null if there is nothing interesting to save. The
16092     *         default implementation returns null.
16093     * @see #onRestoreInstanceState(android.os.Parcelable)
16094     * @see #saveHierarchyState(android.util.SparseArray)
16095     * @see #dispatchSaveInstanceState(android.util.SparseArray)
16096     * @see #setSaveEnabled(boolean)
16097     */
16098    @CallSuper
16099    protected Parcelable onSaveInstanceState() {
16100        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
16101        if (mStartActivityRequestWho != null) {
16102            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
16103            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
16104            return state;
16105        }
16106        return BaseSavedState.EMPTY_STATE;
16107    }
16108
16109    /**
16110     * Restore this view hierarchy's frozen state from the given container.
16111     *
16112     * @param container The SparseArray which holds previously frozen states.
16113     *
16114     * @see #saveHierarchyState(android.util.SparseArray)
16115     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
16116     * @see #onRestoreInstanceState(android.os.Parcelable)
16117     */
16118    public void restoreHierarchyState(SparseArray<Parcelable> container) {
16119        dispatchRestoreInstanceState(container);
16120    }
16121
16122    /**
16123     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
16124     * state for this view and its children. May be overridden to modify how restoring
16125     * happens to a view's children; for example, some views may want to not store state
16126     * for their children.
16127     *
16128     * @param container The SparseArray which holds previously saved state.
16129     *
16130     * @see #dispatchSaveInstanceState(android.util.SparseArray)
16131     * @see #restoreHierarchyState(android.util.SparseArray)
16132     * @see #onRestoreInstanceState(android.os.Parcelable)
16133     */
16134    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
16135        if (mID != NO_ID) {
16136            Parcelable state = container.get(mID);
16137            if (state != null) {
16138                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
16139                // + ": " + state);
16140                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
16141                onRestoreInstanceState(state);
16142                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
16143                    throw new IllegalStateException(
16144                            "Derived class did not call super.onRestoreInstanceState()");
16145                }
16146            }
16147        }
16148    }
16149
16150    /**
16151     * Hook allowing a view to re-apply a representation of its internal state that had previously
16152     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
16153     * null state.
16154     *
16155     * @param state The frozen state that had previously been returned by
16156     *        {@link #onSaveInstanceState}.
16157     *
16158     * @see #onSaveInstanceState()
16159     * @see #restoreHierarchyState(android.util.SparseArray)
16160     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
16161     */
16162    @CallSuper
16163    protected void onRestoreInstanceState(Parcelable state) {
16164        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
16165        if (state != null && !(state instanceof AbsSavedState)) {
16166            throw new IllegalArgumentException("Wrong state class, expecting View State but "
16167                    + "received " + state.getClass().toString() + " instead. This usually happens "
16168                    + "when two views of different type have the same id in the same hierarchy. "
16169                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
16170                    + "other views do not use the same id.");
16171        }
16172        if (state != null && state instanceof BaseSavedState) {
16173            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
16174        }
16175    }
16176
16177    /**
16178     * <p>Return the time at which the drawing of the view hierarchy started.</p>
16179     *
16180     * @return the drawing start time in milliseconds
16181     */
16182    public long getDrawingTime() {
16183        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
16184    }
16185
16186    /**
16187     * <p>Enables or disables the duplication of the parent's state into this view. When
16188     * duplication is enabled, this view gets its drawable state from its parent rather
16189     * than from its own internal properties.</p>
16190     *
16191     * <p>Note: in the current implementation, setting this property to true after the
16192     * view was added to a ViewGroup might have no effect at all. This property should
16193     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
16194     *
16195     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
16196     * property is enabled, an exception will be thrown.</p>
16197     *
16198     * <p>Note: if the child view uses and updates additional states which are unknown to the
16199     * parent, these states should not be affected by this method.</p>
16200     *
16201     * @param enabled True to enable duplication of the parent's drawable state, false
16202     *                to disable it.
16203     *
16204     * @see #getDrawableState()
16205     * @see #isDuplicateParentStateEnabled()
16206     */
16207    public void setDuplicateParentStateEnabled(boolean enabled) {
16208        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
16209    }
16210
16211    /**
16212     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
16213     *
16214     * @return True if this view's drawable state is duplicated from the parent,
16215     *         false otherwise
16216     *
16217     * @see #getDrawableState()
16218     * @see #setDuplicateParentStateEnabled(boolean)
16219     */
16220    public boolean isDuplicateParentStateEnabled() {
16221        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
16222    }
16223
16224    /**
16225     * <p>Specifies the type of layer backing this view. The layer can be
16226     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
16227     * {@link #LAYER_TYPE_HARDWARE}.</p>
16228     *
16229     * <p>A layer is associated with an optional {@link android.graphics.Paint}
16230     * instance that controls how the layer is composed on screen. The following
16231     * properties of the paint are taken into account when composing the layer:</p>
16232     * <ul>
16233     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
16234     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
16235     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
16236     * </ul>
16237     *
16238     * <p>If this view has an alpha value set to < 1.0 by calling
16239     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
16240     * by this view's alpha value.</p>
16241     *
16242     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
16243     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
16244     * for more information on when and how to use layers.</p>
16245     *
16246     * @param layerType The type of layer to use with this view, must be one of
16247     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
16248     *        {@link #LAYER_TYPE_HARDWARE}
16249     * @param paint The paint used to compose the layer. This argument is optional
16250     *        and can be null. It is ignored when the layer type is
16251     *        {@link #LAYER_TYPE_NONE}
16252     *
16253     * @see #getLayerType()
16254     * @see #LAYER_TYPE_NONE
16255     * @see #LAYER_TYPE_SOFTWARE
16256     * @see #LAYER_TYPE_HARDWARE
16257     * @see #setAlpha(float)
16258     *
16259     * @attr ref android.R.styleable#View_layerType
16260     */
16261    public void setLayerType(int layerType, @Nullable Paint paint) {
16262        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
16263            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
16264                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
16265        }
16266
16267        boolean typeChanged = mRenderNode.setLayerType(layerType);
16268
16269        if (!typeChanged) {
16270            setLayerPaint(paint);
16271            return;
16272        }
16273
16274        if (layerType != LAYER_TYPE_SOFTWARE) {
16275            // Destroy any previous software drawing cache if present
16276            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
16277            // drawing cache created in View#draw when drawing to a SW canvas.
16278            destroyDrawingCache();
16279        }
16280
16281        mLayerType = layerType;
16282        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
16283        mRenderNode.setLayerPaint(mLayerPaint);
16284
16285        // draw() behaves differently if we are on a layer, so we need to
16286        // invalidate() here
16287        invalidateParentCaches();
16288        invalidate(true);
16289    }
16290
16291    /**
16292     * Updates the {@link Paint} object used with the current layer (used only if the current
16293     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
16294     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
16295     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
16296     * ensure that the view gets redrawn immediately.
16297     *
16298     * <p>A layer is associated with an optional {@link android.graphics.Paint}
16299     * instance that controls how the layer is composed on screen. The following
16300     * properties of the paint are taken into account when composing the layer:</p>
16301     * <ul>
16302     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
16303     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
16304     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
16305     * </ul>
16306     *
16307     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
16308     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
16309     *
16310     * @param paint The paint used to compose the layer. This argument is optional
16311     *        and can be null. It is ignored when the layer type is
16312     *        {@link #LAYER_TYPE_NONE}
16313     *
16314     * @see #setLayerType(int, android.graphics.Paint)
16315     */
16316    public void setLayerPaint(@Nullable Paint paint) {
16317        int layerType = getLayerType();
16318        if (layerType != LAYER_TYPE_NONE) {
16319            mLayerPaint = paint;
16320            if (layerType == LAYER_TYPE_HARDWARE) {
16321                if (mRenderNode.setLayerPaint(paint)) {
16322                    invalidateViewProperty(false, false);
16323                }
16324            } else {
16325                invalidate();
16326            }
16327        }
16328    }
16329
16330    /**
16331     * Indicates what type of layer is currently associated with this view. By default
16332     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
16333     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
16334     * for more information on the different types of layers.
16335     *
16336     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
16337     *         {@link #LAYER_TYPE_HARDWARE}
16338     *
16339     * @see #setLayerType(int, android.graphics.Paint)
16340     * @see #buildLayer()
16341     * @see #LAYER_TYPE_NONE
16342     * @see #LAYER_TYPE_SOFTWARE
16343     * @see #LAYER_TYPE_HARDWARE
16344     */
16345    public int getLayerType() {
16346        return mLayerType;
16347    }
16348
16349    /**
16350     * Forces this view's layer to be created and this view to be rendered
16351     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
16352     * invoking this method will have no effect.
16353     *
16354     * This method can for instance be used to render a view into its layer before
16355     * starting an animation. If this view is complex, rendering into the layer
16356     * before starting the animation will avoid skipping frames.
16357     *
16358     * @throws IllegalStateException If this view is not attached to a window
16359     *
16360     * @see #setLayerType(int, android.graphics.Paint)
16361     */
16362    public void buildLayer() {
16363        if (mLayerType == LAYER_TYPE_NONE) return;
16364
16365        final AttachInfo attachInfo = mAttachInfo;
16366        if (attachInfo == null) {
16367            throw new IllegalStateException("This view must be attached to a window first");
16368        }
16369
16370        if (getWidth() == 0 || getHeight() == 0) {
16371            return;
16372        }
16373
16374        switch (mLayerType) {
16375            case LAYER_TYPE_HARDWARE:
16376                updateDisplayListIfDirty();
16377                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
16378                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
16379                }
16380                break;
16381            case LAYER_TYPE_SOFTWARE:
16382                buildDrawingCache(true);
16383                break;
16384        }
16385    }
16386
16387    /**
16388     * Destroys all hardware rendering resources. This method is invoked
16389     * when the system needs to reclaim resources. Upon execution of this
16390     * method, you should free any OpenGL resources created by the view.
16391     *
16392     * Note: you <strong>must</strong> call
16393     * <code>super.destroyHardwareResources()</code> when overriding
16394     * this method.
16395     *
16396     * @hide
16397     */
16398    @CallSuper
16399    protected void destroyHardwareResources() {
16400        // Although the Layer will be destroyed by RenderNode, we want to release
16401        // the staging display list, which is also a signal to RenderNode that it's
16402        // safe to free its copy of the display list as it knows that we will
16403        // push an updated DisplayList if we try to draw again
16404        resetDisplayList();
16405    }
16406
16407    /**
16408     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
16409     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
16410     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
16411     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
16412     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
16413     * null.</p>
16414     *
16415     * <p>Enabling the drawing cache is similar to
16416     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
16417     * acceleration is turned off. When hardware acceleration is turned on, enabling the
16418     * drawing cache has no effect on rendering because the system uses a different mechanism
16419     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
16420     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
16421     * for information on how to enable software and hardware layers.</p>
16422     *
16423     * <p>This API can be used to manually generate
16424     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
16425     * {@link #getDrawingCache()}.</p>
16426     *
16427     * @param enabled true to enable the drawing cache, false otherwise
16428     *
16429     * @see #isDrawingCacheEnabled()
16430     * @see #getDrawingCache()
16431     * @see #buildDrawingCache()
16432     * @see #setLayerType(int, android.graphics.Paint)
16433     */
16434    public void setDrawingCacheEnabled(boolean enabled) {
16435        mCachingFailed = false;
16436        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
16437    }
16438
16439    /**
16440     * <p>Indicates whether the drawing cache is enabled for this view.</p>
16441     *
16442     * @return true if the drawing cache is enabled
16443     *
16444     * @see #setDrawingCacheEnabled(boolean)
16445     * @see #getDrawingCache()
16446     */
16447    @ViewDebug.ExportedProperty(category = "drawing")
16448    public boolean isDrawingCacheEnabled() {
16449        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
16450    }
16451
16452    /**
16453     * Debugging utility which recursively outputs the dirty state of a view and its
16454     * descendants.
16455     *
16456     * @hide
16457     */
16458    @SuppressWarnings({"UnusedDeclaration"})
16459    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
16460        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
16461                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
16462                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
16463                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
16464        if (clear) {
16465            mPrivateFlags &= clearMask;
16466        }
16467        if (this instanceof ViewGroup) {
16468            ViewGroup parent = (ViewGroup) this;
16469            final int count = parent.getChildCount();
16470            for (int i = 0; i < count; i++) {
16471                final View child = parent.getChildAt(i);
16472                child.outputDirtyFlags(indent + "  ", clear, clearMask);
16473            }
16474        }
16475    }
16476
16477    /**
16478     * This method is used by ViewGroup to cause its children to restore or recreate their
16479     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
16480     * to recreate its own display list, which would happen if it went through the normal
16481     * draw/dispatchDraw mechanisms.
16482     *
16483     * @hide
16484     */
16485    protected void dispatchGetDisplayList() {}
16486
16487    /**
16488     * A view that is not attached or hardware accelerated cannot create a display list.
16489     * This method checks these conditions and returns the appropriate result.
16490     *
16491     * @return true if view has the ability to create a display list, false otherwise.
16492     *
16493     * @hide
16494     */
16495    public boolean canHaveDisplayList() {
16496        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
16497    }
16498
16499    /**
16500     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
16501     * @hide
16502     */
16503    @NonNull
16504    public RenderNode updateDisplayListIfDirty() {
16505        final RenderNode renderNode = mRenderNode;
16506        if (!canHaveDisplayList()) {
16507            // can't populate RenderNode, don't try
16508            return renderNode;
16509        }
16510
16511        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
16512                || !renderNode.isValid()
16513                || (mRecreateDisplayList)) {
16514            // Don't need to recreate the display list, just need to tell our
16515            // children to restore/recreate theirs
16516            if (renderNode.isValid()
16517                    && !mRecreateDisplayList) {
16518                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16519                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16520                dispatchGetDisplayList();
16521
16522                return renderNode; // no work needed
16523            }
16524
16525            // If we got here, we're recreating it. Mark it as such to ensure that
16526            // we copy in child display lists into ours in drawChild()
16527            mRecreateDisplayList = true;
16528
16529            int width = mRight - mLeft;
16530            int height = mBottom - mTop;
16531            int layerType = getLayerType();
16532
16533            final DisplayListCanvas canvas = renderNode.start(width, height);
16534            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
16535
16536            try {
16537                if (layerType == LAYER_TYPE_SOFTWARE) {
16538                    buildDrawingCache(true);
16539                    Bitmap cache = getDrawingCache(true);
16540                    if (cache != null) {
16541                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
16542                    }
16543                } else {
16544                    computeScroll();
16545
16546                    canvas.translate(-mScrollX, -mScrollY);
16547                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16548                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16549
16550                    // Fast path for layouts with no backgrounds
16551                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16552                        dispatchDraw(canvas);
16553                        if (mOverlay != null && !mOverlay.isEmpty()) {
16554                            mOverlay.getOverlayView().draw(canvas);
16555                        }
16556                        if (debugDraw()) {
16557                            debugDrawFocus(canvas);
16558                        }
16559                    } else {
16560                        draw(canvas);
16561                    }
16562                }
16563            } finally {
16564                renderNode.end(canvas);
16565                setDisplayListProperties(renderNode);
16566            }
16567        } else {
16568            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16569            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16570        }
16571        return renderNode;
16572    }
16573
16574    private void resetDisplayList() {
16575        if (mRenderNode.isValid()) {
16576            mRenderNode.discardDisplayList();
16577        }
16578
16579        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
16580            mBackgroundRenderNode.discardDisplayList();
16581        }
16582    }
16583
16584    /**
16585     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
16586     *
16587     * @return A non-scaled bitmap representing this view or null if cache is disabled.
16588     *
16589     * @see #getDrawingCache(boolean)
16590     */
16591    public Bitmap getDrawingCache() {
16592        return getDrawingCache(false);
16593    }
16594
16595    /**
16596     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
16597     * is null when caching is disabled. If caching is enabled and the cache is not ready,
16598     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
16599     * draw from the cache when the cache is enabled. To benefit from the cache, you must
16600     * request the drawing cache by calling this method and draw it on screen if the
16601     * returned bitmap is not null.</p>
16602     *
16603     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16604     * this method will create a bitmap of the same size as this view. Because this bitmap
16605     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16606     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16607     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16608     * size than the view. This implies that your application must be able to handle this
16609     * size.</p>
16610     *
16611     * @param autoScale Indicates whether the generated bitmap should be scaled based on
16612     *        the current density of the screen when the application is in compatibility
16613     *        mode.
16614     *
16615     * @return A bitmap representing this view or null if cache is disabled.
16616     *
16617     * @see #setDrawingCacheEnabled(boolean)
16618     * @see #isDrawingCacheEnabled()
16619     * @see #buildDrawingCache(boolean)
16620     * @see #destroyDrawingCache()
16621     */
16622    public Bitmap getDrawingCache(boolean autoScale) {
16623        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
16624            return null;
16625        }
16626        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
16627            buildDrawingCache(autoScale);
16628        }
16629        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
16630    }
16631
16632    /**
16633     * <p>Frees the resources used by the drawing cache. If you call
16634     * {@link #buildDrawingCache()} manually without calling
16635     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16636     * should cleanup the cache with this method afterwards.</p>
16637     *
16638     * @see #setDrawingCacheEnabled(boolean)
16639     * @see #buildDrawingCache()
16640     * @see #getDrawingCache()
16641     */
16642    public void destroyDrawingCache() {
16643        if (mDrawingCache != null) {
16644            mDrawingCache.recycle();
16645            mDrawingCache = null;
16646        }
16647        if (mUnscaledDrawingCache != null) {
16648            mUnscaledDrawingCache.recycle();
16649            mUnscaledDrawingCache = null;
16650        }
16651    }
16652
16653    /**
16654     * Setting a solid background color for the drawing cache's bitmaps will improve
16655     * performance and memory usage. Note, though that this should only be used if this
16656     * view will always be drawn on top of a solid color.
16657     *
16658     * @param color The background color to use for the drawing cache's bitmap
16659     *
16660     * @see #setDrawingCacheEnabled(boolean)
16661     * @see #buildDrawingCache()
16662     * @see #getDrawingCache()
16663     */
16664    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
16665        if (color != mDrawingCacheBackgroundColor) {
16666            mDrawingCacheBackgroundColor = color;
16667            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16668        }
16669    }
16670
16671    /**
16672     * @see #setDrawingCacheBackgroundColor(int)
16673     *
16674     * @return The background color to used for the drawing cache's bitmap
16675     */
16676    @ColorInt
16677    public int getDrawingCacheBackgroundColor() {
16678        return mDrawingCacheBackgroundColor;
16679    }
16680
16681    /**
16682     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
16683     *
16684     * @see #buildDrawingCache(boolean)
16685     */
16686    public void buildDrawingCache() {
16687        buildDrawingCache(false);
16688    }
16689
16690    /**
16691     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
16692     *
16693     * <p>If you call {@link #buildDrawingCache()} manually without calling
16694     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16695     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
16696     *
16697     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16698     * this method will create a bitmap of the same size as this view. Because this bitmap
16699     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16700     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16701     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16702     * size than the view. This implies that your application must be able to handle this
16703     * size.</p>
16704     *
16705     * <p>You should avoid calling this method when hardware acceleration is enabled. If
16706     * you do not need the drawing cache bitmap, calling this method will increase memory
16707     * usage and cause the view to be rendered in software once, thus negatively impacting
16708     * performance.</p>
16709     *
16710     * @see #getDrawingCache()
16711     * @see #destroyDrawingCache()
16712     */
16713    public void buildDrawingCache(boolean autoScale) {
16714        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
16715                mDrawingCache == null : mUnscaledDrawingCache == null)) {
16716            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
16717                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
16718                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
16719            }
16720            try {
16721                buildDrawingCacheImpl(autoScale);
16722            } finally {
16723                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
16724            }
16725        }
16726    }
16727
16728    /**
16729     * private, internal implementation of buildDrawingCache, used to enable tracing
16730     */
16731    private void buildDrawingCacheImpl(boolean autoScale) {
16732        mCachingFailed = false;
16733
16734        int width = mRight - mLeft;
16735        int height = mBottom - mTop;
16736
16737        final AttachInfo attachInfo = mAttachInfo;
16738        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
16739
16740        if (autoScale && scalingRequired) {
16741            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
16742            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
16743        }
16744
16745        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
16746        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
16747        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
16748
16749        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
16750        final long drawingCacheSize =
16751                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
16752        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
16753            if (width > 0 && height > 0) {
16754                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
16755                        + " too large to fit into a software layer (or drawing cache), needs "
16756                        + projectedBitmapSize + " bytes, only "
16757                        + drawingCacheSize + " available");
16758            }
16759            destroyDrawingCache();
16760            mCachingFailed = true;
16761            return;
16762        }
16763
16764        boolean clear = true;
16765        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
16766
16767        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
16768            Bitmap.Config quality;
16769            if (!opaque) {
16770                // Never pick ARGB_4444 because it looks awful
16771                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
16772                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
16773                    case DRAWING_CACHE_QUALITY_AUTO:
16774                    case DRAWING_CACHE_QUALITY_LOW:
16775                    case DRAWING_CACHE_QUALITY_HIGH:
16776                    default:
16777                        quality = Bitmap.Config.ARGB_8888;
16778                        break;
16779                }
16780            } else {
16781                // Optimization for translucent windows
16782                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
16783                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
16784            }
16785
16786            // Try to cleanup memory
16787            if (bitmap != null) bitmap.recycle();
16788
16789            try {
16790                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16791                        width, height, quality);
16792                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
16793                if (autoScale) {
16794                    mDrawingCache = bitmap;
16795                } else {
16796                    mUnscaledDrawingCache = bitmap;
16797                }
16798                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
16799            } catch (OutOfMemoryError e) {
16800                // If there is not enough memory to create the bitmap cache, just
16801                // ignore the issue as bitmap caches are not required to draw the
16802                // view hierarchy
16803                if (autoScale) {
16804                    mDrawingCache = null;
16805                } else {
16806                    mUnscaledDrawingCache = null;
16807                }
16808                mCachingFailed = true;
16809                return;
16810            }
16811
16812            clear = drawingCacheBackgroundColor != 0;
16813        }
16814
16815        Canvas canvas;
16816        if (attachInfo != null) {
16817            canvas = attachInfo.mCanvas;
16818            if (canvas == null) {
16819                canvas = new Canvas();
16820            }
16821            canvas.setBitmap(bitmap);
16822            // Temporarily clobber the cached Canvas in case one of our children
16823            // is also using a drawing cache. Without this, the children would
16824            // steal the canvas by attaching their own bitmap to it and bad, bad
16825            // thing would happen (invisible views, corrupted drawings, etc.)
16826            attachInfo.mCanvas = null;
16827        } else {
16828            // This case should hopefully never or seldom happen
16829            canvas = new Canvas(bitmap);
16830        }
16831
16832        if (clear) {
16833            bitmap.eraseColor(drawingCacheBackgroundColor);
16834        }
16835
16836        computeScroll();
16837        final int restoreCount = canvas.save();
16838
16839        if (autoScale && scalingRequired) {
16840            final float scale = attachInfo.mApplicationScale;
16841            canvas.scale(scale, scale);
16842        }
16843
16844        canvas.translate(-mScrollX, -mScrollY);
16845
16846        mPrivateFlags |= PFLAG_DRAWN;
16847        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
16848                mLayerType != LAYER_TYPE_NONE) {
16849            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
16850        }
16851
16852        // Fast path for layouts with no backgrounds
16853        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16854            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16855            dispatchDraw(canvas);
16856            if (mOverlay != null && !mOverlay.isEmpty()) {
16857                mOverlay.getOverlayView().draw(canvas);
16858            }
16859        } else {
16860            draw(canvas);
16861        }
16862
16863        canvas.restoreToCount(restoreCount);
16864        canvas.setBitmap(null);
16865
16866        if (attachInfo != null) {
16867            // Restore the cached Canvas for our siblings
16868            attachInfo.mCanvas = canvas;
16869        }
16870    }
16871
16872    /**
16873     * Create a snapshot of the view into a bitmap.  We should probably make
16874     * some form of this public, but should think about the API.
16875     *
16876     * @hide
16877     */
16878    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
16879        int width = mRight - mLeft;
16880        int height = mBottom - mTop;
16881
16882        final AttachInfo attachInfo = mAttachInfo;
16883        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
16884        width = (int) ((width * scale) + 0.5f);
16885        height = (int) ((height * scale) + 0.5f);
16886
16887        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
16888                width > 0 ? width : 1, height > 0 ? height : 1, quality);
16889        if (bitmap == null) {
16890            throw new OutOfMemoryError();
16891        }
16892
16893        Resources resources = getResources();
16894        if (resources != null) {
16895            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
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            // things 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 ((backgroundColor & 0xff000000) != 0) {
16916            bitmap.eraseColor(backgroundColor);
16917        }
16918
16919        computeScroll();
16920        final int restoreCount = canvas.save();
16921        canvas.scale(scale, scale);
16922        canvas.translate(-mScrollX, -mScrollY);
16923
16924        // Temporarily remove the dirty mask
16925        int flags = mPrivateFlags;
16926        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16927
16928        // Fast path for layouts with no backgrounds
16929        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16930            dispatchDraw(canvas);
16931            if (mOverlay != null && !mOverlay.isEmpty()) {
16932                mOverlay.getOverlayView().draw(canvas);
16933            }
16934        } else {
16935            draw(canvas);
16936        }
16937
16938        mPrivateFlags = flags;
16939
16940        canvas.restoreToCount(restoreCount);
16941        canvas.setBitmap(null);
16942
16943        if (attachInfo != null) {
16944            // Restore the cached Canvas for our siblings
16945            attachInfo.mCanvas = canvas;
16946        }
16947
16948        return bitmap;
16949    }
16950
16951    /**
16952     * Indicates whether this View is currently in edit mode. A View is usually
16953     * in edit mode when displayed within a developer tool. For instance, if
16954     * this View is being drawn by a visual user interface builder, this method
16955     * should return true.
16956     *
16957     * Subclasses should check the return value of this method to provide
16958     * different behaviors if their normal behavior might interfere with the
16959     * host environment. For instance: the class spawns a thread in its
16960     * constructor, the drawing code relies on device-specific features, etc.
16961     *
16962     * This method is usually checked in the drawing code of custom widgets.
16963     *
16964     * @return True if this View is in edit mode, false otherwise.
16965     */
16966    public boolean isInEditMode() {
16967        return false;
16968    }
16969
16970    /**
16971     * If the View draws content inside its padding and enables fading edges,
16972     * it needs to support padding offsets. Padding offsets are added to the
16973     * fading edges to extend the length of the fade so that it covers pixels
16974     * drawn inside the padding.
16975     *
16976     * Subclasses of this class should override this method if they need
16977     * to draw content inside the padding.
16978     *
16979     * @return True if padding offset must be applied, false otherwise.
16980     *
16981     * @see #getLeftPaddingOffset()
16982     * @see #getRightPaddingOffset()
16983     * @see #getTopPaddingOffset()
16984     * @see #getBottomPaddingOffset()
16985     *
16986     * @since CURRENT
16987     */
16988    protected boolean isPaddingOffsetRequired() {
16989        return false;
16990    }
16991
16992    /**
16993     * Amount by which to extend the left fading region. Called only when
16994     * {@link #isPaddingOffsetRequired()} returns true.
16995     *
16996     * @return The left padding offset in pixels.
16997     *
16998     * @see #isPaddingOffsetRequired()
16999     *
17000     * @since CURRENT
17001     */
17002    protected int getLeftPaddingOffset() {
17003        return 0;
17004    }
17005
17006    /**
17007     * Amount by which to extend the right fading region. Called only when
17008     * {@link #isPaddingOffsetRequired()} returns true.
17009     *
17010     * @return The right padding offset in pixels.
17011     *
17012     * @see #isPaddingOffsetRequired()
17013     *
17014     * @since CURRENT
17015     */
17016    protected int getRightPaddingOffset() {
17017        return 0;
17018    }
17019
17020    /**
17021     * Amount by which to extend the top fading region. Called only when
17022     * {@link #isPaddingOffsetRequired()} returns true.
17023     *
17024     * @return The top padding offset in pixels.
17025     *
17026     * @see #isPaddingOffsetRequired()
17027     *
17028     * @since CURRENT
17029     */
17030    protected int getTopPaddingOffset() {
17031        return 0;
17032    }
17033
17034    /**
17035     * Amount by which to extend the bottom fading region. Called only when
17036     * {@link #isPaddingOffsetRequired()} returns true.
17037     *
17038     * @return The bottom padding offset in pixels.
17039     *
17040     * @see #isPaddingOffsetRequired()
17041     *
17042     * @since CURRENT
17043     */
17044    protected int getBottomPaddingOffset() {
17045        return 0;
17046    }
17047
17048    /**
17049     * @hide
17050     * @param offsetRequired
17051     */
17052    protected int getFadeTop(boolean offsetRequired) {
17053        int top = mPaddingTop;
17054        if (offsetRequired) top += getTopPaddingOffset();
17055        return top;
17056    }
17057
17058    /**
17059     * @hide
17060     * @param offsetRequired
17061     */
17062    protected int getFadeHeight(boolean offsetRequired) {
17063        int padding = mPaddingTop;
17064        if (offsetRequired) padding += getTopPaddingOffset();
17065        return mBottom - mTop - mPaddingBottom - padding;
17066    }
17067
17068    /**
17069     * <p>Indicates whether this view is attached to a hardware accelerated
17070     * window or not.</p>
17071     *
17072     * <p>Even if this method returns true, it does not mean that every call
17073     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
17074     * accelerated {@link android.graphics.Canvas}. For instance, if this view
17075     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
17076     * window is hardware accelerated,
17077     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
17078     * return false, and this method will return true.</p>
17079     *
17080     * @return True if the view is attached to a window and the window is
17081     *         hardware accelerated; false in any other case.
17082     */
17083    @ViewDebug.ExportedProperty(category = "drawing")
17084    public boolean isHardwareAccelerated() {
17085        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
17086    }
17087
17088    /**
17089     * Sets a rectangular area on this view to which the view will be clipped
17090     * when it is drawn. Setting the value to null will remove the clip bounds
17091     * and the view will draw normally, using its full bounds.
17092     *
17093     * @param clipBounds The rectangular area, in the local coordinates of
17094     * this view, to which future drawing operations will be clipped.
17095     */
17096    public void setClipBounds(Rect clipBounds) {
17097        if (clipBounds == mClipBounds
17098                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
17099            return;
17100        }
17101        if (clipBounds != null) {
17102            if (mClipBounds == null) {
17103                mClipBounds = new Rect(clipBounds);
17104            } else {
17105                mClipBounds.set(clipBounds);
17106            }
17107        } else {
17108            mClipBounds = null;
17109        }
17110        mRenderNode.setClipBounds(mClipBounds);
17111        invalidateViewProperty(false, false);
17112    }
17113
17114    /**
17115     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
17116     *
17117     * @return A copy of the current clip bounds if clip bounds are set,
17118     * otherwise null.
17119     */
17120    public Rect getClipBounds() {
17121        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
17122    }
17123
17124
17125    /**
17126     * Populates an output rectangle with the clip bounds of the view,
17127     * returning {@code true} if successful or {@code false} if the view's
17128     * clip bounds are {@code null}.
17129     *
17130     * @param outRect rectangle in which to place the clip bounds of the view
17131     * @return {@code true} if successful or {@code false} if the view's
17132     *         clip bounds are {@code null}
17133     */
17134    public boolean getClipBounds(Rect outRect) {
17135        if (mClipBounds != null) {
17136            outRect.set(mClipBounds);
17137            return true;
17138        }
17139        return false;
17140    }
17141
17142    /**
17143     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
17144     * case of an active Animation being run on the view.
17145     */
17146    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
17147            Animation a, boolean scalingRequired) {
17148        Transformation invalidationTransform;
17149        final int flags = parent.mGroupFlags;
17150        final boolean initialized = a.isInitialized();
17151        if (!initialized) {
17152            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
17153            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
17154            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
17155            onAnimationStart();
17156        }
17157
17158        final Transformation t = parent.getChildTransformation();
17159        boolean more = a.getTransformation(drawingTime, t, 1f);
17160        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
17161            if (parent.mInvalidationTransformation == null) {
17162                parent.mInvalidationTransformation = new Transformation();
17163            }
17164            invalidationTransform = parent.mInvalidationTransformation;
17165            a.getTransformation(drawingTime, invalidationTransform, 1f);
17166        } else {
17167            invalidationTransform = t;
17168        }
17169
17170        if (more) {
17171            if (!a.willChangeBounds()) {
17172                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
17173                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
17174                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
17175                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
17176                    // The child need to draw an animation, potentially offscreen, so
17177                    // make sure we do not cancel invalidate requests
17178                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
17179                    parent.invalidate(mLeft, mTop, mRight, mBottom);
17180                }
17181            } else {
17182                if (parent.mInvalidateRegion == null) {
17183                    parent.mInvalidateRegion = new RectF();
17184                }
17185                final RectF region = parent.mInvalidateRegion;
17186                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
17187                        invalidationTransform);
17188
17189                // The child need to draw an animation, potentially offscreen, so
17190                // make sure we do not cancel invalidate requests
17191                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
17192
17193                final int left = mLeft + (int) region.left;
17194                final int top = mTop + (int) region.top;
17195                parent.invalidate(left, top, left + (int) (region.width() + .5f),
17196                        top + (int) (region.height() + .5f));
17197            }
17198        }
17199        return more;
17200    }
17201
17202    /**
17203     * This method is called by getDisplayList() when a display list is recorded for a View.
17204     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
17205     */
17206    void setDisplayListProperties(RenderNode renderNode) {
17207        if (renderNode != null) {
17208            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
17209            renderNode.setClipToBounds(mParent instanceof ViewGroup
17210                    && ((ViewGroup) mParent).getClipChildren());
17211
17212            float alpha = 1;
17213            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
17214                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
17215                ViewGroup parentVG = (ViewGroup) mParent;
17216                final Transformation t = parentVG.getChildTransformation();
17217                if (parentVG.getChildStaticTransformation(this, t)) {
17218                    final int transformType = t.getTransformationType();
17219                    if (transformType != Transformation.TYPE_IDENTITY) {
17220                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
17221                            alpha = t.getAlpha();
17222                        }
17223                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
17224                            renderNode.setStaticMatrix(t.getMatrix());
17225                        }
17226                    }
17227                }
17228            }
17229            if (mTransformationInfo != null) {
17230                alpha *= getFinalAlpha();
17231                if (alpha < 1) {
17232                    final int multipliedAlpha = (int) (255 * alpha);
17233                    if (onSetAlpha(multipliedAlpha)) {
17234                        alpha = 1;
17235                    }
17236                }
17237                renderNode.setAlpha(alpha);
17238            } else if (alpha < 1) {
17239                renderNode.setAlpha(alpha);
17240            }
17241        }
17242    }
17243
17244    /**
17245     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
17246     *
17247     * This is where the View specializes rendering behavior based on layer type,
17248     * and hardware acceleration.
17249     */
17250    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
17251        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
17252        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
17253         *
17254         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
17255         * HW accelerated, it can't handle drawing RenderNodes.
17256         */
17257        boolean drawingWithRenderNode = mAttachInfo != null
17258                && mAttachInfo.mHardwareAccelerated
17259                && hardwareAcceleratedCanvas;
17260
17261        boolean more = false;
17262        final boolean childHasIdentityMatrix = hasIdentityMatrix();
17263        final int parentFlags = parent.mGroupFlags;
17264
17265        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
17266            parent.getChildTransformation().clear();
17267            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17268        }
17269
17270        Transformation transformToApply = null;
17271        boolean concatMatrix = false;
17272        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
17273        final Animation a = getAnimation();
17274        if (a != null) {
17275            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
17276            concatMatrix = a.willChangeTransformationMatrix();
17277            if (concatMatrix) {
17278                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
17279            }
17280            transformToApply = parent.getChildTransformation();
17281        } else {
17282            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
17283                // No longer animating: clear out old animation matrix
17284                mRenderNode.setAnimationMatrix(null);
17285                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
17286            }
17287            if (!drawingWithRenderNode
17288                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
17289                final Transformation t = parent.getChildTransformation();
17290                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
17291                if (hasTransform) {
17292                    final int transformType = t.getTransformationType();
17293                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
17294                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
17295                }
17296            }
17297        }
17298
17299        concatMatrix |= !childHasIdentityMatrix;
17300
17301        // Sets the flag as early as possible to allow draw() implementations
17302        // to call invalidate() successfully when doing animations
17303        mPrivateFlags |= PFLAG_DRAWN;
17304
17305        if (!concatMatrix &&
17306                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
17307                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
17308                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
17309                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
17310            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
17311            return more;
17312        }
17313        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
17314
17315        if (hardwareAcceleratedCanvas) {
17316            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
17317            // retain the flag's value temporarily in the mRecreateDisplayList flag
17318            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
17319            mPrivateFlags &= ~PFLAG_INVALIDATED;
17320        }
17321
17322        RenderNode renderNode = null;
17323        Bitmap cache = null;
17324        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
17325        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
17326             if (layerType != LAYER_TYPE_NONE) {
17327                 // If not drawing with RenderNode, treat HW layers as SW
17328                 layerType = LAYER_TYPE_SOFTWARE;
17329                 buildDrawingCache(true);
17330            }
17331            cache = getDrawingCache(true);
17332        }
17333
17334        if (drawingWithRenderNode) {
17335            // Delay getting the display list until animation-driven alpha values are
17336            // set up and possibly passed on to the view
17337            renderNode = updateDisplayListIfDirty();
17338            if (!renderNode.isValid()) {
17339                // Uncommon, but possible. If a view is removed from the hierarchy during the call
17340                // to getDisplayList(), the display list will be marked invalid and we should not
17341                // try to use it again.
17342                renderNode = null;
17343                drawingWithRenderNode = false;
17344            }
17345        }
17346
17347        int sx = 0;
17348        int sy = 0;
17349        if (!drawingWithRenderNode) {
17350            computeScroll();
17351            sx = mScrollX;
17352            sy = mScrollY;
17353        }
17354
17355        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
17356        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
17357
17358        int restoreTo = -1;
17359        if (!drawingWithRenderNode || transformToApply != null) {
17360            restoreTo = canvas.save();
17361        }
17362        if (offsetForScroll) {
17363            canvas.translate(mLeft - sx, mTop - sy);
17364        } else {
17365            if (!drawingWithRenderNode) {
17366                canvas.translate(mLeft, mTop);
17367            }
17368            if (scalingRequired) {
17369                if (drawingWithRenderNode) {
17370                    // TODO: Might not need this if we put everything inside the DL
17371                    restoreTo = canvas.save();
17372                }
17373                // mAttachInfo cannot be null, otherwise scalingRequired == false
17374                final float scale = 1.0f / mAttachInfo.mApplicationScale;
17375                canvas.scale(scale, scale);
17376            }
17377        }
17378
17379        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
17380        if (transformToApply != null
17381                || alpha < 1
17382                || !hasIdentityMatrix()
17383                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17384            if (transformToApply != null || !childHasIdentityMatrix) {
17385                int transX = 0;
17386                int transY = 0;
17387
17388                if (offsetForScroll) {
17389                    transX = -sx;
17390                    transY = -sy;
17391                }
17392
17393                if (transformToApply != null) {
17394                    if (concatMatrix) {
17395                        if (drawingWithRenderNode) {
17396                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
17397                        } else {
17398                            // Undo the scroll translation, apply the transformation matrix,
17399                            // then redo the scroll translate to get the correct result.
17400                            canvas.translate(-transX, -transY);
17401                            canvas.concat(transformToApply.getMatrix());
17402                            canvas.translate(transX, transY);
17403                        }
17404                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17405                    }
17406
17407                    float transformAlpha = transformToApply.getAlpha();
17408                    if (transformAlpha < 1) {
17409                        alpha *= transformAlpha;
17410                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17411                    }
17412                }
17413
17414                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
17415                    canvas.translate(-transX, -transY);
17416                    canvas.concat(getMatrix());
17417                    canvas.translate(transX, transY);
17418                }
17419            }
17420
17421            // Deal with alpha if it is or used to be <1
17422            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17423                if (alpha < 1) {
17424                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17425                } else {
17426                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17427                }
17428                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17429                if (!drawingWithDrawingCache) {
17430                    final int multipliedAlpha = (int) (255 * alpha);
17431                    if (!onSetAlpha(multipliedAlpha)) {
17432                        if (drawingWithRenderNode) {
17433                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
17434                        } else if (layerType == LAYER_TYPE_NONE) {
17435                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
17436                                    multipliedAlpha);
17437                        }
17438                    } else {
17439                        // Alpha is handled by the child directly, clobber the layer's alpha
17440                        mPrivateFlags |= PFLAG_ALPHA_SET;
17441                    }
17442                }
17443            }
17444        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17445            onSetAlpha(255);
17446            mPrivateFlags &= ~PFLAG_ALPHA_SET;
17447        }
17448
17449        if (!drawingWithRenderNode) {
17450            // apply clips directly, since RenderNode won't do it for this draw
17451            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
17452                if (offsetForScroll) {
17453                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
17454                } else {
17455                    if (!scalingRequired || cache == null) {
17456                        canvas.clipRect(0, 0, getWidth(), getHeight());
17457                    } else {
17458                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
17459                    }
17460                }
17461            }
17462
17463            if (mClipBounds != null) {
17464                // clip bounds ignore scroll
17465                canvas.clipRect(mClipBounds);
17466            }
17467        }
17468
17469        if (!drawingWithDrawingCache) {
17470            if (drawingWithRenderNode) {
17471                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17472                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17473            } else {
17474                // Fast path for layouts with no backgrounds
17475                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17476                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17477                    dispatchDraw(canvas);
17478                } else {
17479                    draw(canvas);
17480                }
17481            }
17482        } else if (cache != null) {
17483            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17484            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
17485                // no layer paint, use temporary paint to draw bitmap
17486                Paint cachePaint = parent.mCachePaint;
17487                if (cachePaint == null) {
17488                    cachePaint = new Paint();
17489                    cachePaint.setDither(false);
17490                    parent.mCachePaint = cachePaint;
17491                }
17492                cachePaint.setAlpha((int) (alpha * 255));
17493                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
17494            } else {
17495                // use layer paint to draw the bitmap, merging the two alphas, but also restore
17496                int layerPaintAlpha = mLayerPaint.getAlpha();
17497                if (alpha < 1) {
17498                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
17499                }
17500                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
17501                if (alpha < 1) {
17502                    mLayerPaint.setAlpha(layerPaintAlpha);
17503                }
17504            }
17505        }
17506
17507        if (restoreTo >= 0) {
17508            canvas.restoreToCount(restoreTo);
17509        }
17510
17511        if (a != null && !more) {
17512            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
17513                onSetAlpha(255);
17514            }
17515            parent.finishAnimatingView(this, a);
17516        }
17517
17518        if (more && hardwareAcceleratedCanvas) {
17519            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17520                // alpha animations should cause the child to recreate its display list
17521                invalidate(true);
17522            }
17523        }
17524
17525        mRecreateDisplayList = false;
17526
17527        return more;
17528    }
17529
17530    static Paint getDebugPaint() {
17531        if (sDebugPaint == null) {
17532            sDebugPaint = new Paint();
17533            sDebugPaint.setAntiAlias(false);
17534        }
17535        return sDebugPaint;
17536    }
17537
17538    final int dipsToPixels(int dips) {
17539        float scale = getContext().getResources().getDisplayMetrics().density;
17540        return (int) (dips * scale + 0.5f);
17541    }
17542
17543    final private void debugDrawFocus(Canvas canvas) {
17544        if (isFocused()) {
17545            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
17546            final int l = mScrollX;
17547            final int r = l + mRight - mLeft;
17548            final int t = mScrollY;
17549            final int b = t + mBottom - mTop;
17550
17551            final Paint paint = getDebugPaint();
17552            paint.setColor(DEBUG_CORNERS_COLOR);
17553
17554            // Draw squares in corners.
17555            paint.setStyle(Paint.Style.FILL);
17556            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
17557            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
17558            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
17559            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
17560
17561            // Draw big X across the view.
17562            paint.setStyle(Paint.Style.STROKE);
17563            canvas.drawLine(l, t, r, b, paint);
17564            canvas.drawLine(l, b, r, t, paint);
17565        }
17566    }
17567
17568    /**
17569     * Manually render this view (and all of its children) to the given Canvas.
17570     * The view must have already done a full layout before this function is
17571     * called.  When implementing a view, implement
17572     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
17573     * If you do need to override this method, call the superclass version.
17574     *
17575     * @param canvas The Canvas to which the View is rendered.
17576     */
17577    @CallSuper
17578    public void draw(Canvas canvas) {
17579        final int privateFlags = mPrivateFlags;
17580        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
17581                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
17582        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
17583
17584        /*
17585         * Draw traversal performs several drawing steps which must be executed
17586         * in the appropriate order:
17587         *
17588         *      1. Draw the background
17589         *      2. If necessary, save the canvas' layers to prepare for fading
17590         *      3. Draw view's content
17591         *      4. Draw children
17592         *      5. If necessary, draw the fading edges and restore layers
17593         *      6. Draw decorations (scrollbars for instance)
17594         */
17595
17596        // Step 1, draw the background, if needed
17597        int saveCount;
17598
17599        if (!dirtyOpaque) {
17600            drawBackground(canvas);
17601        }
17602
17603        // skip step 2 & 5 if possible (common case)
17604        final int viewFlags = mViewFlags;
17605        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
17606        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
17607        if (!verticalEdges && !horizontalEdges) {
17608            // Step 3, draw the content
17609            if (!dirtyOpaque) onDraw(canvas);
17610
17611            // Step 4, draw the children
17612            dispatchDraw(canvas);
17613
17614            // Overlay is part of the content and draws beneath Foreground
17615            if (mOverlay != null && !mOverlay.isEmpty()) {
17616                mOverlay.getOverlayView().dispatchDraw(canvas);
17617            }
17618
17619            // Step 6, draw decorations (foreground, scrollbars)
17620            onDrawForeground(canvas);
17621
17622            if (debugDraw()) {
17623                debugDrawFocus(canvas);
17624            }
17625
17626            // we're done...
17627            return;
17628        }
17629
17630        /*
17631         * Here we do the full fledged routine...
17632         * (this is an uncommon case where speed matters less,
17633         * this is why we repeat some of the tests that have been
17634         * done above)
17635         */
17636
17637        boolean drawTop = false;
17638        boolean drawBottom = false;
17639        boolean drawLeft = false;
17640        boolean drawRight = false;
17641
17642        float topFadeStrength = 0.0f;
17643        float bottomFadeStrength = 0.0f;
17644        float leftFadeStrength = 0.0f;
17645        float rightFadeStrength = 0.0f;
17646
17647        // Step 2, save the canvas' layers
17648        int paddingLeft = mPaddingLeft;
17649
17650        final boolean offsetRequired = isPaddingOffsetRequired();
17651        if (offsetRequired) {
17652            paddingLeft += getLeftPaddingOffset();
17653        }
17654
17655        int left = mScrollX + paddingLeft;
17656        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
17657        int top = mScrollY + getFadeTop(offsetRequired);
17658        int bottom = top + getFadeHeight(offsetRequired);
17659
17660        if (offsetRequired) {
17661            right += getRightPaddingOffset();
17662            bottom += getBottomPaddingOffset();
17663        }
17664
17665        final ScrollabilityCache scrollabilityCache = mScrollCache;
17666        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
17667        int length = (int) fadeHeight;
17668
17669        // clip the fade length if top and bottom fades overlap
17670        // overlapping fades produce odd-looking artifacts
17671        if (verticalEdges && (top + length > bottom - length)) {
17672            length = (bottom - top) / 2;
17673        }
17674
17675        // also clip horizontal fades if necessary
17676        if (horizontalEdges && (left + length > right - length)) {
17677            length = (right - left) / 2;
17678        }
17679
17680        if (verticalEdges) {
17681            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
17682            drawTop = topFadeStrength * fadeHeight > 1.0f;
17683            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
17684            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
17685        }
17686
17687        if (horizontalEdges) {
17688            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
17689            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
17690            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
17691            drawRight = rightFadeStrength * fadeHeight > 1.0f;
17692        }
17693
17694        saveCount = canvas.getSaveCount();
17695
17696        int solidColor = getSolidColor();
17697        if (solidColor == 0) {
17698            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
17699
17700            if (drawTop) {
17701                canvas.saveLayer(left, top, right, top + length, null, flags);
17702            }
17703
17704            if (drawBottom) {
17705                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
17706            }
17707
17708            if (drawLeft) {
17709                canvas.saveLayer(left, top, left + length, bottom, null, flags);
17710            }
17711
17712            if (drawRight) {
17713                canvas.saveLayer(right - length, top, right, bottom, null, flags);
17714            }
17715        } else {
17716            scrollabilityCache.setFadeColor(solidColor);
17717        }
17718
17719        // Step 3, draw the content
17720        if (!dirtyOpaque) onDraw(canvas);
17721
17722        // Step 4, draw the children
17723        dispatchDraw(canvas);
17724
17725        // Step 5, draw the fade effect and restore layers
17726        final Paint p = scrollabilityCache.paint;
17727        final Matrix matrix = scrollabilityCache.matrix;
17728        final Shader fade = scrollabilityCache.shader;
17729
17730        if (drawTop) {
17731            matrix.setScale(1, fadeHeight * topFadeStrength);
17732            matrix.postTranslate(left, top);
17733            fade.setLocalMatrix(matrix);
17734            p.setShader(fade);
17735            canvas.drawRect(left, top, right, top + length, p);
17736        }
17737
17738        if (drawBottom) {
17739            matrix.setScale(1, fadeHeight * bottomFadeStrength);
17740            matrix.postRotate(180);
17741            matrix.postTranslate(left, bottom);
17742            fade.setLocalMatrix(matrix);
17743            p.setShader(fade);
17744            canvas.drawRect(left, bottom - length, right, bottom, p);
17745        }
17746
17747        if (drawLeft) {
17748            matrix.setScale(1, fadeHeight * leftFadeStrength);
17749            matrix.postRotate(-90);
17750            matrix.postTranslate(left, top);
17751            fade.setLocalMatrix(matrix);
17752            p.setShader(fade);
17753            canvas.drawRect(left, top, left + length, bottom, p);
17754        }
17755
17756        if (drawRight) {
17757            matrix.setScale(1, fadeHeight * rightFadeStrength);
17758            matrix.postRotate(90);
17759            matrix.postTranslate(right, top);
17760            fade.setLocalMatrix(matrix);
17761            p.setShader(fade);
17762            canvas.drawRect(right - length, top, right, bottom, p);
17763        }
17764
17765        canvas.restoreToCount(saveCount);
17766
17767        // Overlay is part of the content and draws beneath Foreground
17768        if (mOverlay != null && !mOverlay.isEmpty()) {
17769            mOverlay.getOverlayView().dispatchDraw(canvas);
17770        }
17771
17772        // Step 6, draw decorations (foreground, scrollbars)
17773        onDrawForeground(canvas);
17774
17775        if (debugDraw()) {
17776            debugDrawFocus(canvas);
17777        }
17778    }
17779
17780    /**
17781     * Draws the background onto the specified canvas.
17782     *
17783     * @param canvas Canvas on which to draw the background
17784     */
17785    private void drawBackground(Canvas canvas) {
17786        final Drawable background = mBackground;
17787        if (background == null) {
17788            return;
17789        }
17790
17791        setBackgroundBounds();
17792
17793        // Attempt to use a display list if requested.
17794        if (canvas.isHardwareAccelerated() && mAttachInfo != null
17795                && mAttachInfo.mThreadedRenderer != null) {
17796            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
17797
17798            final RenderNode renderNode = mBackgroundRenderNode;
17799            if (renderNode != null && renderNode.isValid()) {
17800                setBackgroundRenderNodeProperties(renderNode);
17801                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17802                return;
17803            }
17804        }
17805
17806        final int scrollX = mScrollX;
17807        final int scrollY = mScrollY;
17808        if ((scrollX | scrollY) == 0) {
17809            background.draw(canvas);
17810        } else {
17811            canvas.translate(scrollX, scrollY);
17812            background.draw(canvas);
17813            canvas.translate(-scrollX, -scrollY);
17814        }
17815    }
17816
17817    /**
17818     * Sets the correct background bounds and rebuilds the outline, if needed.
17819     * <p/>
17820     * This is called by LayoutLib.
17821     */
17822    void setBackgroundBounds() {
17823        if (mBackgroundSizeChanged && mBackground != null) {
17824            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
17825            mBackgroundSizeChanged = false;
17826            rebuildOutline();
17827        }
17828    }
17829
17830    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
17831        renderNode.setTranslationX(mScrollX);
17832        renderNode.setTranslationY(mScrollY);
17833    }
17834
17835    /**
17836     * Creates a new display list or updates the existing display list for the
17837     * specified Drawable.
17838     *
17839     * @param drawable Drawable for which to create a display list
17840     * @param renderNode Existing RenderNode, or {@code null}
17841     * @return A valid display list for the specified drawable
17842     */
17843    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
17844        if (renderNode == null) {
17845            renderNode = RenderNode.create(drawable.getClass().getName(), this);
17846        }
17847
17848        final Rect bounds = drawable.getBounds();
17849        final int width = bounds.width();
17850        final int height = bounds.height();
17851        final DisplayListCanvas canvas = renderNode.start(width, height);
17852
17853        // Reverse left/top translation done by drawable canvas, which will
17854        // instead be applied by rendernode's LTRB bounds below. This way, the
17855        // drawable's bounds match with its rendernode bounds and its content
17856        // will lie within those bounds in the rendernode tree.
17857        canvas.translate(-bounds.left, -bounds.top);
17858
17859        try {
17860            drawable.draw(canvas);
17861        } finally {
17862            renderNode.end(canvas);
17863        }
17864
17865        // Set up drawable properties that are view-independent.
17866        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
17867        renderNode.setProjectBackwards(drawable.isProjected());
17868        renderNode.setProjectionReceiver(true);
17869        renderNode.setClipToBounds(false);
17870        return renderNode;
17871    }
17872
17873    /**
17874     * Returns the overlay for this view, creating it if it does not yet exist.
17875     * Adding drawables to the overlay will cause them to be displayed whenever
17876     * the view itself is redrawn. Objects in the overlay should be actively
17877     * managed: remove them when they should not be displayed anymore. The
17878     * overlay will always have the same size as its host view.
17879     *
17880     * <p>Note: Overlays do not currently work correctly with {@link
17881     * SurfaceView} or {@link TextureView}; contents in overlays for these
17882     * types of views may not display correctly.</p>
17883     *
17884     * @return The ViewOverlay object for this view.
17885     * @see ViewOverlay
17886     */
17887    public ViewOverlay getOverlay() {
17888        if (mOverlay == null) {
17889            mOverlay = new ViewOverlay(mContext, this);
17890        }
17891        return mOverlay;
17892    }
17893
17894    /**
17895     * Override this if your view is known to always be drawn on top of a solid color background,
17896     * and needs to draw fading edges. Returning a non-zero color enables the view system to
17897     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
17898     * should be set to 0xFF.
17899     *
17900     * @see #setVerticalFadingEdgeEnabled(boolean)
17901     * @see #setHorizontalFadingEdgeEnabled(boolean)
17902     *
17903     * @return The known solid color background for this view, or 0 if the color may vary
17904     */
17905    @ViewDebug.ExportedProperty(category = "drawing")
17906    @ColorInt
17907    public int getSolidColor() {
17908        return 0;
17909    }
17910
17911    /**
17912     * Build a human readable string representation of the specified view flags.
17913     *
17914     * @param flags the view flags to convert to a string
17915     * @return a String representing the supplied flags
17916     */
17917    private static String printFlags(int flags) {
17918        String output = "";
17919        int numFlags = 0;
17920        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
17921            output += "TAKES_FOCUS";
17922            numFlags++;
17923        }
17924
17925        switch (flags & VISIBILITY_MASK) {
17926        case INVISIBLE:
17927            if (numFlags > 0) {
17928                output += " ";
17929            }
17930            output += "INVISIBLE";
17931            // USELESS HERE numFlags++;
17932            break;
17933        case GONE:
17934            if (numFlags > 0) {
17935                output += " ";
17936            }
17937            output += "GONE";
17938            // USELESS HERE numFlags++;
17939            break;
17940        default:
17941            break;
17942        }
17943        return output;
17944    }
17945
17946    /**
17947     * Build a human readable string representation of the specified private
17948     * view flags.
17949     *
17950     * @param privateFlags the private view flags to convert to a string
17951     * @return a String representing the supplied flags
17952     */
17953    private static String printPrivateFlags(int privateFlags) {
17954        String output = "";
17955        int numFlags = 0;
17956
17957        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
17958            output += "WANTS_FOCUS";
17959            numFlags++;
17960        }
17961
17962        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
17963            if (numFlags > 0) {
17964                output += " ";
17965            }
17966            output += "FOCUSED";
17967            numFlags++;
17968        }
17969
17970        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
17971            if (numFlags > 0) {
17972                output += " ";
17973            }
17974            output += "SELECTED";
17975            numFlags++;
17976        }
17977
17978        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
17979            if (numFlags > 0) {
17980                output += " ";
17981            }
17982            output += "IS_ROOT_NAMESPACE";
17983            numFlags++;
17984        }
17985
17986        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
17987            if (numFlags > 0) {
17988                output += " ";
17989            }
17990            output += "HAS_BOUNDS";
17991            numFlags++;
17992        }
17993
17994        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
17995            if (numFlags > 0) {
17996                output += " ";
17997            }
17998            output += "DRAWN";
17999            // USELESS HERE numFlags++;
18000        }
18001        return output;
18002    }
18003
18004    /**
18005     * <p>Indicates whether or not this view's layout will be requested during
18006     * the next hierarchy layout pass.</p>
18007     *
18008     * @return true if the layout will be forced during next layout pass
18009     */
18010    public boolean isLayoutRequested() {
18011        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
18012    }
18013
18014    /**
18015     * Return true if o is a ViewGroup that is laying out using optical bounds.
18016     * @hide
18017     */
18018    public static boolean isLayoutModeOptical(Object o) {
18019        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
18020    }
18021
18022    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
18023        Insets parentInsets = mParent instanceof View ?
18024                ((View) mParent).getOpticalInsets() : Insets.NONE;
18025        Insets childInsets = getOpticalInsets();
18026        return setFrame(
18027                left   + parentInsets.left - childInsets.left,
18028                top    + parentInsets.top  - childInsets.top,
18029                right  + parentInsets.left + childInsets.right,
18030                bottom + parentInsets.top  + childInsets.bottom);
18031    }
18032
18033    /**
18034     * Assign a size and position to a view and all of its
18035     * descendants
18036     *
18037     * <p>This is the second phase of the layout mechanism.
18038     * (The first is measuring). In this phase, each parent calls
18039     * layout on all of its children to position them.
18040     * This is typically done using the child measurements
18041     * that were stored in the measure pass().</p>
18042     *
18043     * <p>Derived classes should not override this method.
18044     * Derived classes with children should override
18045     * onLayout. In that method, they should
18046     * call layout on each of their children.</p>
18047     *
18048     * @param l Left position, relative to parent
18049     * @param t Top position, relative to parent
18050     * @param r Right position, relative to parent
18051     * @param b Bottom position, relative to parent
18052     */
18053    @SuppressWarnings({"unchecked"})
18054    public void layout(int l, int t, int r, int b) {
18055        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
18056            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
18057            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18058        }
18059
18060        int oldL = mLeft;
18061        int oldT = mTop;
18062        int oldB = mBottom;
18063        int oldR = mRight;
18064
18065        boolean changed = isLayoutModeOptical(mParent) ?
18066                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
18067
18068        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
18069            onLayout(changed, l, t, r, b);
18070
18071            if (shouldDrawRoundScrollbar()) {
18072                if(mRoundScrollbarRenderer == null) {
18073                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
18074                }
18075            } else {
18076                mRoundScrollbarRenderer = null;
18077            }
18078
18079            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
18080
18081            ListenerInfo li = mListenerInfo;
18082            if (li != null && li.mOnLayoutChangeListeners != null) {
18083                ArrayList<OnLayoutChangeListener> listenersCopy =
18084                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
18085                int numListeners = listenersCopy.size();
18086                for (int i = 0; i < numListeners; ++i) {
18087                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
18088                }
18089            }
18090        }
18091
18092        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
18093        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
18094    }
18095
18096    /**
18097     * Called from layout when this view should
18098     * assign a size and position to each of its children.
18099     *
18100     * Derived classes with children should override
18101     * this method and call layout on each of
18102     * their children.
18103     * @param changed This is a new size or position for this view
18104     * @param left Left position, relative to parent
18105     * @param top Top position, relative to parent
18106     * @param right Right position, relative to parent
18107     * @param bottom Bottom position, relative to parent
18108     */
18109    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
18110    }
18111
18112    /**
18113     * Assign a size and position to this view.
18114     *
18115     * This is called from layout.
18116     *
18117     * @param left Left position, relative to parent
18118     * @param top Top position, relative to parent
18119     * @param right Right position, relative to parent
18120     * @param bottom Bottom position, relative to parent
18121     * @return true if the new size and position are different than the
18122     *         previous ones
18123     * {@hide}
18124     */
18125    protected boolean setFrame(int left, int top, int right, int bottom) {
18126        boolean changed = false;
18127
18128        if (DBG) {
18129            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
18130                    + right + "," + bottom + ")");
18131        }
18132
18133        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
18134            changed = true;
18135
18136            // Remember our drawn bit
18137            int drawn = mPrivateFlags & PFLAG_DRAWN;
18138
18139            int oldWidth = mRight - mLeft;
18140            int oldHeight = mBottom - mTop;
18141            int newWidth = right - left;
18142            int newHeight = bottom - top;
18143            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
18144
18145            // Invalidate our old position
18146            invalidate(sizeChanged);
18147
18148            mLeft = left;
18149            mTop = top;
18150            mRight = right;
18151            mBottom = bottom;
18152            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
18153
18154            mPrivateFlags |= PFLAG_HAS_BOUNDS;
18155
18156
18157            if (sizeChanged) {
18158                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
18159            }
18160
18161            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
18162                // If we are visible, force the DRAWN bit to on so that
18163                // this invalidate will go through (at least to our parent).
18164                // This is because someone may have invalidated this view
18165                // before this call to setFrame came in, thereby clearing
18166                // the DRAWN bit.
18167                mPrivateFlags |= PFLAG_DRAWN;
18168                invalidate(sizeChanged);
18169                // parent display list may need to be recreated based on a change in the bounds
18170                // of any child
18171                invalidateParentCaches();
18172            }
18173
18174            // Reset drawn bit to original value (invalidate turns it off)
18175            mPrivateFlags |= drawn;
18176
18177            mBackgroundSizeChanged = true;
18178            if (mForegroundInfo != null) {
18179                mForegroundInfo.mBoundsChanged = true;
18180            }
18181
18182            notifySubtreeAccessibilityStateChangedIfNeeded();
18183        }
18184        return changed;
18185    }
18186
18187    /**
18188     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
18189     * @hide
18190     */
18191    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
18192        setFrame(left, top, right, bottom);
18193    }
18194
18195    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
18196        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
18197        if (mOverlay != null) {
18198            mOverlay.getOverlayView().setRight(newWidth);
18199            mOverlay.getOverlayView().setBottom(newHeight);
18200        }
18201        rebuildOutline();
18202    }
18203
18204    /**
18205     * Finalize inflating a view from XML.  This is called as the last phase
18206     * of inflation, after all child views have been added.
18207     *
18208     * <p>Even if the subclass overrides onFinishInflate, they should always be
18209     * sure to call the super method, so that we get called.
18210     */
18211    @CallSuper
18212    protected void onFinishInflate() {
18213    }
18214
18215    /**
18216     * Returns the resources associated with this view.
18217     *
18218     * @return Resources object.
18219     */
18220    public Resources getResources() {
18221        return mResources;
18222    }
18223
18224    /**
18225     * Invalidates the specified Drawable.
18226     *
18227     * @param drawable the drawable to invalidate
18228     */
18229    @Override
18230    public void invalidateDrawable(@NonNull Drawable drawable) {
18231        if (verifyDrawable(drawable)) {
18232            final Rect dirty = drawable.getDirtyBounds();
18233            final int scrollX = mScrollX;
18234            final int scrollY = mScrollY;
18235
18236            invalidate(dirty.left + scrollX, dirty.top + scrollY,
18237                    dirty.right + scrollX, dirty.bottom + scrollY);
18238            rebuildOutline();
18239        }
18240    }
18241
18242    /**
18243     * Schedules an action on a drawable to occur at a specified time.
18244     *
18245     * @param who the recipient of the action
18246     * @param what the action to run on the drawable
18247     * @param when the time at which the action must occur. Uses the
18248     *        {@link SystemClock#uptimeMillis} timebase.
18249     */
18250    @Override
18251    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
18252        if (verifyDrawable(who) && what != null) {
18253            final long delay = when - SystemClock.uptimeMillis();
18254            if (mAttachInfo != null) {
18255                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
18256                        Choreographer.CALLBACK_ANIMATION, what, who,
18257                        Choreographer.subtractFrameDelay(delay));
18258            } else {
18259                // Postpone the runnable until we know
18260                // on which thread it needs to run.
18261                getRunQueue().postDelayed(what, delay);
18262            }
18263        }
18264    }
18265
18266    /**
18267     * Cancels a scheduled action on a drawable.
18268     *
18269     * @param who the recipient of the action
18270     * @param what the action to cancel
18271     */
18272    @Override
18273    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
18274        if (verifyDrawable(who) && what != null) {
18275            if (mAttachInfo != null) {
18276                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
18277                        Choreographer.CALLBACK_ANIMATION, what, who);
18278            }
18279            getRunQueue().removeCallbacks(what);
18280        }
18281    }
18282
18283    /**
18284     * Unschedule any events associated with the given Drawable.  This can be
18285     * used when selecting a new Drawable into a view, so that the previous
18286     * one is completely unscheduled.
18287     *
18288     * @param who The Drawable to unschedule.
18289     *
18290     * @see #drawableStateChanged
18291     */
18292    public void unscheduleDrawable(Drawable who) {
18293        if (mAttachInfo != null && who != null) {
18294            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
18295                    Choreographer.CALLBACK_ANIMATION, null, who);
18296        }
18297    }
18298
18299    /**
18300     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
18301     * that the View directionality can and will be resolved before its Drawables.
18302     *
18303     * Will call {@link View#onResolveDrawables} when resolution is done.
18304     *
18305     * @hide
18306     */
18307    protected void resolveDrawables() {
18308        // Drawables resolution may need to happen before resolving the layout direction (which is
18309        // done only during the measure() call).
18310        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
18311        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
18312        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
18313        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
18314        // direction to be resolved as its resolved value will be the same as its raw value.
18315        if (!isLayoutDirectionResolved() &&
18316                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
18317            return;
18318        }
18319
18320        final int layoutDirection = isLayoutDirectionResolved() ?
18321                getLayoutDirection() : getRawLayoutDirection();
18322
18323        if (mBackground != null) {
18324            mBackground.setLayoutDirection(layoutDirection);
18325        }
18326        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18327            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
18328        }
18329        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
18330        onResolveDrawables(layoutDirection);
18331    }
18332
18333    boolean areDrawablesResolved() {
18334        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
18335    }
18336
18337    /**
18338     * Called when layout direction has been resolved.
18339     *
18340     * The default implementation does nothing.
18341     *
18342     * @param layoutDirection The resolved layout direction.
18343     *
18344     * @see #LAYOUT_DIRECTION_LTR
18345     * @see #LAYOUT_DIRECTION_RTL
18346     *
18347     * @hide
18348     */
18349    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
18350    }
18351
18352    /**
18353     * @hide
18354     */
18355    protected void resetResolvedDrawables() {
18356        resetResolvedDrawablesInternal();
18357    }
18358
18359    void resetResolvedDrawablesInternal() {
18360        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
18361    }
18362
18363    /**
18364     * If your view subclass is displaying its own Drawable objects, it should
18365     * override this function and return true for any Drawable it is
18366     * displaying.  This allows animations for those drawables to be
18367     * scheduled.
18368     *
18369     * <p>Be sure to call through to the super class when overriding this
18370     * function.
18371     *
18372     * @param who The Drawable to verify.  Return true if it is one you are
18373     *            displaying, else return the result of calling through to the
18374     *            super class.
18375     *
18376     * @return boolean If true than the Drawable is being displayed in the
18377     *         view; else false and it is not allowed to animate.
18378     *
18379     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
18380     * @see #drawableStateChanged()
18381     */
18382    @CallSuper
18383    protected boolean verifyDrawable(@NonNull Drawable who) {
18384        // Avoid verifying the scroll bar drawable so that we don't end up in
18385        // an invalidation loop. This effectively prevents the scroll bar
18386        // drawable from triggering invalidations and scheduling runnables.
18387        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
18388    }
18389
18390    /**
18391     * This function is called whenever the state of the view changes in such
18392     * a way that it impacts the state of drawables being shown.
18393     * <p>
18394     * If the View has a StateListAnimator, it will also be called to run necessary state
18395     * change animations.
18396     * <p>
18397     * Be sure to call through to the superclass when overriding this function.
18398     *
18399     * @see Drawable#setState(int[])
18400     */
18401    @CallSuper
18402    protected void drawableStateChanged() {
18403        final int[] state = getDrawableState();
18404        boolean changed = false;
18405
18406        final Drawable bg = mBackground;
18407        if (bg != null && bg.isStateful()) {
18408            changed |= bg.setState(state);
18409        }
18410
18411        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18412        if (fg != null && fg.isStateful()) {
18413            changed |= fg.setState(state);
18414        }
18415
18416        if (mScrollCache != null) {
18417            final Drawable scrollBar = mScrollCache.scrollBar;
18418            if (scrollBar != null && scrollBar.isStateful()) {
18419                changed |= scrollBar.setState(state)
18420                        && mScrollCache.state != ScrollabilityCache.OFF;
18421            }
18422        }
18423
18424        if (mStateListAnimator != null) {
18425            mStateListAnimator.setState(state);
18426        }
18427
18428        if (changed) {
18429            invalidate();
18430        }
18431    }
18432
18433    /**
18434     * This function is called whenever the view hotspot changes and needs to
18435     * be propagated to drawables or child views managed by the view.
18436     * <p>
18437     * Dispatching to child views is handled by
18438     * {@link #dispatchDrawableHotspotChanged(float, float)}.
18439     * <p>
18440     * Be sure to call through to the superclass when overriding this function.
18441     *
18442     * @param x hotspot x coordinate
18443     * @param y hotspot y coordinate
18444     */
18445    @CallSuper
18446    public void drawableHotspotChanged(float x, float y) {
18447        if (mBackground != null) {
18448            mBackground.setHotspot(x, y);
18449        }
18450        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18451            mForegroundInfo.mDrawable.setHotspot(x, y);
18452        }
18453
18454        dispatchDrawableHotspotChanged(x, y);
18455    }
18456
18457    /**
18458     * Dispatches drawableHotspotChanged to all of this View's children.
18459     *
18460     * @param x hotspot x coordinate
18461     * @param y hotspot y coordinate
18462     * @see #drawableHotspotChanged(float, float)
18463     */
18464    public void dispatchDrawableHotspotChanged(float x, float y) {
18465    }
18466
18467    /**
18468     * Call this to force a view to update its drawable state. This will cause
18469     * drawableStateChanged to be called on this view. Views that are interested
18470     * in the new state should call getDrawableState.
18471     *
18472     * @see #drawableStateChanged
18473     * @see #getDrawableState
18474     */
18475    public void refreshDrawableState() {
18476        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
18477        drawableStateChanged();
18478
18479        ViewParent parent = mParent;
18480        if (parent != null) {
18481            parent.childDrawableStateChanged(this);
18482        }
18483    }
18484
18485    /**
18486     * Return an array of resource IDs of the drawable states representing the
18487     * current state of the view.
18488     *
18489     * @return The current drawable state
18490     *
18491     * @see Drawable#setState(int[])
18492     * @see #drawableStateChanged()
18493     * @see #onCreateDrawableState(int)
18494     */
18495    public final int[] getDrawableState() {
18496        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
18497            return mDrawableState;
18498        } else {
18499            mDrawableState = onCreateDrawableState(0);
18500            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
18501            return mDrawableState;
18502        }
18503    }
18504
18505    /**
18506     * Generate the new {@link android.graphics.drawable.Drawable} state for
18507     * this view. This is called by the view
18508     * system when the cached Drawable state is determined to be invalid.  To
18509     * retrieve the current state, you should use {@link #getDrawableState}.
18510     *
18511     * @param extraSpace if non-zero, this is the number of extra entries you
18512     * would like in the returned array in which you can place your own
18513     * states.
18514     *
18515     * @return Returns an array holding the current {@link Drawable} state of
18516     * the view.
18517     *
18518     * @see #mergeDrawableStates(int[], int[])
18519     */
18520    protected int[] onCreateDrawableState(int extraSpace) {
18521        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
18522                mParent instanceof View) {
18523            return ((View) mParent).onCreateDrawableState(extraSpace);
18524        }
18525
18526        int[] drawableState;
18527
18528        int privateFlags = mPrivateFlags;
18529
18530        int viewStateIndex = 0;
18531        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
18532        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
18533        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
18534        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
18535        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
18536        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
18537        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
18538                ThreadedRenderer.isAvailable()) {
18539            // This is set if HW acceleration is requested, even if the current
18540            // process doesn't allow it.  This is just to allow app preview
18541            // windows to better match their app.
18542            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
18543        }
18544        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
18545
18546        final int privateFlags2 = mPrivateFlags2;
18547        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
18548            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
18549        }
18550        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
18551            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
18552        }
18553
18554        drawableState = StateSet.get(viewStateIndex);
18555
18556        //noinspection ConstantIfStatement
18557        if (false) {
18558            Log.i("View", "drawableStateIndex=" + viewStateIndex);
18559            Log.i("View", toString()
18560                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
18561                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
18562                    + " fo=" + hasFocus()
18563                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
18564                    + " wf=" + hasWindowFocus()
18565                    + ": " + Arrays.toString(drawableState));
18566        }
18567
18568        if (extraSpace == 0) {
18569            return drawableState;
18570        }
18571
18572        final int[] fullState;
18573        if (drawableState != null) {
18574            fullState = new int[drawableState.length + extraSpace];
18575            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
18576        } else {
18577            fullState = new int[extraSpace];
18578        }
18579
18580        return fullState;
18581    }
18582
18583    /**
18584     * Merge your own state values in <var>additionalState</var> into the base
18585     * state values <var>baseState</var> that were returned by
18586     * {@link #onCreateDrawableState(int)}.
18587     *
18588     * @param baseState The base state values returned by
18589     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
18590     * own additional state values.
18591     *
18592     * @param additionalState The additional state values you would like
18593     * added to <var>baseState</var>; this array is not modified.
18594     *
18595     * @return As a convenience, the <var>baseState</var> array you originally
18596     * passed into the function is returned.
18597     *
18598     * @see #onCreateDrawableState(int)
18599     */
18600    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
18601        final int N = baseState.length;
18602        int i = N - 1;
18603        while (i >= 0 && baseState[i] == 0) {
18604            i--;
18605        }
18606        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
18607        return baseState;
18608    }
18609
18610    /**
18611     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
18612     * on all Drawable objects associated with this view.
18613     * <p>
18614     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
18615     * attached to this view.
18616     */
18617    @CallSuper
18618    public void jumpDrawablesToCurrentState() {
18619        if (mBackground != null) {
18620            mBackground.jumpToCurrentState();
18621        }
18622        if (mStateListAnimator != null) {
18623            mStateListAnimator.jumpToCurrentState();
18624        }
18625        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18626            mForegroundInfo.mDrawable.jumpToCurrentState();
18627        }
18628    }
18629
18630    /**
18631     * Sets the background color for this view.
18632     * @param color the color of the background
18633     */
18634    @RemotableViewMethod
18635    public void setBackgroundColor(@ColorInt int color) {
18636        if (mBackground instanceof ColorDrawable) {
18637            ((ColorDrawable) mBackground.mutate()).setColor(color);
18638            computeOpaqueFlags();
18639            mBackgroundResource = 0;
18640        } else {
18641            setBackground(new ColorDrawable(color));
18642        }
18643    }
18644
18645    /**
18646     * Set the background to a given resource. The resource should refer to
18647     * a Drawable object or 0 to remove the background.
18648     * @param resid The identifier of the resource.
18649     *
18650     * @attr ref android.R.styleable#View_background
18651     */
18652    @RemotableViewMethod
18653    public void setBackgroundResource(@DrawableRes int resid) {
18654        if (resid != 0 && resid == mBackgroundResource) {
18655            return;
18656        }
18657
18658        Drawable d = null;
18659        if (resid != 0) {
18660            d = mContext.getDrawable(resid);
18661        }
18662        setBackground(d);
18663
18664        mBackgroundResource = resid;
18665    }
18666
18667    /**
18668     * Set the background to a given Drawable, or remove the background. If the
18669     * background has padding, this View's padding is set to the background's
18670     * padding. However, when a background is removed, this View's padding isn't
18671     * touched. If setting the padding is desired, please use
18672     * {@link #setPadding(int, int, int, int)}.
18673     *
18674     * @param background The Drawable to use as the background, or null to remove the
18675     *        background
18676     */
18677    public void setBackground(Drawable background) {
18678        //noinspection deprecation
18679        setBackgroundDrawable(background);
18680    }
18681
18682    /**
18683     * @deprecated use {@link #setBackground(Drawable)} instead
18684     */
18685    @Deprecated
18686    public void setBackgroundDrawable(Drawable background) {
18687        computeOpaqueFlags();
18688
18689        if (background == mBackground) {
18690            return;
18691        }
18692
18693        boolean requestLayout = false;
18694
18695        mBackgroundResource = 0;
18696
18697        /*
18698         * Regardless of whether we're setting a new background or not, we want
18699         * to clear the previous drawable. setVisible first while we still have the callback set.
18700         */
18701        if (mBackground != null) {
18702            if (isAttachedToWindow()) {
18703                mBackground.setVisible(false, false);
18704            }
18705            mBackground.setCallback(null);
18706            unscheduleDrawable(mBackground);
18707        }
18708
18709        if (background != null) {
18710            Rect padding = sThreadLocal.get();
18711            if (padding == null) {
18712                padding = new Rect();
18713                sThreadLocal.set(padding);
18714            }
18715            resetResolvedDrawablesInternal();
18716            background.setLayoutDirection(getLayoutDirection());
18717            if (background.getPadding(padding)) {
18718                resetResolvedPaddingInternal();
18719                switch (background.getLayoutDirection()) {
18720                    case LAYOUT_DIRECTION_RTL:
18721                        mUserPaddingLeftInitial = padding.right;
18722                        mUserPaddingRightInitial = padding.left;
18723                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
18724                        break;
18725                    case LAYOUT_DIRECTION_LTR:
18726                    default:
18727                        mUserPaddingLeftInitial = padding.left;
18728                        mUserPaddingRightInitial = padding.right;
18729                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
18730                }
18731                mLeftPaddingDefined = false;
18732                mRightPaddingDefined = false;
18733            }
18734
18735            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
18736            // if it has a different minimum size, we should layout again
18737            if (mBackground == null
18738                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
18739                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
18740                requestLayout = true;
18741            }
18742
18743            // Set mBackground before we set this as the callback and start making other
18744            // background drawable state change calls. In particular, the setVisible call below
18745            // can result in drawables attempting to start animations or otherwise invalidate,
18746            // which requires the view set as the callback (us) to recognize the drawable as
18747            // belonging to it as per verifyDrawable.
18748            mBackground = background;
18749            if (background.isStateful()) {
18750                background.setState(getDrawableState());
18751            }
18752            if (isAttachedToWindow()) {
18753                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18754            }
18755
18756            applyBackgroundTint();
18757
18758            // Set callback last, since the view may still be initializing.
18759            background.setCallback(this);
18760
18761            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18762                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18763                requestLayout = true;
18764            }
18765        } else {
18766            /* Remove the background */
18767            mBackground = null;
18768            if ((mViewFlags & WILL_NOT_DRAW) != 0
18769                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
18770                mPrivateFlags |= PFLAG_SKIP_DRAW;
18771            }
18772
18773            /*
18774             * When the background is set, we try to apply its padding to this
18775             * View. When the background is removed, we don't touch this View's
18776             * padding. This is noted in the Javadocs. Hence, we don't need to
18777             * requestLayout(), the invalidate() below is sufficient.
18778             */
18779
18780            // The old background's minimum size could have affected this
18781            // View's layout, so let's requestLayout
18782            requestLayout = true;
18783        }
18784
18785        computeOpaqueFlags();
18786
18787        if (requestLayout) {
18788            requestLayout();
18789        }
18790
18791        mBackgroundSizeChanged = true;
18792        invalidate(true);
18793        invalidateOutline();
18794    }
18795
18796    /**
18797     * Gets the background drawable
18798     *
18799     * @return The drawable used as the background for this view, if any.
18800     *
18801     * @see #setBackground(Drawable)
18802     *
18803     * @attr ref android.R.styleable#View_background
18804     */
18805    public Drawable getBackground() {
18806        return mBackground;
18807    }
18808
18809    /**
18810     * Applies a tint to the background drawable. Does not modify the current tint
18811     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
18812     * <p>
18813     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
18814     * mutate the drawable and apply the specified tint and tint mode using
18815     * {@link Drawable#setTintList(ColorStateList)}.
18816     *
18817     * @param tint the tint to apply, may be {@code null} to clear tint
18818     *
18819     * @attr ref android.R.styleable#View_backgroundTint
18820     * @see #getBackgroundTintList()
18821     * @see Drawable#setTintList(ColorStateList)
18822     */
18823    public void setBackgroundTintList(@Nullable ColorStateList tint) {
18824        if (mBackgroundTint == null) {
18825            mBackgroundTint = new TintInfo();
18826        }
18827        mBackgroundTint.mTintList = tint;
18828        mBackgroundTint.mHasTintList = true;
18829
18830        applyBackgroundTint();
18831    }
18832
18833    /**
18834     * Return the tint applied to the background drawable, if specified.
18835     *
18836     * @return the tint applied to the background drawable
18837     * @attr ref android.R.styleable#View_backgroundTint
18838     * @see #setBackgroundTintList(ColorStateList)
18839     */
18840    @Nullable
18841    public ColorStateList getBackgroundTintList() {
18842        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
18843    }
18844
18845    /**
18846     * Specifies the blending mode used to apply the tint specified by
18847     * {@link #setBackgroundTintList(ColorStateList)}} to the background
18848     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
18849     *
18850     * @param tintMode the blending mode used to apply the tint, may be
18851     *                 {@code null} to clear tint
18852     * @attr ref android.R.styleable#View_backgroundTintMode
18853     * @see #getBackgroundTintMode()
18854     * @see Drawable#setTintMode(PorterDuff.Mode)
18855     */
18856    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
18857        if (mBackgroundTint == null) {
18858            mBackgroundTint = new TintInfo();
18859        }
18860        mBackgroundTint.mTintMode = tintMode;
18861        mBackgroundTint.mHasTintMode = true;
18862
18863        applyBackgroundTint();
18864    }
18865
18866    /**
18867     * Return the blending mode used to apply the tint to the background
18868     * drawable, if specified.
18869     *
18870     * @return the blending mode used to apply the tint to the background
18871     *         drawable
18872     * @attr ref android.R.styleable#View_backgroundTintMode
18873     * @see #setBackgroundTintMode(PorterDuff.Mode)
18874     */
18875    @Nullable
18876    public PorterDuff.Mode getBackgroundTintMode() {
18877        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
18878    }
18879
18880    private void applyBackgroundTint() {
18881        if (mBackground != null && mBackgroundTint != null) {
18882            final TintInfo tintInfo = mBackgroundTint;
18883            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
18884                mBackground = mBackground.mutate();
18885
18886                if (tintInfo.mHasTintList) {
18887                    mBackground.setTintList(tintInfo.mTintList);
18888                }
18889
18890                if (tintInfo.mHasTintMode) {
18891                    mBackground.setTintMode(tintInfo.mTintMode);
18892                }
18893
18894                // The drawable (or one of its children) may not have been
18895                // stateful before applying the tint, so let's try again.
18896                if (mBackground.isStateful()) {
18897                    mBackground.setState(getDrawableState());
18898                }
18899            }
18900        }
18901    }
18902
18903    /**
18904     * Returns the drawable used as the foreground of this View. The
18905     * foreground drawable, if non-null, is always drawn on top of the view's content.
18906     *
18907     * @return a Drawable or null if no foreground was set
18908     *
18909     * @see #onDrawForeground(Canvas)
18910     */
18911    public Drawable getForeground() {
18912        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18913    }
18914
18915    /**
18916     * Supply a Drawable that is to be rendered on top of all of the content in the view.
18917     *
18918     * @param foreground the Drawable to be drawn on top of the children
18919     *
18920     * @attr ref android.R.styleable#View_foreground
18921     */
18922    public void setForeground(Drawable foreground) {
18923        if (mForegroundInfo == null) {
18924            if (foreground == null) {
18925                // Nothing to do.
18926                return;
18927            }
18928            mForegroundInfo = new ForegroundInfo();
18929        }
18930
18931        if (foreground == mForegroundInfo.mDrawable) {
18932            // Nothing to do
18933            return;
18934        }
18935
18936        if (mForegroundInfo.mDrawable != null) {
18937            if (isAttachedToWindow()) {
18938                mForegroundInfo.mDrawable.setVisible(false, false);
18939            }
18940            mForegroundInfo.mDrawable.setCallback(null);
18941            unscheduleDrawable(mForegroundInfo.mDrawable);
18942        }
18943
18944        mForegroundInfo.mDrawable = foreground;
18945        mForegroundInfo.mBoundsChanged = true;
18946        if (foreground != null) {
18947            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18948                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18949            }
18950            foreground.setLayoutDirection(getLayoutDirection());
18951            if (foreground.isStateful()) {
18952                foreground.setState(getDrawableState());
18953            }
18954            applyForegroundTint();
18955            if (isAttachedToWindow()) {
18956                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18957            }
18958            // Set callback last, since the view may still be initializing.
18959            foreground.setCallback(this);
18960        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
18961            mPrivateFlags |= PFLAG_SKIP_DRAW;
18962        }
18963        requestLayout();
18964        invalidate();
18965    }
18966
18967    /**
18968     * Magic bit used to support features of framework-internal window decor implementation details.
18969     * This used to live exclusively in FrameLayout.
18970     *
18971     * @return true if the foreground should draw inside the padding region or false
18972     *         if it should draw inset by the view's padding
18973     * @hide internal use only; only used by FrameLayout and internal screen layouts.
18974     */
18975    public boolean isForegroundInsidePadding() {
18976        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
18977    }
18978
18979    /**
18980     * Describes how the foreground is positioned.
18981     *
18982     * @return foreground gravity.
18983     *
18984     * @see #setForegroundGravity(int)
18985     *
18986     * @attr ref android.R.styleable#View_foregroundGravity
18987     */
18988    public int getForegroundGravity() {
18989        return mForegroundInfo != null ? mForegroundInfo.mGravity
18990                : Gravity.START | Gravity.TOP;
18991    }
18992
18993    /**
18994     * Describes how the foreground is positioned. Defaults to START and TOP.
18995     *
18996     * @param gravity see {@link android.view.Gravity}
18997     *
18998     * @see #getForegroundGravity()
18999     *
19000     * @attr ref android.R.styleable#View_foregroundGravity
19001     */
19002    public void setForegroundGravity(int gravity) {
19003        if (mForegroundInfo == null) {
19004            mForegroundInfo = new ForegroundInfo();
19005        }
19006
19007        if (mForegroundInfo.mGravity != gravity) {
19008            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
19009                gravity |= Gravity.START;
19010            }
19011
19012            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
19013                gravity |= Gravity.TOP;
19014            }
19015
19016            mForegroundInfo.mGravity = gravity;
19017            requestLayout();
19018        }
19019    }
19020
19021    /**
19022     * Applies a tint to the foreground drawable. Does not modify the current tint
19023     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
19024     * <p>
19025     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
19026     * mutate the drawable and apply the specified tint and tint mode using
19027     * {@link Drawable#setTintList(ColorStateList)}.
19028     *
19029     * @param tint the tint to apply, may be {@code null} to clear tint
19030     *
19031     * @attr ref android.R.styleable#View_foregroundTint
19032     * @see #getForegroundTintList()
19033     * @see Drawable#setTintList(ColorStateList)
19034     */
19035    public void setForegroundTintList(@Nullable ColorStateList tint) {
19036        if (mForegroundInfo == null) {
19037            mForegroundInfo = new ForegroundInfo();
19038        }
19039        if (mForegroundInfo.mTintInfo == null) {
19040            mForegroundInfo.mTintInfo = new TintInfo();
19041        }
19042        mForegroundInfo.mTintInfo.mTintList = tint;
19043        mForegroundInfo.mTintInfo.mHasTintList = true;
19044
19045        applyForegroundTint();
19046    }
19047
19048    /**
19049     * Return the tint applied to the foreground drawable, if specified.
19050     *
19051     * @return the tint applied to the foreground drawable
19052     * @attr ref android.R.styleable#View_foregroundTint
19053     * @see #setForegroundTintList(ColorStateList)
19054     */
19055    @Nullable
19056    public ColorStateList getForegroundTintList() {
19057        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
19058                ? mForegroundInfo.mTintInfo.mTintList : null;
19059    }
19060
19061    /**
19062     * Specifies the blending mode used to apply the tint specified by
19063     * {@link #setForegroundTintList(ColorStateList)}} to the background
19064     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
19065     *
19066     * @param tintMode the blending mode used to apply the tint, may be
19067     *                 {@code null} to clear tint
19068     * @attr ref android.R.styleable#View_foregroundTintMode
19069     * @see #getForegroundTintMode()
19070     * @see Drawable#setTintMode(PorterDuff.Mode)
19071     */
19072    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
19073        if (mForegroundInfo == null) {
19074            mForegroundInfo = new ForegroundInfo();
19075        }
19076        if (mForegroundInfo.mTintInfo == null) {
19077            mForegroundInfo.mTintInfo = new TintInfo();
19078        }
19079        mForegroundInfo.mTintInfo.mTintMode = tintMode;
19080        mForegroundInfo.mTintInfo.mHasTintMode = true;
19081
19082        applyForegroundTint();
19083    }
19084
19085    /**
19086     * Return the blending mode used to apply the tint to the foreground
19087     * drawable, if specified.
19088     *
19089     * @return the blending mode used to apply the tint to the foreground
19090     *         drawable
19091     * @attr ref android.R.styleable#View_foregroundTintMode
19092     * @see #setForegroundTintMode(PorterDuff.Mode)
19093     */
19094    @Nullable
19095    public PorterDuff.Mode getForegroundTintMode() {
19096        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
19097                ? mForegroundInfo.mTintInfo.mTintMode : null;
19098    }
19099
19100    private void applyForegroundTint() {
19101        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19102                && mForegroundInfo.mTintInfo != null) {
19103            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
19104            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
19105                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
19106
19107                if (tintInfo.mHasTintList) {
19108                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
19109                }
19110
19111                if (tintInfo.mHasTintMode) {
19112                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
19113                }
19114
19115                // The drawable (or one of its children) may not have been
19116                // stateful before applying the tint, so let's try again.
19117                if (mForegroundInfo.mDrawable.isStateful()) {
19118                    mForegroundInfo.mDrawable.setState(getDrawableState());
19119                }
19120            }
19121        }
19122    }
19123
19124    /**
19125     * Draw any foreground content for this view.
19126     *
19127     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
19128     * drawable or other view-specific decorations. The foreground is drawn on top of the
19129     * primary view content.</p>
19130     *
19131     * @param canvas canvas to draw into
19132     */
19133    public void onDrawForeground(Canvas canvas) {
19134        onDrawScrollIndicators(canvas);
19135        onDrawScrollBars(canvas);
19136
19137        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19138        if (foreground != null) {
19139            if (mForegroundInfo.mBoundsChanged) {
19140                mForegroundInfo.mBoundsChanged = false;
19141                final Rect selfBounds = mForegroundInfo.mSelfBounds;
19142                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
19143
19144                if (mForegroundInfo.mInsidePadding) {
19145                    selfBounds.set(0, 0, getWidth(), getHeight());
19146                } else {
19147                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
19148                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
19149                }
19150
19151                final int ld = getLayoutDirection();
19152                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
19153                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
19154                foreground.setBounds(overlayBounds);
19155            }
19156
19157            foreground.draw(canvas);
19158        }
19159    }
19160
19161    /**
19162     * Sets the padding. The view may add on the space required to display
19163     * the scrollbars, depending on the style and visibility of the scrollbars.
19164     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
19165     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
19166     * from the values set in this call.
19167     *
19168     * @attr ref android.R.styleable#View_padding
19169     * @attr ref android.R.styleable#View_paddingBottom
19170     * @attr ref android.R.styleable#View_paddingLeft
19171     * @attr ref android.R.styleable#View_paddingRight
19172     * @attr ref android.R.styleable#View_paddingTop
19173     * @param left the left padding in pixels
19174     * @param top the top padding in pixels
19175     * @param right the right padding in pixels
19176     * @param bottom the bottom padding in pixels
19177     */
19178    public void setPadding(int left, int top, int right, int bottom) {
19179        resetResolvedPaddingInternal();
19180
19181        mUserPaddingStart = UNDEFINED_PADDING;
19182        mUserPaddingEnd = UNDEFINED_PADDING;
19183
19184        mUserPaddingLeftInitial = left;
19185        mUserPaddingRightInitial = right;
19186
19187        mLeftPaddingDefined = true;
19188        mRightPaddingDefined = true;
19189
19190        internalSetPadding(left, top, right, bottom);
19191    }
19192
19193    /**
19194     * @hide
19195     */
19196    protected void internalSetPadding(int left, int top, int right, int bottom) {
19197        mUserPaddingLeft = left;
19198        mUserPaddingRight = right;
19199        mUserPaddingBottom = bottom;
19200
19201        final int viewFlags = mViewFlags;
19202        boolean changed = false;
19203
19204        // Common case is there are no scroll bars.
19205        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
19206            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
19207                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
19208                        ? 0 : getVerticalScrollbarWidth();
19209                switch (mVerticalScrollbarPosition) {
19210                    case SCROLLBAR_POSITION_DEFAULT:
19211                        if (isLayoutRtl()) {
19212                            left += offset;
19213                        } else {
19214                            right += offset;
19215                        }
19216                        break;
19217                    case SCROLLBAR_POSITION_RIGHT:
19218                        right += offset;
19219                        break;
19220                    case SCROLLBAR_POSITION_LEFT:
19221                        left += offset;
19222                        break;
19223                }
19224            }
19225            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
19226                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
19227                        ? 0 : getHorizontalScrollbarHeight();
19228            }
19229        }
19230
19231        if (mPaddingLeft != left) {
19232            changed = true;
19233            mPaddingLeft = left;
19234        }
19235        if (mPaddingTop != top) {
19236            changed = true;
19237            mPaddingTop = top;
19238        }
19239        if (mPaddingRight != right) {
19240            changed = true;
19241            mPaddingRight = right;
19242        }
19243        if (mPaddingBottom != bottom) {
19244            changed = true;
19245            mPaddingBottom = bottom;
19246        }
19247
19248        if (changed) {
19249            requestLayout();
19250            invalidateOutline();
19251        }
19252    }
19253
19254    /**
19255     * Sets the relative padding. The view may add on the space required to display
19256     * the scrollbars, depending on the style and visibility of the scrollbars.
19257     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
19258     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
19259     * from the values set in this call.
19260     *
19261     * @attr ref android.R.styleable#View_padding
19262     * @attr ref android.R.styleable#View_paddingBottom
19263     * @attr ref android.R.styleable#View_paddingStart
19264     * @attr ref android.R.styleable#View_paddingEnd
19265     * @attr ref android.R.styleable#View_paddingTop
19266     * @param start the start padding in pixels
19267     * @param top the top padding in pixels
19268     * @param end the end padding in pixels
19269     * @param bottom the bottom padding in pixels
19270     */
19271    public void setPaddingRelative(int start, int top, int end, int bottom) {
19272        resetResolvedPaddingInternal();
19273
19274        mUserPaddingStart = start;
19275        mUserPaddingEnd = end;
19276        mLeftPaddingDefined = true;
19277        mRightPaddingDefined = true;
19278
19279        switch(getLayoutDirection()) {
19280            case LAYOUT_DIRECTION_RTL:
19281                mUserPaddingLeftInitial = end;
19282                mUserPaddingRightInitial = start;
19283                internalSetPadding(end, top, start, bottom);
19284                break;
19285            case LAYOUT_DIRECTION_LTR:
19286            default:
19287                mUserPaddingLeftInitial = start;
19288                mUserPaddingRightInitial = end;
19289                internalSetPadding(start, top, end, bottom);
19290        }
19291    }
19292
19293    /**
19294     * Returns the top padding of this view.
19295     *
19296     * @return the top padding in pixels
19297     */
19298    public int getPaddingTop() {
19299        return mPaddingTop;
19300    }
19301
19302    /**
19303     * Returns the bottom padding of this view. If there are inset and enabled
19304     * scrollbars, this value may include the space required to display the
19305     * scrollbars as well.
19306     *
19307     * @return the bottom padding in pixels
19308     */
19309    public int getPaddingBottom() {
19310        return mPaddingBottom;
19311    }
19312
19313    /**
19314     * Returns the left padding of this view. If there are inset and enabled
19315     * scrollbars, this value may include the space required to display the
19316     * scrollbars as well.
19317     *
19318     * @return the left padding in pixels
19319     */
19320    public int getPaddingLeft() {
19321        if (!isPaddingResolved()) {
19322            resolvePadding();
19323        }
19324        return mPaddingLeft;
19325    }
19326
19327    /**
19328     * Returns the start padding of this view depending on its resolved layout direction.
19329     * If there are inset and enabled scrollbars, this value may include the space
19330     * required to display the scrollbars as well.
19331     *
19332     * @return the start padding in pixels
19333     */
19334    public int getPaddingStart() {
19335        if (!isPaddingResolved()) {
19336            resolvePadding();
19337        }
19338        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
19339                mPaddingRight : mPaddingLeft;
19340    }
19341
19342    /**
19343     * Returns the right padding of this view. If there are inset and enabled
19344     * scrollbars, this value may include the space required to display the
19345     * scrollbars as well.
19346     *
19347     * @return the right padding in pixels
19348     */
19349    public int getPaddingRight() {
19350        if (!isPaddingResolved()) {
19351            resolvePadding();
19352        }
19353        return mPaddingRight;
19354    }
19355
19356    /**
19357     * Returns the end padding of this view depending on its resolved layout direction.
19358     * If there are inset and enabled scrollbars, this value may include the space
19359     * required to display the scrollbars as well.
19360     *
19361     * @return the end padding in pixels
19362     */
19363    public int getPaddingEnd() {
19364        if (!isPaddingResolved()) {
19365            resolvePadding();
19366        }
19367        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
19368                mPaddingLeft : mPaddingRight;
19369    }
19370
19371    /**
19372     * Return if the padding has been set through relative values
19373     * {@link #setPaddingRelative(int, int, int, int)} or through
19374     * @attr ref android.R.styleable#View_paddingStart or
19375     * @attr ref android.R.styleable#View_paddingEnd
19376     *
19377     * @return true if the padding is relative or false if it is not.
19378     */
19379    public boolean isPaddingRelative() {
19380        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
19381    }
19382
19383    Insets computeOpticalInsets() {
19384        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
19385    }
19386
19387    /**
19388     * @hide
19389     */
19390    public void resetPaddingToInitialValues() {
19391        if (isRtlCompatibilityMode()) {
19392            mPaddingLeft = mUserPaddingLeftInitial;
19393            mPaddingRight = mUserPaddingRightInitial;
19394            return;
19395        }
19396        if (isLayoutRtl()) {
19397            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
19398            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
19399        } else {
19400            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
19401            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
19402        }
19403    }
19404
19405    /**
19406     * @hide
19407     */
19408    public Insets getOpticalInsets() {
19409        if (mLayoutInsets == null) {
19410            mLayoutInsets = computeOpticalInsets();
19411        }
19412        return mLayoutInsets;
19413    }
19414
19415    /**
19416     * Set this view's optical insets.
19417     *
19418     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
19419     * property. Views that compute their own optical insets should call it as part of measurement.
19420     * This method does not request layout. If you are setting optical insets outside of
19421     * measure/layout itself you will want to call requestLayout() yourself.
19422     * </p>
19423     * @hide
19424     */
19425    public void setOpticalInsets(Insets insets) {
19426        mLayoutInsets = insets;
19427    }
19428
19429    /**
19430     * Changes the selection state of this view. A view can be selected or not.
19431     * Note that selection is not the same as focus. Views are typically
19432     * selected in the context of an AdapterView like ListView or GridView;
19433     * the selected view is the view that is highlighted.
19434     *
19435     * @param selected true if the view must be selected, false otherwise
19436     */
19437    public void setSelected(boolean selected) {
19438        //noinspection DoubleNegation
19439        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
19440            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
19441            if (!selected) resetPressedState();
19442            invalidate(true);
19443            refreshDrawableState();
19444            dispatchSetSelected(selected);
19445            if (selected) {
19446                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
19447            } else {
19448                notifyViewAccessibilityStateChangedIfNeeded(
19449                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
19450            }
19451        }
19452    }
19453
19454    /**
19455     * Dispatch setSelected to all of this View's children.
19456     *
19457     * @see #setSelected(boolean)
19458     *
19459     * @param selected The new selected state
19460     */
19461    protected void dispatchSetSelected(boolean selected) {
19462    }
19463
19464    /**
19465     * Indicates the selection state of this view.
19466     *
19467     * @return true if the view is selected, false otherwise
19468     */
19469    @ViewDebug.ExportedProperty
19470    public boolean isSelected() {
19471        return (mPrivateFlags & PFLAG_SELECTED) != 0;
19472    }
19473
19474    /**
19475     * Changes the activated state of this view. A view can be activated or not.
19476     * Note that activation is not the same as selection.  Selection is
19477     * a transient property, representing the view (hierarchy) the user is
19478     * currently interacting with.  Activation is a longer-term state that the
19479     * user can move views in and out of.  For example, in a list view with
19480     * single or multiple selection enabled, the views in the current selection
19481     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
19482     * here.)  The activated state is propagated down to children of the view it
19483     * is set on.
19484     *
19485     * @param activated true if the view must be activated, false otherwise
19486     */
19487    public void setActivated(boolean activated) {
19488        //noinspection DoubleNegation
19489        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
19490            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
19491            invalidate(true);
19492            refreshDrawableState();
19493            dispatchSetActivated(activated);
19494        }
19495    }
19496
19497    /**
19498     * Dispatch setActivated to all of this View's children.
19499     *
19500     * @see #setActivated(boolean)
19501     *
19502     * @param activated The new activated state
19503     */
19504    protected void dispatchSetActivated(boolean activated) {
19505    }
19506
19507    /**
19508     * Indicates the activation state of this view.
19509     *
19510     * @return true if the view is activated, false otherwise
19511     */
19512    @ViewDebug.ExportedProperty
19513    public boolean isActivated() {
19514        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
19515    }
19516
19517    /**
19518     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
19519     * observer can be used to get notifications when global events, like
19520     * layout, happen.
19521     *
19522     * The returned ViewTreeObserver observer is not guaranteed to remain
19523     * valid for the lifetime of this View. If the caller of this method keeps
19524     * a long-lived reference to ViewTreeObserver, it should always check for
19525     * the return value of {@link ViewTreeObserver#isAlive()}.
19526     *
19527     * @return The ViewTreeObserver for this view's hierarchy.
19528     */
19529    public ViewTreeObserver getViewTreeObserver() {
19530        if (mAttachInfo != null) {
19531            return mAttachInfo.mTreeObserver;
19532        }
19533        if (mFloatingTreeObserver == null) {
19534            mFloatingTreeObserver = new ViewTreeObserver(mContext);
19535        }
19536        return mFloatingTreeObserver;
19537    }
19538
19539    /**
19540     * <p>Finds the topmost view in the current view hierarchy.</p>
19541     *
19542     * @return the topmost view containing this view
19543     */
19544    public View getRootView() {
19545        if (mAttachInfo != null) {
19546            final View v = mAttachInfo.mRootView;
19547            if (v != null) {
19548                return v;
19549            }
19550        }
19551
19552        View parent = this;
19553
19554        while (parent.mParent != null && parent.mParent instanceof View) {
19555            parent = (View) parent.mParent;
19556        }
19557
19558        return parent;
19559    }
19560
19561    /**
19562     * Transforms a motion event from view-local coordinates to on-screen
19563     * coordinates.
19564     *
19565     * @param ev the view-local motion event
19566     * @return false if the transformation could not be applied
19567     * @hide
19568     */
19569    public boolean toGlobalMotionEvent(MotionEvent ev) {
19570        final AttachInfo info = mAttachInfo;
19571        if (info == null) {
19572            return false;
19573        }
19574
19575        final Matrix m = info.mTmpMatrix;
19576        m.set(Matrix.IDENTITY_MATRIX);
19577        transformMatrixToGlobal(m);
19578        ev.transform(m);
19579        return true;
19580    }
19581
19582    /**
19583     * Transforms a motion event from on-screen coordinates to view-local
19584     * coordinates.
19585     *
19586     * @param ev the on-screen motion event
19587     * @return false if the transformation could not be applied
19588     * @hide
19589     */
19590    public boolean toLocalMotionEvent(MotionEvent ev) {
19591        final AttachInfo info = mAttachInfo;
19592        if (info == null) {
19593            return false;
19594        }
19595
19596        final Matrix m = info.mTmpMatrix;
19597        m.set(Matrix.IDENTITY_MATRIX);
19598        transformMatrixToLocal(m);
19599        ev.transform(m);
19600        return true;
19601    }
19602
19603    /**
19604     * Modifies the input matrix such that it maps view-local coordinates to
19605     * on-screen coordinates.
19606     *
19607     * @param m input matrix to modify
19608     * @hide
19609     */
19610    public void transformMatrixToGlobal(Matrix m) {
19611        final ViewParent parent = mParent;
19612        if (parent instanceof View) {
19613            final View vp = (View) parent;
19614            vp.transformMatrixToGlobal(m);
19615            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
19616        } else if (parent instanceof ViewRootImpl) {
19617            final ViewRootImpl vr = (ViewRootImpl) parent;
19618            vr.transformMatrixToGlobal(m);
19619            m.preTranslate(0, -vr.mCurScrollY);
19620        }
19621
19622        m.preTranslate(mLeft, mTop);
19623
19624        if (!hasIdentityMatrix()) {
19625            m.preConcat(getMatrix());
19626        }
19627    }
19628
19629    /**
19630     * Modifies the input matrix such that it maps on-screen coordinates to
19631     * view-local coordinates.
19632     *
19633     * @param m input matrix to modify
19634     * @hide
19635     */
19636    public void transformMatrixToLocal(Matrix m) {
19637        final ViewParent parent = mParent;
19638        if (parent instanceof View) {
19639            final View vp = (View) parent;
19640            vp.transformMatrixToLocal(m);
19641            m.postTranslate(vp.mScrollX, vp.mScrollY);
19642        } else if (parent instanceof ViewRootImpl) {
19643            final ViewRootImpl vr = (ViewRootImpl) parent;
19644            vr.transformMatrixToLocal(m);
19645            m.postTranslate(0, vr.mCurScrollY);
19646        }
19647
19648        m.postTranslate(-mLeft, -mTop);
19649
19650        if (!hasIdentityMatrix()) {
19651            m.postConcat(getInverseMatrix());
19652        }
19653    }
19654
19655    /**
19656     * @hide
19657     */
19658    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
19659            @ViewDebug.IntToString(from = 0, to = "x"),
19660            @ViewDebug.IntToString(from = 1, to = "y")
19661    })
19662    public int[] getLocationOnScreen() {
19663        int[] location = new int[2];
19664        getLocationOnScreen(location);
19665        return location;
19666    }
19667
19668    /**
19669     * <p>Computes the coordinates of this view on the screen. The argument
19670     * must be an array of two integers. After the method returns, the array
19671     * contains the x and y location in that order.</p>
19672     *
19673     * @param outLocation an array of two integers in which to hold the coordinates
19674     */
19675    public void getLocationOnScreen(@Size(2) int[] outLocation) {
19676        getLocationInWindow(outLocation);
19677
19678        final AttachInfo info = mAttachInfo;
19679        if (info != null) {
19680            outLocation[0] += info.mWindowLeft;
19681            outLocation[1] += info.mWindowTop;
19682        }
19683    }
19684
19685    /**
19686     * <p>Computes the coordinates of this view in its window. The argument
19687     * must be an array of two integers. After the method returns, the array
19688     * contains the x and y location in that order.</p>
19689     *
19690     * @param outLocation an array of two integers in which to hold the coordinates
19691     */
19692    public void getLocationInWindow(@Size(2) int[] outLocation) {
19693        if (outLocation == null || outLocation.length < 2) {
19694            throw new IllegalArgumentException("outLocation must be an array of two integers");
19695        }
19696
19697        outLocation[0] = 0;
19698        outLocation[1] = 0;
19699
19700        transformFromViewToWindowSpace(outLocation);
19701    }
19702
19703    /** @hide */
19704    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
19705        if (inOutLocation == null || inOutLocation.length < 2) {
19706            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
19707        }
19708
19709        if (mAttachInfo == null) {
19710            // When the view is not attached to a window, this method does not make sense
19711            inOutLocation[0] = inOutLocation[1] = 0;
19712            return;
19713        }
19714
19715        float position[] = mAttachInfo.mTmpTransformLocation;
19716        position[0] = inOutLocation[0];
19717        position[1] = inOutLocation[1];
19718
19719        if (!hasIdentityMatrix()) {
19720            getMatrix().mapPoints(position);
19721        }
19722
19723        position[0] += mLeft;
19724        position[1] += mTop;
19725
19726        ViewParent viewParent = mParent;
19727        while (viewParent instanceof View) {
19728            final View view = (View) viewParent;
19729
19730            position[0] -= view.mScrollX;
19731            position[1] -= view.mScrollY;
19732
19733            if (!view.hasIdentityMatrix()) {
19734                view.getMatrix().mapPoints(position);
19735            }
19736
19737            position[0] += view.mLeft;
19738            position[1] += view.mTop;
19739
19740            viewParent = view.mParent;
19741         }
19742
19743        if (viewParent instanceof ViewRootImpl) {
19744            // *cough*
19745            final ViewRootImpl vr = (ViewRootImpl) viewParent;
19746            position[1] -= vr.mCurScrollY;
19747        }
19748
19749        inOutLocation[0] = Math.round(position[0]);
19750        inOutLocation[1] = Math.round(position[1]);
19751    }
19752
19753    /**
19754     * {@hide}
19755     * @param id the id of the view to be found
19756     * @return the view of the specified id, null if cannot be found
19757     */
19758    protected View findViewTraversal(@IdRes int id) {
19759        if (id == mID) {
19760            return this;
19761        }
19762        return null;
19763    }
19764
19765    /**
19766     * {@hide}
19767     * @param tag the tag of the view to be found
19768     * @return the view of specified tag, null if cannot be found
19769     */
19770    protected View findViewWithTagTraversal(Object tag) {
19771        if (tag != null && tag.equals(mTag)) {
19772            return this;
19773        }
19774        return null;
19775    }
19776
19777    /**
19778     * {@hide}
19779     * @param predicate The predicate to evaluate.
19780     * @param childToSkip If not null, ignores this child during the recursive traversal.
19781     * @return The first view that matches the predicate or null.
19782     */
19783    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
19784        if (predicate.apply(this)) {
19785            return this;
19786        }
19787        return null;
19788    }
19789
19790    /**
19791     * Look for a child view with the given id.  If this view has the given
19792     * id, return this view.
19793     *
19794     * @param id The id to search for.
19795     * @return The view that has the given id in the hierarchy or null
19796     */
19797    @Nullable
19798    public final View findViewById(@IdRes int id) {
19799        if (id < 0) {
19800            return null;
19801        }
19802        return findViewTraversal(id);
19803    }
19804
19805    /**
19806     * Finds a view by its unuque and stable accessibility id.
19807     *
19808     * @param accessibilityId The searched accessibility id.
19809     * @return The found view.
19810     */
19811    final View findViewByAccessibilityId(int accessibilityId) {
19812        if (accessibilityId < 0) {
19813            return null;
19814        }
19815        View view = findViewByAccessibilityIdTraversal(accessibilityId);
19816        if (view != null) {
19817            return view.includeForAccessibility() ? view : null;
19818        }
19819        return null;
19820    }
19821
19822    /**
19823     * Performs the traversal to find a view by its unuque and stable accessibility id.
19824     *
19825     * <strong>Note:</strong>This method does not stop at the root namespace
19826     * boundary since the user can touch the screen at an arbitrary location
19827     * potentially crossing the root namespace bounday which will send an
19828     * accessibility event to accessibility services and they should be able
19829     * to obtain the event source. Also accessibility ids are guaranteed to be
19830     * unique in the window.
19831     *
19832     * @param accessibilityId The accessibility id.
19833     * @return The found view.
19834     *
19835     * @hide
19836     */
19837    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
19838        if (getAccessibilityViewId() == accessibilityId) {
19839            return this;
19840        }
19841        return null;
19842    }
19843
19844    /**
19845     * Look for a child view with the given tag.  If this view has the given
19846     * tag, return this view.
19847     *
19848     * @param tag The tag to search for, using "tag.equals(getTag())".
19849     * @return The View that has the given tag in the hierarchy or null
19850     */
19851    public final View findViewWithTag(Object tag) {
19852        if (tag == null) {
19853            return null;
19854        }
19855        return findViewWithTagTraversal(tag);
19856    }
19857
19858    /**
19859     * {@hide}
19860     * Look for a child view that matches the specified predicate.
19861     * If this view matches the predicate, return this view.
19862     *
19863     * @param predicate The predicate to evaluate.
19864     * @return The first view that matches the predicate or null.
19865     */
19866    public final View findViewByPredicate(Predicate<View> predicate) {
19867        return findViewByPredicateTraversal(predicate, null);
19868    }
19869
19870    /**
19871     * {@hide}
19872     * Look for a child view that matches the specified predicate,
19873     * starting with the specified view and its descendents and then
19874     * recusively searching the ancestors and siblings of that view
19875     * until this view is reached.
19876     *
19877     * This method is useful in cases where the predicate does not match
19878     * a single unique view (perhaps multiple views use the same id)
19879     * and we are trying to find the view that is "closest" in scope to the
19880     * starting view.
19881     *
19882     * @param start The view to start from.
19883     * @param predicate The predicate to evaluate.
19884     * @return The first view that matches the predicate or null.
19885     */
19886    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
19887        View childToSkip = null;
19888        for (;;) {
19889            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
19890            if (view != null || start == this) {
19891                return view;
19892            }
19893
19894            ViewParent parent = start.getParent();
19895            if (parent == null || !(parent instanceof View)) {
19896                return null;
19897            }
19898
19899            childToSkip = start;
19900            start = (View) parent;
19901        }
19902    }
19903
19904    /**
19905     * Sets the identifier for this view. The identifier does not have to be
19906     * unique in this view's hierarchy. The identifier should be a positive
19907     * number.
19908     *
19909     * @see #NO_ID
19910     * @see #getId()
19911     * @see #findViewById(int)
19912     *
19913     * @param id a number used to identify the view
19914     *
19915     * @attr ref android.R.styleable#View_id
19916     */
19917    public void setId(@IdRes int id) {
19918        mID = id;
19919        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
19920            mID = generateViewId();
19921        }
19922    }
19923
19924    /**
19925     * {@hide}
19926     *
19927     * @param isRoot true if the view belongs to the root namespace, false
19928     *        otherwise
19929     */
19930    public void setIsRootNamespace(boolean isRoot) {
19931        if (isRoot) {
19932            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
19933        } else {
19934            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
19935        }
19936    }
19937
19938    /**
19939     * {@hide}
19940     *
19941     * @return true if the view belongs to the root namespace, false otherwise
19942     */
19943    public boolean isRootNamespace() {
19944        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
19945    }
19946
19947    /**
19948     * Returns this view's identifier.
19949     *
19950     * @return a positive integer used to identify the view or {@link #NO_ID}
19951     *         if the view has no ID
19952     *
19953     * @see #setId(int)
19954     * @see #findViewById(int)
19955     * @attr ref android.R.styleable#View_id
19956     */
19957    @IdRes
19958    @ViewDebug.CapturedViewProperty
19959    public int getId() {
19960        return mID;
19961    }
19962
19963    /**
19964     * Returns this view's tag.
19965     *
19966     * @return the Object stored in this view as a tag, or {@code null} if not
19967     *         set
19968     *
19969     * @see #setTag(Object)
19970     * @see #getTag(int)
19971     */
19972    @ViewDebug.ExportedProperty
19973    public Object getTag() {
19974        return mTag;
19975    }
19976
19977    /**
19978     * Sets the tag associated with this view. A tag can be used to mark
19979     * a view in its hierarchy and does not have to be unique within the
19980     * hierarchy. Tags can also be used to store data within a view without
19981     * resorting to another data structure.
19982     *
19983     * @param tag an Object to tag the view with
19984     *
19985     * @see #getTag()
19986     * @see #setTag(int, Object)
19987     */
19988    public void setTag(final Object tag) {
19989        mTag = tag;
19990    }
19991
19992    /**
19993     * Returns the tag associated with this view and the specified key.
19994     *
19995     * @param key The key identifying the tag
19996     *
19997     * @return the Object stored in this view as a tag, or {@code null} if not
19998     *         set
19999     *
20000     * @see #setTag(int, Object)
20001     * @see #getTag()
20002     */
20003    public Object getTag(int key) {
20004        if (mKeyedTags != null) return mKeyedTags.get(key);
20005        return null;
20006    }
20007
20008    /**
20009     * Sets a tag associated with this view and a key. A tag can be used
20010     * to mark a view in its hierarchy and does not have to be unique within
20011     * the hierarchy. Tags can also be used to store data within a view
20012     * without resorting to another data structure.
20013     *
20014     * The specified key should be an id declared in the resources of the
20015     * application to ensure it is unique (see the <a
20016     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
20017     * Keys identified as belonging to
20018     * the Android framework or not associated with any package will cause
20019     * an {@link IllegalArgumentException} to be thrown.
20020     *
20021     * @param key The key identifying the tag
20022     * @param tag An Object to tag the view with
20023     *
20024     * @throws IllegalArgumentException If they specified key is not valid
20025     *
20026     * @see #setTag(Object)
20027     * @see #getTag(int)
20028     */
20029    public void setTag(int key, final Object tag) {
20030        // If the package id is 0x00 or 0x01, it's either an undefined package
20031        // or a framework id
20032        if ((key >>> 24) < 2) {
20033            throw new IllegalArgumentException("The key must be an application-specific "
20034                    + "resource id.");
20035        }
20036
20037        setKeyedTag(key, tag);
20038    }
20039
20040    /**
20041     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
20042     * framework id.
20043     *
20044     * @hide
20045     */
20046    public void setTagInternal(int key, Object tag) {
20047        if ((key >>> 24) != 0x1) {
20048            throw new IllegalArgumentException("The key must be a framework-specific "
20049                    + "resource id.");
20050        }
20051
20052        setKeyedTag(key, tag);
20053    }
20054
20055    private void setKeyedTag(int key, Object tag) {
20056        if (mKeyedTags == null) {
20057            mKeyedTags = new SparseArray<Object>(2);
20058        }
20059
20060        mKeyedTags.put(key, tag);
20061    }
20062
20063    /**
20064     * Prints information about this view in the log output, with the tag
20065     * {@link #VIEW_LOG_TAG}.
20066     *
20067     * @hide
20068     */
20069    public void debug() {
20070        debug(0);
20071    }
20072
20073    /**
20074     * Prints information about this view in the log output, with the tag
20075     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
20076     * indentation defined by the <code>depth</code>.
20077     *
20078     * @param depth the indentation level
20079     *
20080     * @hide
20081     */
20082    protected void debug(int depth) {
20083        String output = debugIndent(depth - 1);
20084
20085        output += "+ " + this;
20086        int id = getId();
20087        if (id != -1) {
20088            output += " (id=" + id + ")";
20089        }
20090        Object tag = getTag();
20091        if (tag != null) {
20092            output += " (tag=" + tag + ")";
20093        }
20094        Log.d(VIEW_LOG_TAG, output);
20095
20096        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
20097            output = debugIndent(depth) + " FOCUSED";
20098            Log.d(VIEW_LOG_TAG, output);
20099        }
20100
20101        output = debugIndent(depth);
20102        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
20103                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
20104                + "} ";
20105        Log.d(VIEW_LOG_TAG, output);
20106
20107        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
20108                || mPaddingBottom != 0) {
20109            output = debugIndent(depth);
20110            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
20111                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
20112            Log.d(VIEW_LOG_TAG, output);
20113        }
20114
20115        output = debugIndent(depth);
20116        output += "mMeasureWidth=" + mMeasuredWidth +
20117                " mMeasureHeight=" + mMeasuredHeight;
20118        Log.d(VIEW_LOG_TAG, output);
20119
20120        output = debugIndent(depth);
20121        if (mLayoutParams == null) {
20122            output += "BAD! no layout params";
20123        } else {
20124            output = mLayoutParams.debug(output);
20125        }
20126        Log.d(VIEW_LOG_TAG, output);
20127
20128        output = debugIndent(depth);
20129        output += "flags={";
20130        output += View.printFlags(mViewFlags);
20131        output += "}";
20132        Log.d(VIEW_LOG_TAG, output);
20133
20134        output = debugIndent(depth);
20135        output += "privateFlags={";
20136        output += View.printPrivateFlags(mPrivateFlags);
20137        output += "}";
20138        Log.d(VIEW_LOG_TAG, output);
20139    }
20140
20141    /**
20142     * Creates a string of whitespaces used for indentation.
20143     *
20144     * @param depth the indentation level
20145     * @return a String containing (depth * 2 + 3) * 2 white spaces
20146     *
20147     * @hide
20148     */
20149    protected static String debugIndent(int depth) {
20150        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
20151        for (int i = 0; i < (depth * 2) + 3; i++) {
20152            spaces.append(' ').append(' ');
20153        }
20154        return spaces.toString();
20155    }
20156
20157    /**
20158     * <p>Return the offset of the widget's text baseline from the widget's top
20159     * boundary. If this widget does not support baseline alignment, this
20160     * method returns -1. </p>
20161     *
20162     * @return the offset of the baseline within the widget's bounds or -1
20163     *         if baseline alignment is not supported
20164     */
20165    @ViewDebug.ExportedProperty(category = "layout")
20166    public int getBaseline() {
20167        return -1;
20168    }
20169
20170    /**
20171     * Returns whether the view hierarchy is currently undergoing a layout pass. This
20172     * information is useful to avoid situations such as calling {@link #requestLayout()} during
20173     * a layout pass.
20174     *
20175     * @return whether the view hierarchy is currently undergoing a layout pass
20176     */
20177    public boolean isInLayout() {
20178        ViewRootImpl viewRoot = getViewRootImpl();
20179        return (viewRoot != null && viewRoot.isInLayout());
20180    }
20181
20182    /**
20183     * Call this when something has changed which has invalidated the
20184     * layout of this view. This will schedule a layout pass of the view
20185     * tree. This should not be called while the view hierarchy is currently in a layout
20186     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
20187     * end of the current layout pass (and then layout will run again) or after the current
20188     * frame is drawn and the next layout occurs.
20189     *
20190     * <p>Subclasses which override this method should call the superclass method to
20191     * handle possible request-during-layout errors correctly.</p>
20192     */
20193    @CallSuper
20194    public void requestLayout() {
20195        if (mMeasureCache != null) mMeasureCache.clear();
20196
20197        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
20198            // Only trigger request-during-layout logic if this is the view requesting it,
20199            // not the views in its parent hierarchy
20200            ViewRootImpl viewRoot = getViewRootImpl();
20201            if (viewRoot != null && viewRoot.isInLayout()) {
20202                if (!viewRoot.requestLayoutDuringLayout(this)) {
20203                    return;
20204                }
20205            }
20206            mAttachInfo.mViewRequestingLayout = this;
20207        }
20208
20209        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
20210        mPrivateFlags |= PFLAG_INVALIDATED;
20211
20212        if (mParent != null && !mParent.isLayoutRequested()) {
20213            mParent.requestLayout();
20214        }
20215        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
20216            mAttachInfo.mViewRequestingLayout = null;
20217        }
20218    }
20219
20220    /**
20221     * Forces this view to be laid out during the next layout pass.
20222     * This method does not call requestLayout() or forceLayout()
20223     * on the parent.
20224     */
20225    public void forceLayout() {
20226        if (mMeasureCache != null) mMeasureCache.clear();
20227
20228        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
20229        mPrivateFlags |= PFLAG_INVALIDATED;
20230    }
20231
20232    /**
20233     * <p>
20234     * This is called to find out how big a view should be. The parent
20235     * supplies constraint information in the width and height parameters.
20236     * </p>
20237     *
20238     * <p>
20239     * The actual measurement work of a view is performed in
20240     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
20241     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
20242     * </p>
20243     *
20244     *
20245     * @param widthMeasureSpec Horizontal space requirements as imposed by the
20246     *        parent
20247     * @param heightMeasureSpec Vertical space requirements as imposed by the
20248     *        parent
20249     *
20250     * @see #onMeasure(int, int)
20251     */
20252    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
20253        boolean optical = isLayoutModeOptical(this);
20254        if (optical != isLayoutModeOptical(mParent)) {
20255            Insets insets = getOpticalInsets();
20256            int oWidth  = insets.left + insets.right;
20257            int oHeight = insets.top  + insets.bottom;
20258            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
20259            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
20260        }
20261
20262        // Suppress sign extension for the low bytes
20263        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
20264        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
20265
20266        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
20267
20268        // Optimize layout by avoiding an extra EXACTLY pass when the view is
20269        // already measured as the correct size. In API 23 and below, this
20270        // extra pass is required to make LinearLayout re-distribute weight.
20271        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
20272                || heightMeasureSpec != mOldHeightMeasureSpec;
20273        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
20274                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
20275        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
20276                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
20277        final boolean needsLayout = specChanged
20278                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
20279
20280        if (forceLayout || needsLayout) {
20281            // first clears the measured dimension flag
20282            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
20283
20284            resolveRtlPropertiesIfNeeded();
20285
20286            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
20287            if (cacheIndex < 0 || sIgnoreMeasureCache) {
20288                // measure ourselves, this should set the measured dimension flag back
20289                onMeasure(widthMeasureSpec, heightMeasureSpec);
20290                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
20291            } else {
20292                long value = mMeasureCache.valueAt(cacheIndex);
20293                // Casting a long to int drops the high 32 bits, no mask needed
20294                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
20295                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
20296            }
20297
20298            // flag not set, setMeasuredDimension() was not invoked, we raise
20299            // an exception to warn the developer
20300            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
20301                throw new IllegalStateException("View with id " + getId() + ": "
20302                        + getClass().getName() + "#onMeasure() did not set the"
20303                        + " measured dimension by calling"
20304                        + " setMeasuredDimension()");
20305            }
20306
20307            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
20308        }
20309
20310        mOldWidthMeasureSpec = widthMeasureSpec;
20311        mOldHeightMeasureSpec = heightMeasureSpec;
20312
20313        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
20314                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
20315    }
20316
20317    /**
20318     * <p>
20319     * Measure the view and its content to determine the measured width and the
20320     * measured height. This method is invoked by {@link #measure(int, int)} and
20321     * should be overridden by subclasses to provide accurate and efficient
20322     * measurement of their contents.
20323     * </p>
20324     *
20325     * <p>
20326     * <strong>CONTRACT:</strong> When overriding this method, you
20327     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
20328     * measured width and height of this view. Failure to do so will trigger an
20329     * <code>IllegalStateException</code>, thrown by
20330     * {@link #measure(int, int)}. Calling the superclass'
20331     * {@link #onMeasure(int, int)} is a valid use.
20332     * </p>
20333     *
20334     * <p>
20335     * The base class implementation of measure defaults to the background size,
20336     * unless a larger size is allowed by the MeasureSpec. Subclasses should
20337     * override {@link #onMeasure(int, int)} to provide better measurements of
20338     * their content.
20339     * </p>
20340     *
20341     * <p>
20342     * If this method is overridden, it is the subclass's responsibility to make
20343     * sure the measured height and width are at least the view's minimum height
20344     * and width ({@link #getSuggestedMinimumHeight()} and
20345     * {@link #getSuggestedMinimumWidth()}).
20346     * </p>
20347     *
20348     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
20349     *                         The requirements are encoded with
20350     *                         {@link android.view.View.MeasureSpec}.
20351     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
20352     *                         The requirements are encoded with
20353     *                         {@link android.view.View.MeasureSpec}.
20354     *
20355     * @see #getMeasuredWidth()
20356     * @see #getMeasuredHeight()
20357     * @see #setMeasuredDimension(int, int)
20358     * @see #getSuggestedMinimumHeight()
20359     * @see #getSuggestedMinimumWidth()
20360     * @see android.view.View.MeasureSpec#getMode(int)
20361     * @see android.view.View.MeasureSpec#getSize(int)
20362     */
20363    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
20364        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
20365                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
20366    }
20367
20368    /**
20369     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
20370     * measured width and measured height. Failing to do so will trigger an
20371     * exception at measurement time.</p>
20372     *
20373     * @param measuredWidth The measured width of this view.  May be a complex
20374     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20375     * {@link #MEASURED_STATE_TOO_SMALL}.
20376     * @param measuredHeight The measured height of this view.  May be a complex
20377     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20378     * {@link #MEASURED_STATE_TOO_SMALL}.
20379     */
20380    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
20381        boolean optical = isLayoutModeOptical(this);
20382        if (optical != isLayoutModeOptical(mParent)) {
20383            Insets insets = getOpticalInsets();
20384            int opticalWidth  = insets.left + insets.right;
20385            int opticalHeight = insets.top  + insets.bottom;
20386
20387            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
20388            measuredHeight += optical ? opticalHeight : -opticalHeight;
20389        }
20390        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
20391    }
20392
20393    /**
20394     * Sets the measured dimension without extra processing for things like optical bounds.
20395     * Useful for reapplying consistent values that have already been cooked with adjustments
20396     * for optical bounds, etc. such as those from the measurement cache.
20397     *
20398     * @param measuredWidth The measured width of this view.  May be a complex
20399     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20400     * {@link #MEASURED_STATE_TOO_SMALL}.
20401     * @param measuredHeight The measured height of this view.  May be a complex
20402     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20403     * {@link #MEASURED_STATE_TOO_SMALL}.
20404     */
20405    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
20406        mMeasuredWidth = measuredWidth;
20407        mMeasuredHeight = measuredHeight;
20408
20409        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
20410    }
20411
20412    /**
20413     * Merge two states as returned by {@link #getMeasuredState()}.
20414     * @param curState The current state as returned from a view or the result
20415     * of combining multiple views.
20416     * @param newState The new view state to combine.
20417     * @return Returns a new integer reflecting the combination of the two
20418     * states.
20419     */
20420    public static int combineMeasuredStates(int curState, int newState) {
20421        return curState | newState;
20422    }
20423
20424    /**
20425     * Version of {@link #resolveSizeAndState(int, int, int)}
20426     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
20427     */
20428    public static int resolveSize(int size, int measureSpec) {
20429        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
20430    }
20431
20432    /**
20433     * Utility to reconcile a desired size and state, with constraints imposed
20434     * by a MeasureSpec. Will take the desired size, unless a different size
20435     * is imposed by the constraints. The returned value is a compound integer,
20436     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
20437     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
20438     * resulting size is smaller than the size the view wants to be.
20439     *
20440     * @param size How big the view wants to be.
20441     * @param measureSpec Constraints imposed by the parent.
20442     * @param childMeasuredState Size information bit mask for the view's
20443     *                           children.
20444     * @return Size information bit mask as defined by
20445     *         {@link #MEASURED_SIZE_MASK} and
20446     *         {@link #MEASURED_STATE_TOO_SMALL}.
20447     */
20448    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
20449        final int specMode = MeasureSpec.getMode(measureSpec);
20450        final int specSize = MeasureSpec.getSize(measureSpec);
20451        final int result;
20452        switch (specMode) {
20453            case MeasureSpec.AT_MOST:
20454                if (specSize < size) {
20455                    result = specSize | MEASURED_STATE_TOO_SMALL;
20456                } else {
20457                    result = size;
20458                }
20459                break;
20460            case MeasureSpec.EXACTLY:
20461                result = specSize;
20462                break;
20463            case MeasureSpec.UNSPECIFIED:
20464            default:
20465                result = size;
20466        }
20467        return result | (childMeasuredState & MEASURED_STATE_MASK);
20468    }
20469
20470    /**
20471     * Utility to return a default size. Uses the supplied size if the
20472     * MeasureSpec imposed no constraints. Will get larger if allowed
20473     * by the MeasureSpec.
20474     *
20475     * @param size Default size for this view
20476     * @param measureSpec Constraints imposed by the parent
20477     * @return The size this view should be.
20478     */
20479    public static int getDefaultSize(int size, int measureSpec) {
20480        int result = size;
20481        int specMode = MeasureSpec.getMode(measureSpec);
20482        int specSize = MeasureSpec.getSize(measureSpec);
20483
20484        switch (specMode) {
20485        case MeasureSpec.UNSPECIFIED:
20486            result = size;
20487            break;
20488        case MeasureSpec.AT_MOST:
20489        case MeasureSpec.EXACTLY:
20490            result = specSize;
20491            break;
20492        }
20493        return result;
20494    }
20495
20496    /**
20497     * Returns the suggested minimum height that the view should use. This
20498     * returns the maximum of the view's minimum height
20499     * and the background's minimum height
20500     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
20501     * <p>
20502     * When being used in {@link #onMeasure(int, int)}, the caller should still
20503     * ensure the returned height is within the requirements of the parent.
20504     *
20505     * @return The suggested minimum height of the view.
20506     */
20507    protected int getSuggestedMinimumHeight() {
20508        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
20509
20510    }
20511
20512    /**
20513     * Returns the suggested minimum width that the view should use. This
20514     * returns the maximum of the view's minimum width
20515     * and the background's minimum width
20516     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
20517     * <p>
20518     * When being used in {@link #onMeasure(int, int)}, the caller should still
20519     * ensure the returned width is within the requirements of the parent.
20520     *
20521     * @return The suggested minimum width of the view.
20522     */
20523    protected int getSuggestedMinimumWidth() {
20524        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
20525    }
20526
20527    /**
20528     * Returns the minimum height of the view.
20529     *
20530     * @return the minimum height the view will try to be, in pixels
20531     *
20532     * @see #setMinimumHeight(int)
20533     *
20534     * @attr ref android.R.styleable#View_minHeight
20535     */
20536    public int getMinimumHeight() {
20537        return mMinHeight;
20538    }
20539
20540    /**
20541     * Sets the minimum height of the view. It is not guaranteed the view will
20542     * be able to achieve this minimum height (for example, if its parent layout
20543     * constrains it with less available height).
20544     *
20545     * @param minHeight The minimum height the view will try to be, in pixels
20546     *
20547     * @see #getMinimumHeight()
20548     *
20549     * @attr ref android.R.styleable#View_minHeight
20550     */
20551    @RemotableViewMethod
20552    public void setMinimumHeight(int minHeight) {
20553        mMinHeight = minHeight;
20554        requestLayout();
20555    }
20556
20557    /**
20558     * Returns the minimum width of the view.
20559     *
20560     * @return the minimum width the view will try to be, in pixels
20561     *
20562     * @see #setMinimumWidth(int)
20563     *
20564     * @attr ref android.R.styleable#View_minWidth
20565     */
20566    public int getMinimumWidth() {
20567        return mMinWidth;
20568    }
20569
20570    /**
20571     * Sets the minimum width of the view. It is not guaranteed the view will
20572     * be able to achieve this minimum width (for example, if its parent layout
20573     * constrains it with less available width).
20574     *
20575     * @param minWidth The minimum width the view will try to be, in pixels
20576     *
20577     * @see #getMinimumWidth()
20578     *
20579     * @attr ref android.R.styleable#View_minWidth
20580     */
20581    public void setMinimumWidth(int minWidth) {
20582        mMinWidth = minWidth;
20583        requestLayout();
20584
20585    }
20586
20587    /**
20588     * Get the animation currently associated with this view.
20589     *
20590     * @return The animation that is currently playing or
20591     *         scheduled to play for this view.
20592     */
20593    public Animation getAnimation() {
20594        return mCurrentAnimation;
20595    }
20596
20597    /**
20598     * Start the specified animation now.
20599     *
20600     * @param animation the animation to start now
20601     */
20602    public void startAnimation(Animation animation) {
20603        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
20604        setAnimation(animation);
20605        invalidateParentCaches();
20606        invalidate(true);
20607    }
20608
20609    /**
20610     * Cancels any animations for this view.
20611     */
20612    public void clearAnimation() {
20613        if (mCurrentAnimation != null) {
20614            mCurrentAnimation.detach();
20615        }
20616        mCurrentAnimation = null;
20617        invalidateParentIfNeeded();
20618    }
20619
20620    /**
20621     * Sets the next animation to play for this view.
20622     * If you want the animation to play immediately, use
20623     * {@link #startAnimation(android.view.animation.Animation)} instead.
20624     * This method provides allows fine-grained
20625     * control over the start time and invalidation, but you
20626     * must make sure that 1) the animation has a start time set, and
20627     * 2) the view's parent (which controls animations on its children)
20628     * will be invalidated when the animation is supposed to
20629     * start.
20630     *
20631     * @param animation The next animation, or null.
20632     */
20633    public void setAnimation(Animation animation) {
20634        mCurrentAnimation = animation;
20635
20636        if (animation != null) {
20637            // If the screen is off assume the animation start time is now instead of
20638            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
20639            // would cause the animation to start when the screen turns back on
20640            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
20641                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
20642                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
20643            }
20644            animation.reset();
20645        }
20646    }
20647
20648    /**
20649     * Invoked by a parent ViewGroup to notify the start of the animation
20650     * currently associated with this view. If you override this method,
20651     * always call super.onAnimationStart();
20652     *
20653     * @see #setAnimation(android.view.animation.Animation)
20654     * @see #getAnimation()
20655     */
20656    @CallSuper
20657    protected void onAnimationStart() {
20658        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
20659    }
20660
20661    /**
20662     * Invoked by a parent ViewGroup to notify the end of the animation
20663     * currently associated with this view. If you override this method,
20664     * always call super.onAnimationEnd();
20665     *
20666     * @see #setAnimation(android.view.animation.Animation)
20667     * @see #getAnimation()
20668     */
20669    @CallSuper
20670    protected void onAnimationEnd() {
20671        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
20672    }
20673
20674    /**
20675     * Invoked if there is a Transform that involves alpha. Subclass that can
20676     * draw themselves with the specified alpha should return true, and then
20677     * respect that alpha when their onDraw() is called. If this returns false
20678     * then the view may be redirected to draw into an offscreen buffer to
20679     * fulfill the request, which will look fine, but may be slower than if the
20680     * subclass handles it internally. The default implementation returns false.
20681     *
20682     * @param alpha The alpha (0..255) to apply to the view's drawing
20683     * @return true if the view can draw with the specified alpha.
20684     */
20685    protected boolean onSetAlpha(int alpha) {
20686        return false;
20687    }
20688
20689    /**
20690     * This is used by the RootView to perform an optimization when
20691     * the view hierarchy contains one or several SurfaceView.
20692     * SurfaceView is always considered transparent, but its children are not,
20693     * therefore all View objects remove themselves from the global transparent
20694     * region (passed as a parameter to this function).
20695     *
20696     * @param region The transparent region for this ViewAncestor (window).
20697     *
20698     * @return Returns true if the effective visibility of the view at this
20699     * point is opaque, regardless of the transparent region; returns false
20700     * if it is possible for underlying windows to be seen behind the view.
20701     *
20702     * {@hide}
20703     */
20704    public boolean gatherTransparentRegion(Region region) {
20705        final AttachInfo attachInfo = mAttachInfo;
20706        if (region != null && attachInfo != null) {
20707            final int pflags = mPrivateFlags;
20708            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
20709                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
20710                // remove it from the transparent region.
20711                final int[] location = attachInfo.mTransparentLocation;
20712                getLocationInWindow(location);
20713                // When a view has Z value, then it will be better to leave some area below the view
20714                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
20715                // the bottom part needs more offset than the left, top and right parts due to the
20716                // spot light effects.
20717                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
20718                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
20719                        location[0] + mRight - mLeft + shadowOffset,
20720                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
20721            } else {
20722                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
20723                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
20724                    // the background drawable's non-transparent parts from this transparent region.
20725                    applyDrawableToTransparentRegion(mBackground, region);
20726                }
20727                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20728                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
20729                    // Similarly, we remove the foreground drawable's non-transparent parts.
20730                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
20731                }
20732            }
20733        }
20734        return true;
20735    }
20736
20737    /**
20738     * Play a sound effect for this view.
20739     *
20740     * <p>The framework will play sound effects for some built in actions, such as
20741     * clicking, but you may wish to play these effects in your widget,
20742     * for instance, for internal navigation.
20743     *
20744     * <p>The sound effect will only be played if sound effects are enabled by the user, and
20745     * {@link #isSoundEffectsEnabled()} is true.
20746     *
20747     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
20748     */
20749    public void playSoundEffect(int soundConstant) {
20750        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
20751            return;
20752        }
20753        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
20754    }
20755
20756    /**
20757     * BZZZTT!!1!
20758     *
20759     * <p>Provide haptic feedback to the user for this view.
20760     *
20761     * <p>The framework will provide haptic feedback for some built in actions,
20762     * such as long presses, but you may wish to provide feedback for your
20763     * own widget.
20764     *
20765     * <p>The feedback will only be performed if
20766     * {@link #isHapticFeedbackEnabled()} is true.
20767     *
20768     * @param feedbackConstant One of the constants defined in
20769     * {@link HapticFeedbackConstants}
20770     */
20771    public boolean performHapticFeedback(int feedbackConstant) {
20772        return performHapticFeedback(feedbackConstant, 0);
20773    }
20774
20775    /**
20776     * BZZZTT!!1!
20777     *
20778     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
20779     *
20780     * @param feedbackConstant One of the constants defined in
20781     * {@link HapticFeedbackConstants}
20782     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
20783     */
20784    public boolean performHapticFeedback(int feedbackConstant, int flags) {
20785        if (mAttachInfo == null) {
20786            return false;
20787        }
20788        //noinspection SimplifiableIfStatement
20789        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
20790                && !isHapticFeedbackEnabled()) {
20791            return false;
20792        }
20793        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
20794                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
20795    }
20796
20797    /**
20798     * Request that the visibility of the status bar or other screen/window
20799     * decorations be changed.
20800     *
20801     * <p>This method is used to put the over device UI into temporary modes
20802     * where the user's attention is focused more on the application content,
20803     * by dimming or hiding surrounding system affordances.  This is typically
20804     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
20805     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
20806     * to be placed behind the action bar (and with these flags other system
20807     * affordances) so that smooth transitions between hiding and showing them
20808     * can be done.
20809     *
20810     * <p>Two representative examples of the use of system UI visibility is
20811     * implementing a content browsing application (like a magazine reader)
20812     * and a video playing application.
20813     *
20814     * <p>The first code shows a typical implementation of a View in a content
20815     * browsing application.  In this implementation, the application goes
20816     * into a content-oriented mode by hiding the status bar and action bar,
20817     * and putting the navigation elements into lights out mode.  The user can
20818     * then interact with content while in this mode.  Such an application should
20819     * provide an easy way for the user to toggle out of the mode (such as to
20820     * check information in the status bar or access notifications).  In the
20821     * implementation here, this is done simply by tapping on the content.
20822     *
20823     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
20824     *      content}
20825     *
20826     * <p>This second code sample shows a typical implementation of a View
20827     * in a video playing application.  In this situation, while the video is
20828     * playing the application would like to go into a complete full-screen mode,
20829     * to use as much of the display as possible for the video.  When in this state
20830     * the user can not interact with the application; the system intercepts
20831     * touching on the screen to pop the UI out of full screen mode.  See
20832     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
20833     *
20834     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
20835     *      content}
20836     *
20837     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20838     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20839     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20840     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20841     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20842     */
20843    public void setSystemUiVisibility(int visibility) {
20844        if (visibility != mSystemUiVisibility) {
20845            mSystemUiVisibility = visibility;
20846            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20847                mParent.recomputeViewAttributes(this);
20848            }
20849        }
20850    }
20851
20852    /**
20853     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
20854     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20855     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
20856     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
20857     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
20858     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
20859     */
20860    public int getSystemUiVisibility() {
20861        return mSystemUiVisibility;
20862    }
20863
20864    /**
20865     * Returns the current system UI visibility that is currently set for
20866     * the entire window.  This is the combination of the
20867     * {@link #setSystemUiVisibility(int)} values supplied by all of the
20868     * views in the window.
20869     */
20870    public int getWindowSystemUiVisibility() {
20871        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
20872    }
20873
20874    /**
20875     * Override to find out when the window's requested system UI visibility
20876     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
20877     * This is different from the callbacks received through
20878     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
20879     * in that this is only telling you about the local request of the window,
20880     * not the actual values applied by the system.
20881     */
20882    public void onWindowSystemUiVisibilityChanged(int visible) {
20883    }
20884
20885    /**
20886     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
20887     * the view hierarchy.
20888     */
20889    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
20890        onWindowSystemUiVisibilityChanged(visible);
20891    }
20892
20893    /**
20894     * Set a listener to receive callbacks when the visibility of the system bar changes.
20895     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
20896     */
20897    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
20898        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
20899        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
20900            mParent.recomputeViewAttributes(this);
20901        }
20902    }
20903
20904    /**
20905     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
20906     * the view hierarchy.
20907     */
20908    public void dispatchSystemUiVisibilityChanged(int visibility) {
20909        ListenerInfo li = mListenerInfo;
20910        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
20911            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
20912                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
20913        }
20914    }
20915
20916    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
20917        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
20918        if (val != mSystemUiVisibility) {
20919            setSystemUiVisibility(val);
20920            return true;
20921        }
20922        return false;
20923    }
20924
20925    /** @hide */
20926    public void setDisabledSystemUiVisibility(int flags) {
20927        if (mAttachInfo != null) {
20928            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
20929                mAttachInfo.mDisabledSystemUiVisibility = flags;
20930                if (mParent != null) {
20931                    mParent.recomputeViewAttributes(this);
20932                }
20933            }
20934        }
20935    }
20936
20937    /**
20938     * Creates an image that the system displays during the drag and drop
20939     * operation. This is called a &quot;drag shadow&quot;. The default implementation
20940     * for a DragShadowBuilder based on a View returns an image that has exactly the same
20941     * appearance as the given View. The default also positions the center of the drag shadow
20942     * directly under the touch point. If no View is provided (the constructor with no parameters
20943     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
20944     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
20945     * default is an invisible drag shadow.
20946     * <p>
20947     * You are not required to use the View you provide to the constructor as the basis of the
20948     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
20949     * anything you want as the drag shadow.
20950     * </p>
20951     * <p>
20952     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
20953     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
20954     *  size and position of the drag shadow. It uses this data to construct a
20955     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
20956     *  so that your application can draw the shadow image in the Canvas.
20957     * </p>
20958     *
20959     * <div class="special reference">
20960     * <h3>Developer Guides</h3>
20961     * <p>For a guide to implementing drag and drop features, read the
20962     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20963     * </div>
20964     */
20965    public static class DragShadowBuilder {
20966        private final WeakReference<View> mView;
20967
20968        /**
20969         * Constructs a shadow image builder based on a View. By default, the resulting drag
20970         * shadow will have the same appearance and dimensions as the View, with the touch point
20971         * over the center of the View.
20972         * @param view A View. Any View in scope can be used.
20973         */
20974        public DragShadowBuilder(View view) {
20975            mView = new WeakReference<View>(view);
20976        }
20977
20978        /**
20979         * Construct a shadow builder object with no associated View.  This
20980         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
20981         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
20982         * to supply the drag shadow's dimensions and appearance without
20983         * reference to any View object. If they are not overridden, then the result is an
20984         * invisible drag shadow.
20985         */
20986        public DragShadowBuilder() {
20987            mView = new WeakReference<View>(null);
20988        }
20989
20990        /**
20991         * Returns the View object that had been passed to the
20992         * {@link #View.DragShadowBuilder(View)}
20993         * constructor.  If that View parameter was {@code null} or if the
20994         * {@link #View.DragShadowBuilder()}
20995         * constructor was used to instantiate the builder object, this method will return
20996         * null.
20997         *
20998         * @return The View object associate with this builder object.
20999         */
21000        @SuppressWarnings({"JavadocReference"})
21001        final public View getView() {
21002            return mView.get();
21003        }
21004
21005        /**
21006         * Provides the metrics for the shadow image. These include the dimensions of
21007         * the shadow image, and the point within that shadow that should
21008         * be centered under the touch location while dragging.
21009         * <p>
21010         * The default implementation sets the dimensions of the shadow to be the
21011         * same as the dimensions of the View itself and centers the shadow under
21012         * the touch point.
21013         * </p>
21014         *
21015         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
21016         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
21017         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
21018         * image.
21019         *
21020         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
21021         * shadow image that should be underneath the touch point during the drag and drop
21022         * operation. Your application must set {@link android.graphics.Point#x} to the
21023         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
21024         */
21025        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
21026            final View view = mView.get();
21027            if (view != null) {
21028                outShadowSize.set(view.getWidth(), view.getHeight());
21029                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
21030            } else {
21031                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
21032            }
21033        }
21034
21035        /**
21036         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
21037         * based on the dimensions it received from the
21038         * {@link #onProvideShadowMetrics(Point, Point)} callback.
21039         *
21040         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
21041         */
21042        public void onDrawShadow(Canvas canvas) {
21043            final View view = mView.get();
21044            if (view != null) {
21045                view.draw(canvas);
21046            } else {
21047                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
21048            }
21049        }
21050    }
21051
21052    /**
21053     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
21054     * startDragAndDrop()} for newer platform versions.
21055     */
21056    @Deprecated
21057    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
21058                                   Object myLocalState, int flags) {
21059        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
21060    }
21061
21062    /**
21063     * Starts a drag and drop operation. When your application calls this method, it passes a
21064     * {@link android.view.View.DragShadowBuilder} object to the system. The
21065     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
21066     * to get metrics for the drag shadow, and then calls the object's
21067     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
21068     * <p>
21069     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
21070     *  drag events to all the View objects in your application that are currently visible. It does
21071     *  this either by calling the View object's drag listener (an implementation of
21072     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
21073     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
21074     *  Both are passed a {@link android.view.DragEvent} object that has a
21075     *  {@link android.view.DragEvent#getAction()} value of
21076     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
21077     * </p>
21078     * <p>
21079     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
21080     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
21081     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
21082     * to the View the user selected for dragging.
21083     * </p>
21084     * @param data A {@link android.content.ClipData} object pointing to the data to be
21085     * transferred by the drag and drop operation.
21086     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
21087     * drag shadow.
21088     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
21089     * drop operation. When dispatching drag events to views in the same activity this object
21090     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
21091     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
21092     * will return null).
21093     * <p>
21094     * myLocalState is a lightweight mechanism for the sending information from the dragged View
21095     * to the target Views. For example, it can contain flags that differentiate between a
21096     * a copy operation and a move operation.
21097     * </p>
21098     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
21099     * flags, or any combination of the following:
21100     *     <ul>
21101     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
21102     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
21103     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
21104     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
21105     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
21106     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
21107     *     </ul>
21108     * @return {@code true} if the method completes successfully, or
21109     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
21110     * do a drag, and so no drag operation is in progress.
21111     */
21112    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
21113            Object myLocalState, int flags) {
21114        if (ViewDebug.DEBUG_DRAG) {
21115            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
21116        }
21117        if (mAttachInfo == null) {
21118            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
21119            return false;
21120        }
21121
21122        if (data != null) {
21123            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
21124        }
21125
21126        boolean okay = false;
21127
21128        Point shadowSize = new Point();
21129        Point shadowTouchPoint = new Point();
21130        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
21131
21132        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
21133                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
21134            throw new IllegalStateException("Drag shadow dimensions must not be negative");
21135        }
21136
21137        if (ViewDebug.DEBUG_DRAG) {
21138            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
21139                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
21140        }
21141        if (mAttachInfo.mDragSurface != null) {
21142            mAttachInfo.mDragSurface.release();
21143        }
21144        mAttachInfo.mDragSurface = new Surface();
21145        try {
21146            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
21147                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
21148            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
21149                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
21150            if (mAttachInfo.mDragToken != null) {
21151                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
21152                try {
21153                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
21154                    shadowBuilder.onDrawShadow(canvas);
21155                } finally {
21156                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
21157                }
21158
21159                final ViewRootImpl root = getViewRootImpl();
21160
21161                // Cache the local state object for delivery with DragEvents
21162                root.setLocalDragState(myLocalState);
21163
21164                // repurpose 'shadowSize' for the last touch point
21165                root.getLastTouchPoint(shadowSize);
21166
21167                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
21168                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
21169                        shadowTouchPoint.x, shadowTouchPoint.y, data);
21170                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
21171            }
21172        } catch (Exception e) {
21173            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
21174            mAttachInfo.mDragSurface.destroy();
21175            mAttachInfo.mDragSurface = null;
21176        }
21177
21178        return okay;
21179    }
21180
21181    /**
21182     * Cancels an ongoing drag and drop operation.
21183     * <p>
21184     * A {@link android.view.DragEvent} object with
21185     * {@link android.view.DragEvent#getAction()} value of
21186     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
21187     * {@link android.view.DragEvent#getResult()} value of {@code false}
21188     * will be sent to every
21189     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
21190     * even if they are not currently visible.
21191     * </p>
21192     * <p>
21193     * This method can be called on any View in the same window as the View on which
21194     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
21195     * was called.
21196     * </p>
21197     */
21198    public final void cancelDragAndDrop() {
21199        if (ViewDebug.DEBUG_DRAG) {
21200            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
21201        }
21202        if (mAttachInfo == null) {
21203            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
21204            return;
21205        }
21206        if (mAttachInfo.mDragToken != null) {
21207            try {
21208                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
21209            } catch (Exception e) {
21210                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
21211            }
21212            mAttachInfo.mDragToken = null;
21213        } else {
21214            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
21215        }
21216    }
21217
21218    /**
21219     * Updates the drag shadow for the ongoing drag and drop operation.
21220     *
21221     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
21222     * new drag shadow.
21223     */
21224    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
21225        if (ViewDebug.DEBUG_DRAG) {
21226            Log.d(VIEW_LOG_TAG, "updateDragShadow");
21227        }
21228        if (mAttachInfo == null) {
21229            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
21230            return;
21231        }
21232        if (mAttachInfo.mDragToken != null) {
21233            try {
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            } catch (Exception e) {
21242                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
21243            }
21244        } else {
21245            Log.e(VIEW_LOG_TAG, "No active drag");
21246        }
21247    }
21248
21249    /**
21250     * Starts a move from {startX, startY}, the amount of the movement will be the offset
21251     * between {startX, startY} and the new cursor positon.
21252     * @param startX horizontal coordinate where the move started.
21253     * @param startY vertical coordinate where the move started.
21254     * @return whether moving was started successfully.
21255     * @hide
21256     */
21257    public final boolean startMovingTask(float startX, float startY) {
21258        if (ViewDebug.DEBUG_POSITIONING) {
21259            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
21260        }
21261        try {
21262            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
21263        } catch (RemoteException e) {
21264            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
21265        }
21266        return false;
21267    }
21268
21269    /**
21270     * Handles drag events sent by the system following a call to
21271     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
21272     * startDragAndDrop()}.
21273     *<p>
21274     * When the system calls this method, it passes a
21275     * {@link android.view.DragEvent} object. A call to
21276     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
21277     * in DragEvent. The method uses these to determine what is happening in the drag and drop
21278     * operation.
21279     * @param event The {@link android.view.DragEvent} sent by the system.
21280     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
21281     * in DragEvent, indicating the type of drag event represented by this object.
21282     * @return {@code true} if the method was successful, otherwise {@code false}.
21283     * <p>
21284     *  The method should return {@code true} in response to an action type of
21285     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
21286     *  operation.
21287     * </p>
21288     * <p>
21289     *  The method should also return {@code true} in response to an action type of
21290     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
21291     *  {@code false} if it didn't.
21292     * </p>
21293     * <p>
21294     *  For all other events, the return value is ignored.
21295     * </p>
21296     */
21297    public boolean onDragEvent(DragEvent event) {
21298        return false;
21299    }
21300
21301    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
21302    boolean dispatchDragEnterExitInPreN(DragEvent event) {
21303        return callDragEventHandler(event);
21304    }
21305
21306    /**
21307     * Detects if this View is enabled and has a drag event listener.
21308     * If both are true, then it calls the drag event listener with the
21309     * {@link android.view.DragEvent} it received. If the drag event listener returns
21310     * {@code true}, then dispatchDragEvent() returns {@code true}.
21311     * <p>
21312     * For all other cases, the method calls the
21313     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
21314     * method and returns its result.
21315     * </p>
21316     * <p>
21317     * This ensures that a drag event is always consumed, even if the View does not have a drag
21318     * event listener. However, if the View has a listener and the listener returns true, then
21319     * onDragEvent() is not called.
21320     * </p>
21321     */
21322    public boolean dispatchDragEvent(DragEvent event) {
21323        event.mEventHandlerWasCalled = true;
21324        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
21325            event.mAction == DragEvent.ACTION_DROP) {
21326            // About to deliver an event with coordinates to this view. Notify that now this view
21327            // has drag focus. This will send exit/enter events as needed.
21328            getViewRootImpl().setDragFocus(this, event);
21329        }
21330        return callDragEventHandler(event);
21331    }
21332
21333    final boolean callDragEventHandler(DragEvent event) {
21334        final boolean result;
21335
21336        ListenerInfo li = mListenerInfo;
21337        //noinspection SimplifiableIfStatement
21338        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
21339                && li.mOnDragListener.onDrag(this, event)) {
21340            result = true;
21341        } else {
21342            result = onDragEvent(event);
21343        }
21344
21345        switch (event.mAction) {
21346            case DragEvent.ACTION_DRAG_ENTERED: {
21347                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
21348                refreshDrawableState();
21349            } break;
21350            case DragEvent.ACTION_DRAG_EXITED: {
21351                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
21352                refreshDrawableState();
21353            } break;
21354            case DragEvent.ACTION_DRAG_ENDED: {
21355                mPrivateFlags2 &= ~View.DRAG_MASK;
21356                refreshDrawableState();
21357            } break;
21358        }
21359
21360        return result;
21361    }
21362
21363    boolean canAcceptDrag() {
21364        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
21365    }
21366
21367    /**
21368     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
21369     * it is ever exposed at all.
21370     * @hide
21371     */
21372    public void onCloseSystemDialogs(String reason) {
21373    }
21374
21375    /**
21376     * Given a Drawable whose bounds have been set to draw into this view,
21377     * update a Region being computed for
21378     * {@link #gatherTransparentRegion(android.graphics.Region)} so
21379     * that any non-transparent parts of the Drawable are removed from the
21380     * given transparent region.
21381     *
21382     * @param dr The Drawable whose transparency is to be applied to the region.
21383     * @param region A Region holding the current transparency information,
21384     * where any parts of the region that are set are considered to be
21385     * transparent.  On return, this region will be modified to have the
21386     * transparency information reduced by the corresponding parts of the
21387     * Drawable that are not transparent.
21388     * {@hide}
21389     */
21390    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
21391        if (DBG) {
21392            Log.i("View", "Getting transparent region for: " + this);
21393        }
21394        final Region r = dr.getTransparentRegion();
21395        final Rect db = dr.getBounds();
21396        final AttachInfo attachInfo = mAttachInfo;
21397        if (r != null && attachInfo != null) {
21398            final int w = getRight()-getLeft();
21399            final int h = getBottom()-getTop();
21400            if (db.left > 0) {
21401                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
21402                r.op(0, 0, db.left, h, Region.Op.UNION);
21403            }
21404            if (db.right < w) {
21405                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
21406                r.op(db.right, 0, w, h, Region.Op.UNION);
21407            }
21408            if (db.top > 0) {
21409                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
21410                r.op(0, 0, w, db.top, Region.Op.UNION);
21411            }
21412            if (db.bottom < h) {
21413                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
21414                r.op(0, db.bottom, w, h, Region.Op.UNION);
21415            }
21416            final int[] location = attachInfo.mTransparentLocation;
21417            getLocationInWindow(location);
21418            r.translate(location[0], location[1]);
21419            region.op(r, Region.Op.INTERSECT);
21420        } else {
21421            region.op(db, Region.Op.DIFFERENCE);
21422        }
21423    }
21424
21425    private void checkForLongClick(int delayOffset, float x, float y) {
21426        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
21427            mHasPerformedLongPress = false;
21428
21429            if (mPendingCheckForLongPress == null) {
21430                mPendingCheckForLongPress = new CheckForLongPress();
21431            }
21432            mPendingCheckForLongPress.setAnchor(x, y);
21433            mPendingCheckForLongPress.rememberWindowAttachCount();
21434            mPendingCheckForLongPress.rememberPressedState();
21435            postDelayed(mPendingCheckForLongPress,
21436                    ViewConfiguration.getLongPressTimeout() - delayOffset);
21437        }
21438    }
21439
21440    /**
21441     * Inflate a view from an XML resource.  This convenience method wraps the {@link
21442     * LayoutInflater} class, which provides a full range of options for view inflation.
21443     *
21444     * @param context The Context object for your activity or application.
21445     * @param resource The resource ID to inflate
21446     * @param root A view group that will be the parent.  Used to properly inflate the
21447     * layout_* parameters.
21448     * @see LayoutInflater
21449     */
21450    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
21451        LayoutInflater factory = LayoutInflater.from(context);
21452        return factory.inflate(resource, root);
21453    }
21454
21455    /**
21456     * Scroll the view with standard behavior for scrolling beyond the normal
21457     * content boundaries. Views that call this method should override
21458     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
21459     * results of an over-scroll operation.
21460     *
21461     * Views can use this method to handle any touch or fling-based scrolling.
21462     *
21463     * @param deltaX Change in X in pixels
21464     * @param deltaY Change in Y in pixels
21465     * @param scrollX Current X scroll value in pixels before applying deltaX
21466     * @param scrollY Current Y scroll value in pixels before applying deltaY
21467     * @param scrollRangeX Maximum content scroll range along the X axis
21468     * @param scrollRangeY Maximum content scroll range along the Y axis
21469     * @param maxOverScrollX Number of pixels to overscroll by in either direction
21470     *          along the X axis.
21471     * @param maxOverScrollY Number of pixels to overscroll by in either direction
21472     *          along the Y axis.
21473     * @param isTouchEvent true if this scroll operation is the result of a touch event.
21474     * @return true if scrolling was clamped to an over-scroll boundary along either
21475     *          axis, false otherwise.
21476     */
21477    @SuppressWarnings({"UnusedParameters"})
21478    protected boolean overScrollBy(int deltaX, int deltaY,
21479            int scrollX, int scrollY,
21480            int scrollRangeX, int scrollRangeY,
21481            int maxOverScrollX, int maxOverScrollY,
21482            boolean isTouchEvent) {
21483        final int overScrollMode = mOverScrollMode;
21484        final boolean canScrollHorizontal =
21485                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
21486        final boolean canScrollVertical =
21487                computeVerticalScrollRange() > computeVerticalScrollExtent();
21488        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
21489                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
21490        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
21491                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
21492
21493        int newScrollX = scrollX + deltaX;
21494        if (!overScrollHorizontal) {
21495            maxOverScrollX = 0;
21496        }
21497
21498        int newScrollY = scrollY + deltaY;
21499        if (!overScrollVertical) {
21500            maxOverScrollY = 0;
21501        }
21502
21503        // Clamp values if at the limits and record
21504        final int left = -maxOverScrollX;
21505        final int right = maxOverScrollX + scrollRangeX;
21506        final int top = -maxOverScrollY;
21507        final int bottom = maxOverScrollY + scrollRangeY;
21508
21509        boolean clampedX = false;
21510        if (newScrollX > right) {
21511            newScrollX = right;
21512            clampedX = true;
21513        } else if (newScrollX < left) {
21514            newScrollX = left;
21515            clampedX = true;
21516        }
21517
21518        boolean clampedY = false;
21519        if (newScrollY > bottom) {
21520            newScrollY = bottom;
21521            clampedY = true;
21522        } else if (newScrollY < top) {
21523            newScrollY = top;
21524            clampedY = true;
21525        }
21526
21527        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
21528
21529        return clampedX || clampedY;
21530    }
21531
21532    /**
21533     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
21534     * respond to the results of an over-scroll operation.
21535     *
21536     * @param scrollX New X scroll value in pixels
21537     * @param scrollY New Y scroll value in pixels
21538     * @param clampedX True if scrollX was clamped to an over-scroll boundary
21539     * @param clampedY True if scrollY was clamped to an over-scroll boundary
21540     */
21541    protected void onOverScrolled(int scrollX, int scrollY,
21542            boolean clampedX, boolean clampedY) {
21543        // Intentionally empty.
21544    }
21545
21546    /**
21547     * Returns the over-scroll mode for this view. The result will be
21548     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21549     * (allow over-scrolling only if the view content is larger than the container),
21550     * or {@link #OVER_SCROLL_NEVER}.
21551     *
21552     * @return This view's over-scroll mode.
21553     */
21554    public int getOverScrollMode() {
21555        return mOverScrollMode;
21556    }
21557
21558    /**
21559     * Set the over-scroll mode for this view. Valid over-scroll modes are
21560     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21561     * (allow over-scrolling only if the view content is larger than the container),
21562     * or {@link #OVER_SCROLL_NEVER}.
21563     *
21564     * Setting the over-scroll mode of a view will have an effect only if the
21565     * view is capable of scrolling.
21566     *
21567     * @param overScrollMode The new over-scroll mode for this view.
21568     */
21569    public void setOverScrollMode(int overScrollMode) {
21570        if (overScrollMode != OVER_SCROLL_ALWAYS &&
21571                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
21572                overScrollMode != OVER_SCROLL_NEVER) {
21573            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
21574        }
21575        mOverScrollMode = overScrollMode;
21576    }
21577
21578    /**
21579     * Enable or disable nested scrolling for this view.
21580     *
21581     * <p>If this property is set to true the view will be permitted to initiate nested
21582     * scrolling operations with a compatible parent view in the current hierarchy. If this
21583     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
21584     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
21585     * the nested scroll.</p>
21586     *
21587     * @param enabled true to enable nested scrolling, false to disable
21588     *
21589     * @see #isNestedScrollingEnabled()
21590     */
21591    public void setNestedScrollingEnabled(boolean enabled) {
21592        if (enabled) {
21593            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
21594        } else {
21595            stopNestedScroll();
21596            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
21597        }
21598    }
21599
21600    /**
21601     * Returns true if nested scrolling is enabled for this view.
21602     *
21603     * <p>If nested scrolling is enabled and this View class implementation supports it,
21604     * this view will act as a nested scrolling child view when applicable, forwarding data
21605     * about the scroll operation in progress to a compatible and cooperating nested scrolling
21606     * parent.</p>
21607     *
21608     * @return true if nested scrolling is enabled
21609     *
21610     * @see #setNestedScrollingEnabled(boolean)
21611     */
21612    public boolean isNestedScrollingEnabled() {
21613        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
21614                PFLAG3_NESTED_SCROLLING_ENABLED;
21615    }
21616
21617    /**
21618     * Begin a nestable scroll operation along the given axes.
21619     *
21620     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
21621     *
21622     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
21623     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
21624     * In the case of touch scrolling the nested scroll will be terminated automatically in
21625     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
21626     * In the event of programmatic scrolling the caller must explicitly call
21627     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
21628     *
21629     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
21630     * If it returns false the caller may ignore the rest of this contract until the next scroll.
21631     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
21632     *
21633     * <p>At each incremental step of the scroll the caller should invoke
21634     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
21635     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
21636     * parent at least partially consumed the scroll and the caller should adjust the amount it
21637     * scrolls by.</p>
21638     *
21639     * <p>After applying the remainder of the scroll delta the caller should invoke
21640     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
21641     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
21642     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
21643     * </p>
21644     *
21645     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
21646     *             {@link #SCROLL_AXIS_VERTICAL}.
21647     * @return true if a cooperative parent was found and nested scrolling has been enabled for
21648     *         the current gesture.
21649     *
21650     * @see #stopNestedScroll()
21651     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21652     * @see #dispatchNestedScroll(int, int, int, int, int[])
21653     */
21654    public boolean startNestedScroll(int axes) {
21655        if (hasNestedScrollingParent()) {
21656            // Already in progress
21657            return true;
21658        }
21659        if (isNestedScrollingEnabled()) {
21660            ViewParent p = getParent();
21661            View child = this;
21662            while (p != null) {
21663                try {
21664                    if (p.onStartNestedScroll(child, this, axes)) {
21665                        mNestedScrollingParent = p;
21666                        p.onNestedScrollAccepted(child, this, axes);
21667                        return true;
21668                    }
21669                } catch (AbstractMethodError e) {
21670                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
21671                            "method onStartNestedScroll", e);
21672                    // Allow the search upward to continue
21673                }
21674                if (p instanceof View) {
21675                    child = (View) p;
21676                }
21677                p = p.getParent();
21678            }
21679        }
21680        return false;
21681    }
21682
21683    /**
21684     * Stop a nested scroll in progress.
21685     *
21686     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
21687     *
21688     * @see #startNestedScroll(int)
21689     */
21690    public void stopNestedScroll() {
21691        if (mNestedScrollingParent != null) {
21692            mNestedScrollingParent.onStopNestedScroll(this);
21693            mNestedScrollingParent = null;
21694        }
21695    }
21696
21697    /**
21698     * Returns true if this view has a nested scrolling parent.
21699     *
21700     * <p>The presence of a nested scrolling parent indicates that this view has initiated
21701     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
21702     *
21703     * @return whether this view has a nested scrolling parent
21704     */
21705    public boolean hasNestedScrollingParent() {
21706        return mNestedScrollingParent != null;
21707    }
21708
21709    /**
21710     * Dispatch one step of a nested scroll in progress.
21711     *
21712     * <p>Implementations of views that support nested scrolling should call this to report
21713     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
21714     * is not currently in progress or nested scrolling is not
21715     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
21716     *
21717     * <p>Compatible View implementations should also call
21718     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
21719     * consuming a component of the scroll event themselves.</p>
21720     *
21721     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
21722     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
21723     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
21724     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
21725     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21726     *                       in local view coordinates of this view from before this operation
21727     *                       to after it completes. View implementations may use this to adjust
21728     *                       expected input coordinate tracking.
21729     * @return true if the event was dispatched, false if it could not be dispatched.
21730     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21731     */
21732    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
21733            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
21734        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21735            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
21736                int startX = 0;
21737                int startY = 0;
21738                if (offsetInWindow != null) {
21739                    getLocationInWindow(offsetInWindow);
21740                    startX = offsetInWindow[0];
21741                    startY = offsetInWindow[1];
21742                }
21743
21744                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
21745                        dxUnconsumed, dyUnconsumed);
21746
21747                if (offsetInWindow != null) {
21748                    getLocationInWindow(offsetInWindow);
21749                    offsetInWindow[0] -= startX;
21750                    offsetInWindow[1] -= startY;
21751                }
21752                return true;
21753            } else if (offsetInWindow != null) {
21754                // No motion, no dispatch. Keep offsetInWindow up to date.
21755                offsetInWindow[0] = 0;
21756                offsetInWindow[1] = 0;
21757            }
21758        }
21759        return false;
21760    }
21761
21762    /**
21763     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
21764     *
21765     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
21766     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
21767     * scrolling operation to consume some or all of the scroll operation before the child view
21768     * consumes it.</p>
21769     *
21770     * @param dx Horizontal scroll distance in pixels
21771     * @param dy Vertical scroll distance in pixels
21772     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
21773     *                 and consumed[1] the consumed dy.
21774     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21775     *                       in local view coordinates of this view from before this operation
21776     *                       to after it completes. View implementations may use this to adjust
21777     *                       expected input coordinate tracking.
21778     * @return true if the parent consumed some or all of the scroll delta
21779     * @see #dispatchNestedScroll(int, int, int, int, int[])
21780     */
21781    public boolean dispatchNestedPreScroll(int dx, int dy,
21782            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
21783        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21784            if (dx != 0 || dy != 0) {
21785                int startX = 0;
21786                int startY = 0;
21787                if (offsetInWindow != null) {
21788                    getLocationInWindow(offsetInWindow);
21789                    startX = offsetInWindow[0];
21790                    startY = offsetInWindow[1];
21791                }
21792
21793                if (consumed == null) {
21794                    if (mTempNestedScrollConsumed == null) {
21795                        mTempNestedScrollConsumed = new int[2];
21796                    }
21797                    consumed = mTempNestedScrollConsumed;
21798                }
21799                consumed[0] = 0;
21800                consumed[1] = 0;
21801                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
21802
21803                if (offsetInWindow != null) {
21804                    getLocationInWindow(offsetInWindow);
21805                    offsetInWindow[0] -= startX;
21806                    offsetInWindow[1] -= startY;
21807                }
21808                return consumed[0] != 0 || consumed[1] != 0;
21809            } else if (offsetInWindow != null) {
21810                offsetInWindow[0] = 0;
21811                offsetInWindow[1] = 0;
21812            }
21813        }
21814        return false;
21815    }
21816
21817    /**
21818     * Dispatch a fling to a nested scrolling parent.
21819     *
21820     * <p>This method should be used to indicate that a nested scrolling child has detected
21821     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
21822     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
21823     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
21824     * along a scrollable axis.</p>
21825     *
21826     * <p>If a nested scrolling child view would normally fling but it is at the edge of
21827     * its own content, it can use this method to delegate the fling to its nested scrolling
21828     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
21829     *
21830     * @param velocityX Horizontal fling velocity in pixels per second
21831     * @param velocityY Vertical fling velocity in pixels per second
21832     * @param consumed true if the child consumed the fling, false otherwise
21833     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
21834     */
21835    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
21836        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21837            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
21838        }
21839        return false;
21840    }
21841
21842    /**
21843     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
21844     *
21845     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
21846     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
21847     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
21848     * before the child view consumes it. If this method returns <code>true</code>, a nested
21849     * parent view consumed the fling and this view should not scroll as a result.</p>
21850     *
21851     * <p>For a better user experience, only one view in a nested scrolling chain should consume
21852     * the fling at a time. If a parent view consumed the fling this method will return false.
21853     * Custom view implementations should account for this in two ways:</p>
21854     *
21855     * <ul>
21856     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
21857     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
21858     *     position regardless.</li>
21859     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
21860     *     even to settle back to a valid idle position.</li>
21861     * </ul>
21862     *
21863     * <p>Views should also not offer fling velocities to nested parent views along an axis
21864     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
21865     * should not offer a horizontal fling velocity to its parents since scrolling along that
21866     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
21867     *
21868     * @param velocityX Horizontal fling velocity in pixels per second
21869     * @param velocityY Vertical fling velocity in pixels per second
21870     * @return true if a nested scrolling parent consumed the fling
21871     */
21872    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
21873        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21874            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
21875        }
21876        return false;
21877    }
21878
21879    /**
21880     * Gets a scale factor that determines the distance the view should scroll
21881     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
21882     * @return The vertical scroll scale factor.
21883     * @hide
21884     */
21885    protected float getVerticalScrollFactor() {
21886        if (mVerticalScrollFactor == 0) {
21887            TypedValue outValue = new TypedValue();
21888            if (!mContext.getTheme().resolveAttribute(
21889                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
21890                throw new IllegalStateException(
21891                        "Expected theme to define listPreferredItemHeight.");
21892            }
21893            mVerticalScrollFactor = outValue.getDimension(
21894                    mContext.getResources().getDisplayMetrics());
21895        }
21896        return mVerticalScrollFactor;
21897    }
21898
21899    /**
21900     * Gets a scale factor that determines the distance the view should scroll
21901     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
21902     * @return The horizontal scroll scale factor.
21903     * @hide
21904     */
21905    protected float getHorizontalScrollFactor() {
21906        // TODO: Should use something else.
21907        return getVerticalScrollFactor();
21908    }
21909
21910    /**
21911     * Return the value specifying the text direction or policy that was set with
21912     * {@link #setTextDirection(int)}.
21913     *
21914     * @return the defined text direction. It can be one of:
21915     *
21916     * {@link #TEXT_DIRECTION_INHERIT},
21917     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21918     * {@link #TEXT_DIRECTION_ANY_RTL},
21919     * {@link #TEXT_DIRECTION_LTR},
21920     * {@link #TEXT_DIRECTION_RTL},
21921     * {@link #TEXT_DIRECTION_LOCALE},
21922     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21923     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21924     *
21925     * @attr ref android.R.styleable#View_textDirection
21926     *
21927     * @hide
21928     */
21929    @ViewDebug.ExportedProperty(category = "text", mapping = {
21930            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21931            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21932            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21933            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
21934            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
21935            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
21936            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
21937            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
21938    })
21939    public int getRawTextDirection() {
21940        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
21941    }
21942
21943    /**
21944     * Set the text direction.
21945     *
21946     * @param textDirection the direction to set. Should be one of:
21947     *
21948     * {@link #TEXT_DIRECTION_INHERIT},
21949     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21950     * {@link #TEXT_DIRECTION_ANY_RTL},
21951     * {@link #TEXT_DIRECTION_LTR},
21952     * {@link #TEXT_DIRECTION_RTL},
21953     * {@link #TEXT_DIRECTION_LOCALE}
21954     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21955     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
21956     *
21957     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
21958     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
21959     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
21960     *
21961     * @attr ref android.R.styleable#View_textDirection
21962     */
21963    public void setTextDirection(int textDirection) {
21964        if (getRawTextDirection() != textDirection) {
21965            // Reset the current text direction and the resolved one
21966            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
21967            resetResolvedTextDirection();
21968            // Set the new text direction
21969            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
21970            // Do resolution
21971            resolveTextDirection();
21972            // Notify change
21973            onRtlPropertiesChanged(getLayoutDirection());
21974            // Refresh
21975            requestLayout();
21976            invalidate(true);
21977        }
21978    }
21979
21980    /**
21981     * Return the resolved text direction.
21982     *
21983     * @return the resolved text direction. Returns one of:
21984     *
21985     * {@link #TEXT_DIRECTION_FIRST_STRONG},
21986     * {@link #TEXT_DIRECTION_ANY_RTL},
21987     * {@link #TEXT_DIRECTION_LTR},
21988     * {@link #TEXT_DIRECTION_RTL},
21989     * {@link #TEXT_DIRECTION_LOCALE},
21990     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
21991     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
21992     *
21993     * @attr ref android.R.styleable#View_textDirection
21994     */
21995    @ViewDebug.ExportedProperty(category = "text", mapping = {
21996            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
21997            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
21998            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
21999            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
22000            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
22001            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
22002            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
22003            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
22004    })
22005    public int getTextDirection() {
22006        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
22007    }
22008
22009    /**
22010     * Resolve the text direction.
22011     *
22012     * @return true if resolution has been done, false otherwise.
22013     *
22014     * @hide
22015     */
22016    public boolean resolveTextDirection() {
22017        // Reset any previous text direction resolution
22018        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
22019
22020        if (hasRtlSupport()) {
22021            // Set resolved text direction flag depending on text direction flag
22022            final int textDirection = getRawTextDirection();
22023            switch(textDirection) {
22024                case TEXT_DIRECTION_INHERIT:
22025                    if (!canResolveTextDirection()) {
22026                        // We cannot do the resolution if there is no parent, so use the default one
22027                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22028                        // Resolution will need to happen again later
22029                        return false;
22030                    }
22031
22032                    // Parent has not yet resolved, so we still return the default
22033                    try {
22034                        if (!mParent.isTextDirectionResolved()) {
22035                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22036                            // Resolution will need to happen again later
22037                            return false;
22038                        }
22039                    } catch (AbstractMethodError e) {
22040                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22041                                " does not fully implement ViewParent", e);
22042                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
22043                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22044                        return true;
22045                    }
22046
22047                    // Set current resolved direction to the same value as the parent's one
22048                    int parentResolvedDirection;
22049                    try {
22050                        parentResolvedDirection = mParent.getTextDirection();
22051                    } catch (AbstractMethodError e) {
22052                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22053                                " does not fully implement ViewParent", e);
22054                        parentResolvedDirection = TEXT_DIRECTION_LTR;
22055                    }
22056                    switch (parentResolvedDirection) {
22057                        case TEXT_DIRECTION_FIRST_STRONG:
22058                        case TEXT_DIRECTION_ANY_RTL:
22059                        case TEXT_DIRECTION_LTR:
22060                        case TEXT_DIRECTION_RTL:
22061                        case TEXT_DIRECTION_LOCALE:
22062                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
22063                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
22064                            mPrivateFlags2 |=
22065                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
22066                            break;
22067                        default:
22068                            // Default resolved direction is "first strong" heuristic
22069                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22070                    }
22071                    break;
22072                case TEXT_DIRECTION_FIRST_STRONG:
22073                case TEXT_DIRECTION_ANY_RTL:
22074                case TEXT_DIRECTION_LTR:
22075                case TEXT_DIRECTION_RTL:
22076                case TEXT_DIRECTION_LOCALE:
22077                case TEXT_DIRECTION_FIRST_STRONG_LTR:
22078                case TEXT_DIRECTION_FIRST_STRONG_RTL:
22079                    // Resolved direction is the same as text direction
22080                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
22081                    break;
22082                default:
22083                    // Default resolved direction is "first strong" heuristic
22084                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22085            }
22086        } else {
22087            // Default resolved direction is "first strong" heuristic
22088            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22089        }
22090
22091        // Set to resolved
22092        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
22093        return true;
22094    }
22095
22096    /**
22097     * Check if text direction resolution can be done.
22098     *
22099     * @return true if text direction resolution can be done otherwise return false.
22100     */
22101    public boolean canResolveTextDirection() {
22102        switch (getRawTextDirection()) {
22103            case TEXT_DIRECTION_INHERIT:
22104                if (mParent != null) {
22105                    try {
22106                        return mParent.canResolveTextDirection();
22107                    } catch (AbstractMethodError e) {
22108                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22109                                " does not fully implement ViewParent", e);
22110                    }
22111                }
22112                return false;
22113
22114            default:
22115                return true;
22116        }
22117    }
22118
22119    /**
22120     * Reset resolved text direction. Text direction will be resolved during a call to
22121     * {@link #onMeasure(int, int)}.
22122     *
22123     * @hide
22124     */
22125    public void resetResolvedTextDirection() {
22126        // Reset any previous text direction resolution
22127        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
22128        // Set to default value
22129        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22130    }
22131
22132    /**
22133     * @return true if text direction is inherited.
22134     *
22135     * @hide
22136     */
22137    public boolean isTextDirectionInherited() {
22138        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
22139    }
22140
22141    /**
22142     * @return true if text direction is resolved.
22143     */
22144    public boolean isTextDirectionResolved() {
22145        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
22146    }
22147
22148    /**
22149     * Return the value specifying the text alignment or policy that was set with
22150     * {@link #setTextAlignment(int)}.
22151     *
22152     * @return the defined text alignment. It can be one of:
22153     *
22154     * {@link #TEXT_ALIGNMENT_INHERIT},
22155     * {@link #TEXT_ALIGNMENT_GRAVITY},
22156     * {@link #TEXT_ALIGNMENT_CENTER},
22157     * {@link #TEXT_ALIGNMENT_TEXT_START},
22158     * {@link #TEXT_ALIGNMENT_TEXT_END},
22159     * {@link #TEXT_ALIGNMENT_VIEW_START},
22160     * {@link #TEXT_ALIGNMENT_VIEW_END}
22161     *
22162     * @attr ref android.R.styleable#View_textAlignment
22163     *
22164     * @hide
22165     */
22166    @ViewDebug.ExportedProperty(category = "text", mapping = {
22167            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
22168            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
22169            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
22170            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
22171            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
22172            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
22173            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
22174    })
22175    @TextAlignment
22176    public int getRawTextAlignment() {
22177        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
22178    }
22179
22180    /**
22181     * Set the text alignment.
22182     *
22183     * @param textAlignment The text alignment to set. Should be one of
22184     *
22185     * {@link #TEXT_ALIGNMENT_INHERIT},
22186     * {@link #TEXT_ALIGNMENT_GRAVITY},
22187     * {@link #TEXT_ALIGNMENT_CENTER},
22188     * {@link #TEXT_ALIGNMENT_TEXT_START},
22189     * {@link #TEXT_ALIGNMENT_TEXT_END},
22190     * {@link #TEXT_ALIGNMENT_VIEW_START},
22191     * {@link #TEXT_ALIGNMENT_VIEW_END}
22192     *
22193     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
22194     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
22195     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
22196     *
22197     * @attr ref android.R.styleable#View_textAlignment
22198     */
22199    public void setTextAlignment(@TextAlignment int textAlignment) {
22200        if (textAlignment != getRawTextAlignment()) {
22201            // Reset the current and resolved text alignment
22202            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
22203            resetResolvedTextAlignment();
22204            // Set the new text alignment
22205            mPrivateFlags2 |=
22206                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
22207            // Do resolution
22208            resolveTextAlignment();
22209            // Notify change
22210            onRtlPropertiesChanged(getLayoutDirection());
22211            // Refresh
22212            requestLayout();
22213            invalidate(true);
22214        }
22215    }
22216
22217    /**
22218     * Return the resolved text alignment.
22219     *
22220     * @return the resolved text alignment. Returns one of:
22221     *
22222     * {@link #TEXT_ALIGNMENT_GRAVITY},
22223     * {@link #TEXT_ALIGNMENT_CENTER},
22224     * {@link #TEXT_ALIGNMENT_TEXT_START},
22225     * {@link #TEXT_ALIGNMENT_TEXT_END},
22226     * {@link #TEXT_ALIGNMENT_VIEW_START},
22227     * {@link #TEXT_ALIGNMENT_VIEW_END}
22228     *
22229     * @attr ref android.R.styleable#View_textAlignment
22230     */
22231    @ViewDebug.ExportedProperty(category = "text", mapping = {
22232            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
22233            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
22234            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
22235            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
22236            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
22237            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
22238            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
22239    })
22240    @TextAlignment
22241    public int getTextAlignment() {
22242        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
22243                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
22244    }
22245
22246    /**
22247     * Resolve the text alignment.
22248     *
22249     * @return true if resolution has been done, false otherwise.
22250     *
22251     * @hide
22252     */
22253    public boolean resolveTextAlignment() {
22254        // Reset any previous text alignment resolution
22255        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
22256
22257        if (hasRtlSupport()) {
22258            // Set resolved text alignment flag depending on text alignment flag
22259            final int textAlignment = getRawTextAlignment();
22260            switch (textAlignment) {
22261                case TEXT_ALIGNMENT_INHERIT:
22262                    // Check if we can resolve the text alignment
22263                    if (!canResolveTextAlignment()) {
22264                        // We cannot do the resolution if there is no parent so use the default
22265                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22266                        // Resolution will need to happen again later
22267                        return false;
22268                    }
22269
22270                    // Parent has not yet resolved, so we still return the default
22271                    try {
22272                        if (!mParent.isTextAlignmentResolved()) {
22273                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22274                            // Resolution will need to happen again later
22275                            return false;
22276                        }
22277                    } catch (AbstractMethodError e) {
22278                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22279                                " does not fully implement ViewParent", e);
22280                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
22281                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22282                        return true;
22283                    }
22284
22285                    int parentResolvedTextAlignment;
22286                    try {
22287                        parentResolvedTextAlignment = mParent.getTextAlignment();
22288                    } catch (AbstractMethodError e) {
22289                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22290                                " does not fully implement ViewParent", e);
22291                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
22292                    }
22293                    switch (parentResolvedTextAlignment) {
22294                        case TEXT_ALIGNMENT_GRAVITY:
22295                        case TEXT_ALIGNMENT_TEXT_START:
22296                        case TEXT_ALIGNMENT_TEXT_END:
22297                        case TEXT_ALIGNMENT_CENTER:
22298                        case TEXT_ALIGNMENT_VIEW_START:
22299                        case TEXT_ALIGNMENT_VIEW_END:
22300                            // Resolved text alignment is the same as the parent resolved
22301                            // text alignment
22302                            mPrivateFlags2 |=
22303                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
22304                            break;
22305                        default:
22306                            // Use default resolved text alignment
22307                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22308                    }
22309                    break;
22310                case TEXT_ALIGNMENT_GRAVITY:
22311                case TEXT_ALIGNMENT_TEXT_START:
22312                case TEXT_ALIGNMENT_TEXT_END:
22313                case TEXT_ALIGNMENT_CENTER:
22314                case TEXT_ALIGNMENT_VIEW_START:
22315                case TEXT_ALIGNMENT_VIEW_END:
22316                    // Resolved text alignment is the same as text alignment
22317                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
22318                    break;
22319                default:
22320                    // Use default resolved text alignment
22321                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22322            }
22323        } else {
22324            // Use default resolved text alignment
22325            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22326        }
22327
22328        // Set the resolved
22329        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
22330        return true;
22331    }
22332
22333    /**
22334     * Check if text alignment resolution can be done.
22335     *
22336     * @return true if text alignment resolution can be done otherwise return false.
22337     */
22338    public boolean canResolveTextAlignment() {
22339        switch (getRawTextAlignment()) {
22340            case TEXT_DIRECTION_INHERIT:
22341                if (mParent != null) {
22342                    try {
22343                        return mParent.canResolveTextAlignment();
22344                    } catch (AbstractMethodError e) {
22345                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22346                                " does not fully implement ViewParent", e);
22347                    }
22348                }
22349                return false;
22350
22351            default:
22352                return true;
22353        }
22354    }
22355
22356    /**
22357     * Reset resolved text alignment. Text alignment will be resolved during a call to
22358     * {@link #onMeasure(int, int)}.
22359     *
22360     * @hide
22361     */
22362    public void resetResolvedTextAlignment() {
22363        // Reset any previous text alignment resolution
22364        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
22365        // Set to default
22366        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22367    }
22368
22369    /**
22370     * @return true if text alignment is inherited.
22371     *
22372     * @hide
22373     */
22374    public boolean isTextAlignmentInherited() {
22375        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
22376    }
22377
22378    /**
22379     * @return true if text alignment is resolved.
22380     */
22381    public boolean isTextAlignmentResolved() {
22382        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
22383    }
22384
22385    /**
22386     * Generate a value suitable for use in {@link #setId(int)}.
22387     * This value will not collide with ID values generated at build time by aapt for R.id.
22388     *
22389     * @return a generated ID value
22390     */
22391    public static int generateViewId() {
22392        for (;;) {
22393            final int result = sNextGeneratedId.get();
22394            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
22395            int newValue = result + 1;
22396            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
22397            if (sNextGeneratedId.compareAndSet(result, newValue)) {
22398                return result;
22399            }
22400        }
22401    }
22402
22403    /**
22404     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
22405     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
22406     *                           a normal View or a ViewGroup with
22407     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
22408     * @hide
22409     */
22410    public void captureTransitioningViews(List<View> transitioningViews) {
22411        if (getVisibility() == View.VISIBLE) {
22412            transitioningViews.add(this);
22413        }
22414    }
22415
22416    /**
22417     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
22418     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
22419     * @hide
22420     */
22421    public void findNamedViews(Map<String, View> namedElements) {
22422        if (getVisibility() == VISIBLE || mGhostView != null) {
22423            String transitionName = getTransitionName();
22424            if (transitionName != null) {
22425                namedElements.put(transitionName, this);
22426            }
22427        }
22428    }
22429
22430    /**
22431     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
22432     * The default implementation does not care the location or event types, but some subclasses
22433     * may use it (such as WebViews).
22434     * @param event The MotionEvent from a mouse
22435     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
22436     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
22437     * @see PointerIcon
22438     */
22439    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
22440        final float x = event.getX(pointerIndex);
22441        final float y = event.getY(pointerIndex);
22442        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
22443            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
22444        }
22445        return mPointerIcon;
22446    }
22447
22448    /**
22449     * Set the pointer icon for the current view.
22450     * Passing {@code null} will restore the pointer icon to its default value.
22451     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
22452     */
22453    public void setPointerIcon(PointerIcon pointerIcon) {
22454        mPointerIcon = pointerIcon;
22455        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
22456            return;
22457        }
22458        try {
22459            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
22460        } catch (RemoteException e) {
22461        }
22462    }
22463
22464    /**
22465     * Gets the pointer icon for the current view.
22466     */
22467    public PointerIcon getPointerIcon() {
22468        return mPointerIcon;
22469    }
22470
22471    //
22472    // Properties
22473    //
22474    /**
22475     * A Property wrapper around the <code>alpha</code> functionality handled by the
22476     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
22477     */
22478    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
22479        @Override
22480        public void setValue(View object, float value) {
22481            object.setAlpha(value);
22482        }
22483
22484        @Override
22485        public Float get(View object) {
22486            return object.getAlpha();
22487        }
22488    };
22489
22490    /**
22491     * A Property wrapper around the <code>translationX</code> functionality handled by the
22492     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
22493     */
22494    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
22495        @Override
22496        public void setValue(View object, float value) {
22497            object.setTranslationX(value);
22498        }
22499
22500                @Override
22501        public Float get(View object) {
22502            return object.getTranslationX();
22503        }
22504    };
22505
22506    /**
22507     * A Property wrapper around the <code>translationY</code> functionality handled by the
22508     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
22509     */
22510    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
22511        @Override
22512        public void setValue(View object, float value) {
22513            object.setTranslationY(value);
22514        }
22515
22516        @Override
22517        public Float get(View object) {
22518            return object.getTranslationY();
22519        }
22520    };
22521
22522    /**
22523     * A Property wrapper around the <code>translationZ</code> functionality handled by the
22524     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
22525     */
22526    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
22527        @Override
22528        public void setValue(View object, float value) {
22529            object.setTranslationZ(value);
22530        }
22531
22532        @Override
22533        public Float get(View object) {
22534            return object.getTranslationZ();
22535        }
22536    };
22537
22538    /**
22539     * A Property wrapper around the <code>x</code> functionality handled by the
22540     * {@link View#setX(float)} and {@link View#getX()} methods.
22541     */
22542    public static final Property<View, Float> X = new FloatProperty<View>("x") {
22543        @Override
22544        public void setValue(View object, float value) {
22545            object.setX(value);
22546        }
22547
22548        @Override
22549        public Float get(View object) {
22550            return object.getX();
22551        }
22552    };
22553
22554    /**
22555     * A Property wrapper around the <code>y</code> functionality handled by the
22556     * {@link View#setY(float)} and {@link View#getY()} methods.
22557     */
22558    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
22559        @Override
22560        public void setValue(View object, float value) {
22561            object.setY(value);
22562        }
22563
22564        @Override
22565        public Float get(View object) {
22566            return object.getY();
22567        }
22568    };
22569
22570    /**
22571     * A Property wrapper around the <code>z</code> functionality handled by the
22572     * {@link View#setZ(float)} and {@link View#getZ()} methods.
22573     */
22574    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
22575        @Override
22576        public void setValue(View object, float value) {
22577            object.setZ(value);
22578        }
22579
22580        @Override
22581        public Float get(View object) {
22582            return object.getZ();
22583        }
22584    };
22585
22586    /**
22587     * A Property wrapper around the <code>rotation</code> functionality handled by the
22588     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
22589     */
22590    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
22591        @Override
22592        public void setValue(View object, float value) {
22593            object.setRotation(value);
22594        }
22595
22596        @Override
22597        public Float get(View object) {
22598            return object.getRotation();
22599        }
22600    };
22601
22602    /**
22603     * A Property wrapper around the <code>rotationX</code> functionality handled by the
22604     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
22605     */
22606    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
22607        @Override
22608        public void setValue(View object, float value) {
22609            object.setRotationX(value);
22610        }
22611
22612        @Override
22613        public Float get(View object) {
22614            return object.getRotationX();
22615        }
22616    };
22617
22618    /**
22619     * A Property wrapper around the <code>rotationY</code> functionality handled by the
22620     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
22621     */
22622    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
22623        @Override
22624        public void setValue(View object, float value) {
22625            object.setRotationY(value);
22626        }
22627
22628        @Override
22629        public Float get(View object) {
22630            return object.getRotationY();
22631        }
22632    };
22633
22634    /**
22635     * A Property wrapper around the <code>scaleX</code> functionality handled by the
22636     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
22637     */
22638    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
22639        @Override
22640        public void setValue(View object, float value) {
22641            object.setScaleX(value);
22642        }
22643
22644        @Override
22645        public Float get(View object) {
22646            return object.getScaleX();
22647        }
22648    };
22649
22650    /**
22651     * A Property wrapper around the <code>scaleY</code> functionality handled by the
22652     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
22653     */
22654    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
22655        @Override
22656        public void setValue(View object, float value) {
22657            object.setScaleY(value);
22658        }
22659
22660        @Override
22661        public Float get(View object) {
22662            return object.getScaleY();
22663        }
22664    };
22665
22666    /**
22667     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
22668     * Each MeasureSpec represents a requirement for either the width or the height.
22669     * A MeasureSpec is comprised of a size and a mode. There are three possible
22670     * modes:
22671     * <dl>
22672     * <dt>UNSPECIFIED</dt>
22673     * <dd>
22674     * The parent has not imposed any constraint on the child. It can be whatever size
22675     * it wants.
22676     * </dd>
22677     *
22678     * <dt>EXACTLY</dt>
22679     * <dd>
22680     * The parent has determined an exact size for the child. The child is going to be
22681     * given those bounds regardless of how big it wants to be.
22682     * </dd>
22683     *
22684     * <dt>AT_MOST</dt>
22685     * <dd>
22686     * The child can be as large as it wants up to the specified size.
22687     * </dd>
22688     * </dl>
22689     *
22690     * MeasureSpecs are implemented as ints to reduce object allocation. This class
22691     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
22692     */
22693    public static class MeasureSpec {
22694        private static final int MODE_SHIFT = 30;
22695        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
22696
22697        /** @hide */
22698        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
22699        @Retention(RetentionPolicy.SOURCE)
22700        public @interface MeasureSpecMode {}
22701
22702        /**
22703         * Measure specification mode: The parent has not imposed any constraint
22704         * on the child. It can be whatever size it wants.
22705         */
22706        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
22707
22708        /**
22709         * Measure specification mode: The parent has determined an exact size
22710         * for the child. The child is going to be given those bounds regardless
22711         * of how big it wants to be.
22712         */
22713        public static final int EXACTLY     = 1 << MODE_SHIFT;
22714
22715        /**
22716         * Measure specification mode: The child can be as large as it wants up
22717         * to the specified size.
22718         */
22719        public static final int AT_MOST     = 2 << MODE_SHIFT;
22720
22721        /**
22722         * Creates a measure specification based on the supplied size and mode.
22723         *
22724         * The mode must always be one of the following:
22725         * <ul>
22726         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
22727         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
22728         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
22729         * </ul>
22730         *
22731         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
22732         * implementation was such that the order of arguments did not matter
22733         * and overflow in either value could impact the resulting MeasureSpec.
22734         * {@link android.widget.RelativeLayout} was affected by this bug.
22735         * Apps targeting API levels greater than 17 will get the fixed, more strict
22736         * behavior.</p>
22737         *
22738         * @param size the size of the measure specification
22739         * @param mode the mode of the measure specification
22740         * @return the measure specification based on size and mode
22741         */
22742        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
22743                                          @MeasureSpecMode int mode) {
22744            if (sUseBrokenMakeMeasureSpec) {
22745                return size + mode;
22746            } else {
22747                return (size & ~MODE_MASK) | (mode & MODE_MASK);
22748            }
22749        }
22750
22751        /**
22752         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
22753         * will automatically get a size of 0. Older apps expect this.
22754         *
22755         * @hide internal use only for compatibility with system widgets and older apps
22756         */
22757        public static int makeSafeMeasureSpec(int size, int mode) {
22758            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
22759                return 0;
22760            }
22761            return makeMeasureSpec(size, mode);
22762        }
22763
22764        /**
22765         * Extracts the mode from the supplied measure specification.
22766         *
22767         * @param measureSpec the measure specification to extract the mode from
22768         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
22769         *         {@link android.view.View.MeasureSpec#AT_MOST} or
22770         *         {@link android.view.View.MeasureSpec#EXACTLY}
22771         */
22772        @MeasureSpecMode
22773        public static int getMode(int measureSpec) {
22774            //noinspection ResourceType
22775            return (measureSpec & MODE_MASK);
22776        }
22777
22778        /**
22779         * Extracts the size from the supplied measure specification.
22780         *
22781         * @param measureSpec the measure specification to extract the size from
22782         * @return the size in pixels defined in the supplied measure specification
22783         */
22784        public static int getSize(int measureSpec) {
22785            return (measureSpec & ~MODE_MASK);
22786        }
22787
22788        static int adjust(int measureSpec, int delta) {
22789            final int mode = getMode(measureSpec);
22790            int size = getSize(measureSpec);
22791            if (mode == UNSPECIFIED) {
22792                // No need to adjust size for UNSPECIFIED mode.
22793                return makeMeasureSpec(size, UNSPECIFIED);
22794            }
22795            size += delta;
22796            if (size < 0) {
22797                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
22798                        ") spec: " + toString(measureSpec) + " delta: " + delta);
22799                size = 0;
22800            }
22801            return makeMeasureSpec(size, mode);
22802        }
22803
22804        /**
22805         * Returns a String representation of the specified measure
22806         * specification.
22807         *
22808         * @param measureSpec the measure specification to convert to a String
22809         * @return a String with the following format: "MeasureSpec: MODE SIZE"
22810         */
22811        public static String toString(int measureSpec) {
22812            int mode = getMode(measureSpec);
22813            int size = getSize(measureSpec);
22814
22815            StringBuilder sb = new StringBuilder("MeasureSpec: ");
22816
22817            if (mode == UNSPECIFIED)
22818                sb.append("UNSPECIFIED ");
22819            else if (mode == EXACTLY)
22820                sb.append("EXACTLY ");
22821            else if (mode == AT_MOST)
22822                sb.append("AT_MOST ");
22823            else
22824                sb.append(mode).append(" ");
22825
22826            sb.append(size);
22827            return sb.toString();
22828        }
22829    }
22830
22831    private final class CheckForLongPress implements Runnable {
22832        private int mOriginalWindowAttachCount;
22833        private float mX;
22834        private float mY;
22835        private boolean mOriginalPressedState;
22836
22837        @Override
22838        public void run() {
22839            if ((mOriginalPressedState == isPressed()) && (mParent != null)
22840                    && mOriginalWindowAttachCount == mWindowAttachCount) {
22841                if (performLongClick(mX, mY)) {
22842                    mHasPerformedLongPress = true;
22843                }
22844            }
22845        }
22846
22847        public void setAnchor(float x, float y) {
22848            mX = x;
22849            mY = y;
22850        }
22851
22852        public void rememberWindowAttachCount() {
22853            mOriginalWindowAttachCount = mWindowAttachCount;
22854        }
22855
22856        public void rememberPressedState() {
22857            mOriginalPressedState = isPressed();
22858        }
22859    }
22860
22861    private final class CheckForTap implements Runnable {
22862        public float x;
22863        public float y;
22864
22865        @Override
22866        public void run() {
22867            mPrivateFlags &= ~PFLAG_PREPRESSED;
22868            setPressed(true, x, y);
22869            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
22870        }
22871    }
22872
22873    private final class PerformClick implements Runnable {
22874        @Override
22875        public void run() {
22876            performClick();
22877        }
22878    }
22879
22880    /**
22881     * This method returns a ViewPropertyAnimator object, which can be used to animate
22882     * specific properties on this View.
22883     *
22884     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
22885     */
22886    public ViewPropertyAnimator animate() {
22887        if (mAnimator == null) {
22888            mAnimator = new ViewPropertyAnimator(this);
22889        }
22890        return mAnimator;
22891    }
22892
22893    /**
22894     * Sets the name of the View to be used to identify Views in Transitions.
22895     * Names should be unique in the View hierarchy.
22896     *
22897     * @param transitionName The name of the View to uniquely identify it for Transitions.
22898     */
22899    public final void setTransitionName(String transitionName) {
22900        mTransitionName = transitionName;
22901    }
22902
22903    /**
22904     * Returns the name of the View to be used to identify Views in Transitions.
22905     * Names should be unique in the View hierarchy.
22906     *
22907     * <p>This returns null if the View has not been given a name.</p>
22908     *
22909     * @return The name used of the View to be used to identify Views in Transitions or null
22910     * if no name has been given.
22911     */
22912    @ViewDebug.ExportedProperty
22913    public String getTransitionName() {
22914        return mTransitionName;
22915    }
22916
22917    /**
22918     * @hide
22919     */
22920    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
22921        // Do nothing.
22922    }
22923
22924    /**
22925     * Interface definition for a callback to be invoked when a hardware key event is
22926     * dispatched to this view. The callback will be invoked before the key event is
22927     * given to the view. This is only useful for hardware keyboards; a software input
22928     * method has no obligation to trigger this listener.
22929     */
22930    public interface OnKeyListener {
22931        /**
22932         * Called when a hardware key is dispatched to a view. This allows listeners to
22933         * get a chance to respond before the target view.
22934         * <p>Key presses in software keyboards will generally NOT trigger this method,
22935         * although some may elect to do so in some situations. Do not assume a
22936         * software input method has to be key-based; even if it is, it may use key presses
22937         * in a different way than you expect, so there is no way to reliably catch soft
22938         * input key presses.
22939         *
22940         * @param v The view the key has been dispatched to.
22941         * @param keyCode The code for the physical key that was pressed
22942         * @param event The KeyEvent object containing full information about
22943         *        the event.
22944         * @return True if the listener has consumed the event, false otherwise.
22945         */
22946        boolean onKey(View v, int keyCode, KeyEvent event);
22947    }
22948
22949    /**
22950     * Interface definition for a callback to be invoked when a touch event is
22951     * dispatched to this view. The callback will be invoked before the touch
22952     * event is given to the view.
22953     */
22954    public interface OnTouchListener {
22955        /**
22956         * Called when a touch event is dispatched to a view. This allows listeners to
22957         * get a chance to respond before the target view.
22958         *
22959         * @param v The view the touch event has been dispatched to.
22960         * @param event The MotionEvent object containing full information about
22961         *        the event.
22962         * @return True if the listener has consumed the event, false otherwise.
22963         */
22964        boolean onTouch(View v, MotionEvent event);
22965    }
22966
22967    /**
22968     * Interface definition for a callback to be invoked when a hover event is
22969     * dispatched to this view. The callback will be invoked before the hover
22970     * event is given to the view.
22971     */
22972    public interface OnHoverListener {
22973        /**
22974         * Called when a hover event is dispatched to a view. This allows listeners to
22975         * get a chance to respond before the target view.
22976         *
22977         * @param v The view the hover event has been dispatched to.
22978         * @param event The MotionEvent object containing full information about
22979         *        the event.
22980         * @return True if the listener has consumed the event, false otherwise.
22981         */
22982        boolean onHover(View v, MotionEvent event);
22983    }
22984
22985    /**
22986     * Interface definition for a callback to be invoked when a generic motion event is
22987     * dispatched to this view. The callback will be invoked before the generic motion
22988     * event is given to the view.
22989     */
22990    public interface OnGenericMotionListener {
22991        /**
22992         * Called when a generic motion event is dispatched to a view. This allows listeners to
22993         * get a chance to respond before the target view.
22994         *
22995         * @param v The view the generic motion event has been dispatched to.
22996         * @param event The MotionEvent object containing full information about
22997         *        the event.
22998         * @return True if the listener has consumed the event, false otherwise.
22999         */
23000        boolean onGenericMotion(View v, MotionEvent event);
23001    }
23002
23003    /**
23004     * Interface definition for a callback to be invoked when a view has been clicked and held.
23005     */
23006    public interface OnLongClickListener {
23007        /**
23008         * Called when a view has been clicked and held.
23009         *
23010         * @param v The view that was clicked and held.
23011         *
23012         * @return true if the callback consumed the long click, false otherwise.
23013         */
23014        boolean onLongClick(View v);
23015    }
23016
23017    /**
23018     * Interface definition for a callback to be invoked when a drag is being dispatched
23019     * to this view.  The callback will be invoked before the hosting view's own
23020     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
23021     * onDrag(event) behavior, it should return 'false' from this callback.
23022     *
23023     * <div class="special reference">
23024     * <h3>Developer Guides</h3>
23025     * <p>For a guide to implementing drag and drop features, read the
23026     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
23027     * </div>
23028     */
23029    public interface OnDragListener {
23030        /**
23031         * Called when a drag event is dispatched to a view. This allows listeners
23032         * to get a chance to override base View behavior.
23033         *
23034         * @param v The View that received the drag event.
23035         * @param event The {@link android.view.DragEvent} object for the drag event.
23036         * @return {@code true} if the drag event was handled successfully, or {@code false}
23037         * if the drag event was not handled. Note that {@code false} will trigger the View
23038         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
23039         */
23040        boolean onDrag(View v, DragEvent event);
23041    }
23042
23043    /**
23044     * Interface definition for a callback to be invoked when the focus state of
23045     * a view changed.
23046     */
23047    public interface OnFocusChangeListener {
23048        /**
23049         * Called when the focus state of a view has changed.
23050         *
23051         * @param v The view whose state has changed.
23052         * @param hasFocus The new focus state of v.
23053         */
23054        void onFocusChange(View v, boolean hasFocus);
23055    }
23056
23057    /**
23058     * Interface definition for a callback to be invoked when a view is clicked.
23059     */
23060    public interface OnClickListener {
23061        /**
23062         * Called when a view has been clicked.
23063         *
23064         * @param v The view that was clicked.
23065         */
23066        void onClick(View v);
23067    }
23068
23069    /**
23070     * Interface definition for a callback to be invoked when a view is context clicked.
23071     */
23072    public interface OnContextClickListener {
23073        /**
23074         * Called when a view is context clicked.
23075         *
23076         * @param v The view that has been context clicked.
23077         * @return true if the callback consumed the context click, false otherwise.
23078         */
23079        boolean onContextClick(View v);
23080    }
23081
23082    /**
23083     * Interface definition for a callback to be invoked when the context menu
23084     * for this view is being built.
23085     */
23086    public interface OnCreateContextMenuListener {
23087        /**
23088         * Called when the context menu for this view is being built. It is not
23089         * safe to hold onto the menu after this method returns.
23090         *
23091         * @param menu The context menu that is being built
23092         * @param v The view for which the context menu is being built
23093         * @param menuInfo Extra information about the item for which the
23094         *            context menu should be shown. This information will vary
23095         *            depending on the class of v.
23096         */
23097        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
23098    }
23099
23100    /**
23101     * Interface definition for a callback to be invoked when the status bar changes
23102     * visibility.  This reports <strong>global</strong> changes to the system UI
23103     * state, not what the application is requesting.
23104     *
23105     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
23106     */
23107    public interface OnSystemUiVisibilityChangeListener {
23108        /**
23109         * Called when the status bar changes visibility because of a call to
23110         * {@link View#setSystemUiVisibility(int)}.
23111         *
23112         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
23113         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
23114         * This tells you the <strong>global</strong> state of these UI visibility
23115         * flags, not what your app is currently applying.
23116         */
23117        public void onSystemUiVisibilityChange(int visibility);
23118    }
23119
23120    /**
23121     * Interface definition for a callback to be invoked when this view is attached
23122     * or detached from its window.
23123     */
23124    public interface OnAttachStateChangeListener {
23125        /**
23126         * Called when the view is attached to a window.
23127         * @param v The view that was attached
23128         */
23129        public void onViewAttachedToWindow(View v);
23130        /**
23131         * Called when the view is detached from a window.
23132         * @param v The view that was detached
23133         */
23134        public void onViewDetachedFromWindow(View v);
23135    }
23136
23137    /**
23138     * Listener for applying window insets on a view in a custom way.
23139     *
23140     * <p>Apps may choose to implement this interface if they want to apply custom policy
23141     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
23142     * is set, its
23143     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
23144     * method will be called instead of the View's own
23145     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
23146     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
23147     * the View's normal behavior as part of its own.</p>
23148     */
23149    public interface OnApplyWindowInsetsListener {
23150        /**
23151         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
23152         * on a View, this listener method will be called instead of the view's own
23153         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
23154         *
23155         * @param v The view applying window insets
23156         * @param insets The insets to apply
23157         * @return The insets supplied, minus any insets that were consumed
23158         */
23159        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
23160    }
23161
23162    private final class UnsetPressedState implements Runnable {
23163        @Override
23164        public void run() {
23165            setPressed(false);
23166        }
23167    }
23168
23169    /**
23170     * Base class for derived classes that want to save and restore their own
23171     * state in {@link android.view.View#onSaveInstanceState()}.
23172     */
23173    public static class BaseSavedState extends AbsSavedState {
23174        String mStartActivityRequestWhoSaved;
23175
23176        /**
23177         * Constructor used when reading from a parcel. Reads the state of the superclass.
23178         *
23179         * @param source parcel to read from
23180         */
23181        public BaseSavedState(Parcel source) {
23182            this(source, null);
23183        }
23184
23185        /**
23186         * Constructor used when reading from a parcel using a given class loader.
23187         * Reads the state of the superclass.
23188         *
23189         * @param source parcel to read from
23190         * @param loader ClassLoader to use for reading
23191         */
23192        public BaseSavedState(Parcel source, ClassLoader loader) {
23193            super(source, loader);
23194            mStartActivityRequestWhoSaved = source.readString();
23195        }
23196
23197        /**
23198         * Constructor called by derived classes when creating their SavedState objects
23199         *
23200         * @param superState The state of the superclass of this view
23201         */
23202        public BaseSavedState(Parcelable superState) {
23203            super(superState);
23204        }
23205
23206        @Override
23207        public void writeToParcel(Parcel out, int flags) {
23208            super.writeToParcel(out, flags);
23209            out.writeString(mStartActivityRequestWhoSaved);
23210        }
23211
23212        public static final Parcelable.Creator<BaseSavedState> CREATOR
23213                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
23214            @Override
23215            public BaseSavedState createFromParcel(Parcel in) {
23216                return new BaseSavedState(in);
23217            }
23218
23219            @Override
23220            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
23221                return new BaseSavedState(in, loader);
23222            }
23223
23224            @Override
23225            public BaseSavedState[] newArray(int size) {
23226                return new BaseSavedState[size];
23227            }
23228        };
23229    }
23230
23231    /**
23232     * A set of information given to a view when it is attached to its parent
23233     * window.
23234     */
23235    final static class AttachInfo {
23236        interface Callbacks {
23237            void playSoundEffect(int effectId);
23238            boolean performHapticFeedback(int effectId, boolean always);
23239        }
23240
23241        /**
23242         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
23243         * to a Handler. This class contains the target (View) to invalidate and
23244         * the coordinates of the dirty rectangle.
23245         *
23246         * For performance purposes, this class also implements a pool of up to
23247         * POOL_LIMIT objects that get reused. This reduces memory allocations
23248         * whenever possible.
23249         */
23250        static class InvalidateInfo {
23251            private static final int POOL_LIMIT = 10;
23252
23253            private static final SynchronizedPool<InvalidateInfo> sPool =
23254                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
23255
23256            View target;
23257
23258            int left;
23259            int top;
23260            int right;
23261            int bottom;
23262
23263            public static InvalidateInfo obtain() {
23264                InvalidateInfo instance = sPool.acquire();
23265                return (instance != null) ? instance : new InvalidateInfo();
23266            }
23267
23268            public void recycle() {
23269                target = null;
23270                sPool.release(this);
23271            }
23272        }
23273
23274        final IWindowSession mSession;
23275
23276        final IWindow mWindow;
23277
23278        final IBinder mWindowToken;
23279
23280        final Display mDisplay;
23281
23282        final Callbacks mRootCallbacks;
23283
23284        IWindowId mIWindowId;
23285        WindowId mWindowId;
23286
23287        /**
23288         * The top view of the hierarchy.
23289         */
23290        View mRootView;
23291
23292        IBinder mPanelParentWindowToken;
23293
23294        boolean mHardwareAccelerated;
23295        boolean mHardwareAccelerationRequested;
23296        ThreadedRenderer mThreadedRenderer;
23297        List<RenderNode> mPendingAnimatingRenderNodes;
23298
23299        /**
23300         * The state of the display to which the window is attached, as reported
23301         * by {@link Display#getState()}.  Note that the display state constants
23302         * declared by {@link Display} do not exactly line up with the screen state
23303         * constants declared by {@link View} (there are more display states than
23304         * screen states).
23305         */
23306        int mDisplayState = Display.STATE_UNKNOWN;
23307
23308        /**
23309         * Scale factor used by the compatibility mode
23310         */
23311        float mApplicationScale;
23312
23313        /**
23314         * Indicates whether the application is in compatibility mode
23315         */
23316        boolean mScalingRequired;
23317
23318        /**
23319         * Left position of this view's window
23320         */
23321        int mWindowLeft;
23322
23323        /**
23324         * Top position of this view's window
23325         */
23326        int mWindowTop;
23327
23328        /**
23329         * Indicates whether views need to use 32-bit drawing caches
23330         */
23331        boolean mUse32BitDrawingCache;
23332
23333        /**
23334         * For windows that are full-screen but using insets to layout inside
23335         * of the screen areas, these are the current insets to appear inside
23336         * the overscan area of the display.
23337         */
23338        final Rect mOverscanInsets = new Rect();
23339
23340        /**
23341         * For windows that are full-screen but using insets to layout inside
23342         * of the screen decorations, these are the current insets for the
23343         * content of the window.
23344         */
23345        final Rect mContentInsets = new Rect();
23346
23347        /**
23348         * For windows that are full-screen but using insets to layout inside
23349         * of the screen decorations, these are the current insets for the
23350         * actual visible parts of the window.
23351         */
23352        final Rect mVisibleInsets = new Rect();
23353
23354        /**
23355         * For windows that are full-screen but using insets to layout inside
23356         * of the screen decorations, these are the current insets for the
23357         * stable system windows.
23358         */
23359        final Rect mStableInsets = new Rect();
23360
23361        /**
23362         * For windows that include areas that are not covered by real surface these are the outsets
23363         * for real surface.
23364         */
23365        final Rect mOutsets = new Rect();
23366
23367        /**
23368         * In multi-window we force show the navigation bar. Because we don't want that the surface
23369         * size changes in this mode, we instead have a flag whether the navigation bar size should
23370         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
23371         */
23372        boolean mAlwaysConsumeNavBar;
23373
23374        /**
23375         * The internal insets given by this window.  This value is
23376         * supplied by the client (through
23377         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
23378         * be given to the window manager when changed to be used in laying
23379         * out windows behind it.
23380         */
23381        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
23382                = new ViewTreeObserver.InternalInsetsInfo();
23383
23384        /**
23385         * Set to true when mGivenInternalInsets is non-empty.
23386         */
23387        boolean mHasNonEmptyGivenInternalInsets;
23388
23389        /**
23390         * All views in the window's hierarchy that serve as scroll containers,
23391         * used to determine if the window can be resized or must be panned
23392         * to adjust for a soft input area.
23393         */
23394        final ArrayList<View> mScrollContainers = new ArrayList<View>();
23395
23396        final KeyEvent.DispatcherState mKeyDispatchState
23397                = new KeyEvent.DispatcherState();
23398
23399        /**
23400         * Indicates whether the view's window currently has the focus.
23401         */
23402        boolean mHasWindowFocus;
23403
23404        /**
23405         * The current visibility of the window.
23406         */
23407        int mWindowVisibility;
23408
23409        /**
23410         * Indicates the time at which drawing started to occur.
23411         */
23412        long mDrawingTime;
23413
23414        /**
23415         * Indicates whether or not ignoring the DIRTY_MASK flags.
23416         */
23417        boolean mIgnoreDirtyState;
23418
23419        /**
23420         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
23421         * to avoid clearing that flag prematurely.
23422         */
23423        boolean mSetIgnoreDirtyState = false;
23424
23425        /**
23426         * Indicates whether the view's window is currently in touch mode.
23427         */
23428        boolean mInTouchMode;
23429
23430        /**
23431         * Indicates whether the view has requested unbuffered input dispatching for the current
23432         * event stream.
23433         */
23434        boolean mUnbufferedDispatchRequested;
23435
23436        /**
23437         * Indicates that ViewAncestor should trigger a global layout change
23438         * the next time it performs a traversal
23439         */
23440        boolean mRecomputeGlobalAttributes;
23441
23442        /**
23443         * Always report new attributes at next traversal.
23444         */
23445        boolean mForceReportNewAttributes;
23446
23447        /**
23448         * Set during a traveral if any views want to keep the screen on.
23449         */
23450        boolean mKeepScreenOn;
23451
23452        /**
23453         * Set during a traveral if the light center needs to be updated.
23454         */
23455        boolean mNeedsUpdateLightCenter;
23456
23457        /**
23458         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
23459         */
23460        int mSystemUiVisibility;
23461
23462        /**
23463         * Hack to force certain system UI visibility flags to be cleared.
23464         */
23465        int mDisabledSystemUiVisibility;
23466
23467        /**
23468         * Last global system UI visibility reported by the window manager.
23469         */
23470        int mGlobalSystemUiVisibility = -1;
23471
23472        /**
23473         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
23474         * attached.
23475         */
23476        boolean mHasSystemUiListeners;
23477
23478        /**
23479         * Set if the window has requested to extend into the overscan region
23480         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
23481         */
23482        boolean mOverscanRequested;
23483
23484        /**
23485         * Set if the visibility of any views has changed.
23486         */
23487        boolean mViewVisibilityChanged;
23488
23489        /**
23490         * Set to true if a view has been scrolled.
23491         */
23492        boolean mViewScrollChanged;
23493
23494        /**
23495         * Set to true if high contrast mode enabled
23496         */
23497        boolean mHighContrastText;
23498
23499        /**
23500         * Set to true if a pointer event is currently being handled.
23501         */
23502        boolean mHandlingPointerEvent;
23503
23504        /**
23505         * Global to the view hierarchy used as a temporary for dealing with
23506         * x/y points in the transparent region computations.
23507         */
23508        final int[] mTransparentLocation = new int[2];
23509
23510        /**
23511         * Global to the view hierarchy used as a temporary for dealing with
23512         * x/y points in the ViewGroup.invalidateChild implementation.
23513         */
23514        final int[] mInvalidateChildLocation = new int[2];
23515
23516        /**
23517         * Global to the view hierarchy used as a temporary for dealing with
23518         * computing absolute on-screen location.
23519         */
23520        final int[] mTmpLocation = new int[2];
23521
23522        /**
23523         * Global to the view hierarchy used as a temporary for dealing with
23524         * x/y location when view is transformed.
23525         */
23526        final float[] mTmpTransformLocation = new float[2];
23527
23528        /**
23529         * The view tree observer used to dispatch global events like
23530         * layout, pre-draw, touch mode change, etc.
23531         */
23532        final ViewTreeObserver mTreeObserver;
23533
23534        /**
23535         * A Canvas used by the view hierarchy to perform bitmap caching.
23536         */
23537        Canvas mCanvas;
23538
23539        /**
23540         * The view root impl.
23541         */
23542        final ViewRootImpl mViewRootImpl;
23543
23544        /**
23545         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
23546         * handler can be used to pump events in the UI events queue.
23547         */
23548        final Handler mHandler;
23549
23550        /**
23551         * Temporary for use in computing invalidate rectangles while
23552         * calling up the hierarchy.
23553         */
23554        final Rect mTmpInvalRect = new Rect();
23555
23556        /**
23557         * Temporary for use in computing hit areas with transformed views
23558         */
23559        final RectF mTmpTransformRect = new RectF();
23560
23561        /**
23562         * Temporary for use in computing hit areas with transformed views
23563         */
23564        final RectF mTmpTransformRect1 = new RectF();
23565
23566        /**
23567         * Temporary list of rectanges.
23568         */
23569        final List<RectF> mTmpRectList = new ArrayList<>();
23570
23571        /**
23572         * Temporary for use in transforming invalidation rect
23573         */
23574        final Matrix mTmpMatrix = new Matrix();
23575
23576        /**
23577         * Temporary for use in transforming invalidation rect
23578         */
23579        final Transformation mTmpTransformation = new Transformation();
23580
23581        /**
23582         * Temporary for use in querying outlines from OutlineProviders
23583         */
23584        final Outline mTmpOutline = new Outline();
23585
23586        /**
23587         * Temporary list for use in collecting focusable descendents of a view.
23588         */
23589        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
23590
23591        /**
23592         * The id of the window for accessibility purposes.
23593         */
23594        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
23595
23596        /**
23597         * Flags related to accessibility processing.
23598         *
23599         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
23600         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
23601         */
23602        int mAccessibilityFetchFlags;
23603
23604        /**
23605         * The drawable for highlighting accessibility focus.
23606         */
23607        Drawable mAccessibilityFocusDrawable;
23608
23609        /**
23610         * Show where the margins, bounds and layout bounds are for each view.
23611         */
23612        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
23613
23614        /**
23615         * Point used to compute visible regions.
23616         */
23617        final Point mPoint = new Point();
23618
23619        /**
23620         * Used to track which View originated a requestLayout() call, used when
23621         * requestLayout() is called during layout.
23622         */
23623        View mViewRequestingLayout;
23624
23625        /**
23626         * Used to track views that need (at least) a partial relayout at their current size
23627         * during the next traversal.
23628         */
23629        List<View> mPartialLayoutViews = new ArrayList<>();
23630
23631        /**
23632         * Swapped with mPartialLayoutViews during layout to avoid concurrent
23633         * modification. Lazily assigned during ViewRootImpl layout.
23634         */
23635        List<View> mEmptyPartialLayoutViews;
23636
23637        /**
23638         * Used to track the identity of the current drag operation.
23639         */
23640        IBinder mDragToken;
23641
23642        /**
23643         * The drag shadow surface for the current drag operation.
23644         */
23645        public Surface mDragSurface;
23646
23647
23648        /**
23649         * The view that currently has a tooltip displayed.
23650         */
23651        View mTooltipHost;
23652
23653        /**
23654         * Creates a new set of attachment information with the specified
23655         * events handler and thread.
23656         *
23657         * @param handler the events handler the view must use
23658         */
23659        AttachInfo(IWindowSession session, IWindow window, Display display,
23660                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
23661                Context context) {
23662            mSession = session;
23663            mWindow = window;
23664            mWindowToken = window.asBinder();
23665            mDisplay = display;
23666            mViewRootImpl = viewRootImpl;
23667            mHandler = handler;
23668            mRootCallbacks = effectPlayer;
23669            mTreeObserver = new ViewTreeObserver(context);
23670        }
23671    }
23672
23673    /**
23674     * <p>ScrollabilityCache holds various fields used by a View when scrolling
23675     * is supported. This avoids keeping too many unused fields in most
23676     * instances of View.</p>
23677     */
23678    private static class ScrollabilityCache implements Runnable {
23679
23680        /**
23681         * Scrollbars are not visible
23682         */
23683        public static final int OFF = 0;
23684
23685        /**
23686         * Scrollbars are visible
23687         */
23688        public static final int ON = 1;
23689
23690        /**
23691         * Scrollbars are fading away
23692         */
23693        public static final int FADING = 2;
23694
23695        public boolean fadeScrollBars;
23696
23697        public int fadingEdgeLength;
23698        public int scrollBarDefaultDelayBeforeFade;
23699        public int scrollBarFadeDuration;
23700
23701        public int scrollBarSize;
23702        public ScrollBarDrawable scrollBar;
23703        public float[] interpolatorValues;
23704        public View host;
23705
23706        public final Paint paint;
23707        public final Matrix matrix;
23708        public Shader shader;
23709
23710        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
23711
23712        private static final float[] OPAQUE = { 255 };
23713        private static final float[] TRANSPARENT = { 0.0f };
23714
23715        /**
23716         * When fading should start. This time moves into the future every time
23717         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
23718         */
23719        public long fadeStartTime;
23720
23721
23722        /**
23723         * The current state of the scrollbars: ON, OFF, or FADING
23724         */
23725        public int state = OFF;
23726
23727        private int mLastColor;
23728
23729        public final Rect mScrollBarBounds = new Rect();
23730
23731        public static final int NOT_DRAGGING = 0;
23732        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
23733        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
23734        public int mScrollBarDraggingState = NOT_DRAGGING;
23735
23736        public float mScrollBarDraggingPos = 0;
23737
23738        public ScrollabilityCache(ViewConfiguration configuration, View host) {
23739            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
23740            scrollBarSize = configuration.getScaledScrollBarSize();
23741            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
23742            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
23743
23744            paint = new Paint();
23745            matrix = new Matrix();
23746            // use use a height of 1, and then wack the matrix each time we
23747            // actually use it.
23748            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23749            paint.setShader(shader);
23750            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23751
23752            this.host = host;
23753        }
23754
23755        public void setFadeColor(int color) {
23756            if (color != mLastColor) {
23757                mLastColor = color;
23758
23759                if (color != 0) {
23760                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
23761                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
23762                    paint.setShader(shader);
23763                    // Restore the default transfer mode (src_over)
23764                    paint.setXfermode(null);
23765                } else {
23766                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23767                    paint.setShader(shader);
23768                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23769                }
23770            }
23771        }
23772
23773        public void run() {
23774            long now = AnimationUtils.currentAnimationTimeMillis();
23775            if (now >= fadeStartTime) {
23776
23777                // the animation fades the scrollbars out by changing
23778                // the opacity (alpha) from fully opaque to fully
23779                // transparent
23780                int nextFrame = (int) now;
23781                int framesCount = 0;
23782
23783                Interpolator interpolator = scrollBarInterpolator;
23784
23785                // Start opaque
23786                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
23787
23788                // End transparent
23789                nextFrame += scrollBarFadeDuration;
23790                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
23791
23792                state = FADING;
23793
23794                // Kick off the fade animation
23795                host.invalidate(true);
23796            }
23797        }
23798    }
23799
23800    /**
23801     * Resuable callback for sending
23802     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
23803     */
23804    private class SendViewScrolledAccessibilityEvent implements Runnable {
23805        public volatile boolean mIsPending;
23806
23807        public void run() {
23808            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
23809            mIsPending = false;
23810        }
23811    }
23812
23813    /**
23814     * <p>
23815     * This class represents a delegate that can be registered in a {@link View}
23816     * to enhance accessibility support via composition rather via inheritance.
23817     * It is specifically targeted to widget developers that extend basic View
23818     * classes i.e. classes in package android.view, that would like their
23819     * applications to be backwards compatible.
23820     * </p>
23821     * <div class="special reference">
23822     * <h3>Developer Guides</h3>
23823     * <p>For more information about making applications accessible, read the
23824     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
23825     * developer guide.</p>
23826     * </div>
23827     * <p>
23828     * A scenario in which a developer would like to use an accessibility delegate
23829     * is overriding a method introduced in a later API version than the minimal API
23830     * version supported by the application. For example, the method
23831     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
23832     * in API version 4 when the accessibility APIs were first introduced. If a
23833     * developer would like his application to run on API version 4 devices (assuming
23834     * all other APIs used by the application are version 4 or lower) and take advantage
23835     * of this method, instead of overriding the method which would break the application's
23836     * backwards compatibility, he can override the corresponding method in this
23837     * delegate and register the delegate in the target View if the API version of
23838     * the system is high enough, i.e. the API version is the same as or higher than the API
23839     * version that introduced
23840     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
23841     * </p>
23842     * <p>
23843     * Here is an example implementation:
23844     * </p>
23845     * <code><pre><p>
23846     * if (Build.VERSION.SDK_INT >= 14) {
23847     *     // If the API version is equal of higher than the version in
23848     *     // which onInitializeAccessibilityNodeInfo was introduced we
23849     *     // register a delegate with a customized implementation.
23850     *     View view = findViewById(R.id.view_id);
23851     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
23852     *         public void onInitializeAccessibilityNodeInfo(View host,
23853     *                 AccessibilityNodeInfo info) {
23854     *             // Let the default implementation populate the info.
23855     *             super.onInitializeAccessibilityNodeInfo(host, info);
23856     *             // Set some other information.
23857     *             info.setEnabled(host.isEnabled());
23858     *         }
23859     *     });
23860     * }
23861     * </code></pre></p>
23862     * <p>
23863     * This delegate contains methods that correspond to the accessibility methods
23864     * in View. If a delegate has been specified the implementation in View hands
23865     * off handling to the corresponding method in this delegate. The default
23866     * implementation the delegate methods behaves exactly as the corresponding
23867     * method in View for the case of no accessibility delegate been set. Hence,
23868     * to customize the behavior of a View method, clients can override only the
23869     * corresponding delegate method without altering the behavior of the rest
23870     * accessibility related methods of the host view.
23871     * </p>
23872     * <p>
23873     * <strong>Note:</strong> On platform versions prior to
23874     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
23875     * views in the {@code android.widget.*} package are called <i>before</i>
23876     * host methods. This prevents certain properties such as class name from
23877     * being modified by overriding
23878     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
23879     * as any changes will be overwritten by the host class.
23880     * <p>
23881     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
23882     * methods are called <i>after</i> host methods, which all properties to be
23883     * modified without being overwritten by the host class.
23884     */
23885    public static class AccessibilityDelegate {
23886
23887        /**
23888         * Sends an accessibility event of the given type. If accessibility is not
23889         * enabled this method has no effect.
23890         * <p>
23891         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
23892         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
23893         * been set.
23894         * </p>
23895         *
23896         * @param host The View hosting the delegate.
23897         * @param eventType The type of the event to send.
23898         *
23899         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
23900         */
23901        public void sendAccessibilityEvent(View host, int eventType) {
23902            host.sendAccessibilityEventInternal(eventType);
23903        }
23904
23905        /**
23906         * Performs the specified accessibility action on the view. For
23907         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
23908         * <p>
23909         * The default implementation behaves as
23910         * {@link View#performAccessibilityAction(int, Bundle)
23911         *  View#performAccessibilityAction(int, Bundle)} for the case of
23912         *  no accessibility delegate been set.
23913         * </p>
23914         *
23915         * @param action The action to perform.
23916         * @return Whether the action was performed.
23917         *
23918         * @see View#performAccessibilityAction(int, Bundle)
23919         *      View#performAccessibilityAction(int, Bundle)
23920         */
23921        public boolean performAccessibilityAction(View host, int action, Bundle args) {
23922            return host.performAccessibilityActionInternal(action, args);
23923        }
23924
23925        /**
23926         * Sends an accessibility event. This method behaves exactly as
23927         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
23928         * empty {@link AccessibilityEvent} and does not perform a check whether
23929         * accessibility is enabled.
23930         * <p>
23931         * The default implementation behaves as
23932         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23933         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
23934         * the case of no accessibility delegate been set.
23935         * </p>
23936         *
23937         * @param host The View hosting the delegate.
23938         * @param event The event to send.
23939         *
23940         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23941         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
23942         */
23943        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
23944            host.sendAccessibilityEventUncheckedInternal(event);
23945        }
23946
23947        /**
23948         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
23949         * to its children for adding their text content to the event.
23950         * <p>
23951         * The default implementation behaves as
23952         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23953         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
23954         * the case of no accessibility delegate been set.
23955         * </p>
23956         *
23957         * @param host The View hosting the delegate.
23958         * @param event The event.
23959         * @return True if the event population was completed.
23960         *
23961         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23962         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
23963         */
23964        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23965            return host.dispatchPopulateAccessibilityEventInternal(event);
23966        }
23967
23968        /**
23969         * Gives a chance to the host View to populate the accessibility event with its
23970         * text content.
23971         * <p>
23972         * The default implementation behaves as
23973         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
23974         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
23975         * the case of no accessibility delegate been set.
23976         * </p>
23977         *
23978         * @param host The View hosting the delegate.
23979         * @param event The accessibility event which to populate.
23980         *
23981         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
23982         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
23983         */
23984        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
23985            host.onPopulateAccessibilityEventInternal(event);
23986        }
23987
23988        /**
23989         * Initializes an {@link AccessibilityEvent} with information about the
23990         * the host View which is the event source.
23991         * <p>
23992         * The default implementation behaves as
23993         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
23994         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
23995         * the case of no accessibility delegate been set.
23996         * </p>
23997         *
23998         * @param host The View hosting the delegate.
23999         * @param event The event to initialize.
24000         *
24001         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
24002         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
24003         */
24004        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
24005            host.onInitializeAccessibilityEventInternal(event);
24006        }
24007
24008        /**
24009         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
24010         * <p>
24011         * The default implementation behaves as
24012         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
24013         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
24014         * the case of no accessibility delegate been set.
24015         * </p>
24016         *
24017         * @param host The View hosting the delegate.
24018         * @param info The instance to initialize.
24019         *
24020         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
24021         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
24022         */
24023        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
24024            host.onInitializeAccessibilityNodeInfoInternal(info);
24025        }
24026
24027        /**
24028         * Called when a child of the host View has requested sending an
24029         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
24030         * to augment the event.
24031         * <p>
24032         * The default implementation behaves as
24033         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
24034         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
24035         * the case of no accessibility delegate been set.
24036         * </p>
24037         *
24038         * @param host The View hosting the delegate.
24039         * @param child The child which requests sending the event.
24040         * @param event The event to be sent.
24041         * @return True if the event should be sent
24042         *
24043         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
24044         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
24045         */
24046        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
24047                AccessibilityEvent event) {
24048            return host.onRequestSendAccessibilityEventInternal(child, event);
24049        }
24050
24051        /**
24052         * Gets the provider for managing a virtual view hierarchy rooted at this View
24053         * and reported to {@link android.accessibilityservice.AccessibilityService}s
24054         * that explore the window content.
24055         * <p>
24056         * The default implementation behaves as
24057         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
24058         * the case of no accessibility delegate been set.
24059         * </p>
24060         *
24061         * @return The provider.
24062         *
24063         * @see AccessibilityNodeProvider
24064         */
24065        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
24066            return null;
24067        }
24068
24069        /**
24070         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
24071         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
24072         * This method is responsible for obtaining an accessibility node info from a
24073         * pool of reusable instances and calling
24074         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
24075         * view to initialize the former.
24076         * <p>
24077         * <strong>Note:</strong> The client is responsible for recycling the obtained
24078         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
24079         * creation.
24080         * </p>
24081         * <p>
24082         * The default implementation behaves as
24083         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
24084         * the case of no accessibility delegate been set.
24085         * </p>
24086         * @return A populated {@link AccessibilityNodeInfo}.
24087         *
24088         * @see AccessibilityNodeInfo
24089         *
24090         * @hide
24091         */
24092        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
24093            return host.createAccessibilityNodeInfoInternal();
24094        }
24095    }
24096
24097    private class MatchIdPredicate implements Predicate<View> {
24098        public int mId;
24099
24100        @Override
24101        public boolean apply(View view) {
24102            return (view.mID == mId);
24103        }
24104    }
24105
24106    private class MatchLabelForPredicate implements Predicate<View> {
24107        private int mLabeledId;
24108
24109        @Override
24110        public boolean apply(View view) {
24111            return (view.mLabelForId == mLabeledId);
24112        }
24113    }
24114
24115    private class SendViewStateChangedAccessibilityEvent implements Runnable {
24116        private int mChangeTypes = 0;
24117        private boolean mPosted;
24118        private boolean mPostedWithDelay;
24119        private long mLastEventTimeMillis;
24120
24121        @Override
24122        public void run() {
24123            mPosted = false;
24124            mPostedWithDelay = false;
24125            mLastEventTimeMillis = SystemClock.uptimeMillis();
24126            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
24127                final AccessibilityEvent event = AccessibilityEvent.obtain();
24128                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
24129                event.setContentChangeTypes(mChangeTypes);
24130                sendAccessibilityEventUnchecked(event);
24131            }
24132            mChangeTypes = 0;
24133        }
24134
24135        public void runOrPost(int changeType) {
24136            mChangeTypes |= changeType;
24137
24138            // If this is a live region or the child of a live region, collect
24139            // all events from this frame and send them on the next frame.
24140            if (inLiveRegion()) {
24141                // If we're already posted with a delay, remove that.
24142                if (mPostedWithDelay) {
24143                    removeCallbacks(this);
24144                    mPostedWithDelay = false;
24145                }
24146                // Only post if we're not already posted.
24147                if (!mPosted) {
24148                    post(this);
24149                    mPosted = true;
24150                }
24151                return;
24152            }
24153
24154            if (mPosted) {
24155                return;
24156            }
24157
24158            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
24159            final long minEventIntevalMillis =
24160                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
24161            if (timeSinceLastMillis >= minEventIntevalMillis) {
24162                removeCallbacks(this);
24163                run();
24164            } else {
24165                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
24166                mPostedWithDelay = true;
24167            }
24168        }
24169    }
24170
24171    private boolean inLiveRegion() {
24172        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
24173            return true;
24174        }
24175
24176        ViewParent parent = getParent();
24177        while (parent instanceof View) {
24178            if (((View) parent).getAccessibilityLiveRegion()
24179                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
24180                return true;
24181            }
24182            parent = parent.getParent();
24183        }
24184
24185        return false;
24186    }
24187
24188    /**
24189     * Dump all private flags in readable format, useful for documentation and
24190     * sanity checking.
24191     */
24192    private static void dumpFlags() {
24193        final HashMap<String, String> found = Maps.newHashMap();
24194        try {
24195            for (Field field : View.class.getDeclaredFields()) {
24196                final int modifiers = field.getModifiers();
24197                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
24198                    if (field.getType().equals(int.class)) {
24199                        final int value = field.getInt(null);
24200                        dumpFlag(found, field.getName(), value);
24201                    } else if (field.getType().equals(int[].class)) {
24202                        final int[] values = (int[]) field.get(null);
24203                        for (int i = 0; i < values.length; i++) {
24204                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
24205                        }
24206                    }
24207                }
24208            }
24209        } catch (IllegalAccessException e) {
24210            throw new RuntimeException(e);
24211        }
24212
24213        final ArrayList<String> keys = Lists.newArrayList();
24214        keys.addAll(found.keySet());
24215        Collections.sort(keys);
24216        for (String key : keys) {
24217            Log.d(VIEW_LOG_TAG, found.get(key));
24218        }
24219    }
24220
24221    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
24222        // Sort flags by prefix, then by bits, always keeping unique keys
24223        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
24224        final int prefix = name.indexOf('_');
24225        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
24226        final String output = bits + " " + name;
24227        found.put(key, output);
24228    }
24229
24230    /** {@hide} */
24231    public void encode(@NonNull ViewHierarchyEncoder stream) {
24232        stream.beginObject(this);
24233        encodeProperties(stream);
24234        stream.endObject();
24235    }
24236
24237    /** {@hide} */
24238    @CallSuper
24239    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
24240        Object resolveId = ViewDebug.resolveId(getContext(), mID);
24241        if (resolveId instanceof String) {
24242            stream.addProperty("id", (String) resolveId);
24243        } else {
24244            stream.addProperty("id", mID);
24245        }
24246
24247        stream.addProperty("misc:transformation.alpha",
24248                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
24249        stream.addProperty("misc:transitionName", getTransitionName());
24250
24251        // layout
24252        stream.addProperty("layout:left", mLeft);
24253        stream.addProperty("layout:right", mRight);
24254        stream.addProperty("layout:top", mTop);
24255        stream.addProperty("layout:bottom", mBottom);
24256        stream.addProperty("layout:width", getWidth());
24257        stream.addProperty("layout:height", getHeight());
24258        stream.addProperty("layout:layoutDirection", getLayoutDirection());
24259        stream.addProperty("layout:layoutRtl", isLayoutRtl());
24260        stream.addProperty("layout:hasTransientState", hasTransientState());
24261        stream.addProperty("layout:baseline", getBaseline());
24262
24263        // layout params
24264        ViewGroup.LayoutParams layoutParams = getLayoutParams();
24265        if (layoutParams != null) {
24266            stream.addPropertyKey("layoutParams");
24267            layoutParams.encode(stream);
24268        }
24269
24270        // scrolling
24271        stream.addProperty("scrolling:scrollX", mScrollX);
24272        stream.addProperty("scrolling:scrollY", mScrollY);
24273
24274        // padding
24275        stream.addProperty("padding:paddingLeft", mPaddingLeft);
24276        stream.addProperty("padding:paddingRight", mPaddingRight);
24277        stream.addProperty("padding:paddingTop", mPaddingTop);
24278        stream.addProperty("padding:paddingBottom", mPaddingBottom);
24279        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
24280        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
24281        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
24282        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
24283        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
24284
24285        // measurement
24286        stream.addProperty("measurement:minHeight", mMinHeight);
24287        stream.addProperty("measurement:minWidth", mMinWidth);
24288        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
24289        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
24290
24291        // drawing
24292        stream.addProperty("drawing:elevation", getElevation());
24293        stream.addProperty("drawing:translationX", getTranslationX());
24294        stream.addProperty("drawing:translationY", getTranslationY());
24295        stream.addProperty("drawing:translationZ", getTranslationZ());
24296        stream.addProperty("drawing:rotation", getRotation());
24297        stream.addProperty("drawing:rotationX", getRotationX());
24298        stream.addProperty("drawing:rotationY", getRotationY());
24299        stream.addProperty("drawing:scaleX", getScaleX());
24300        stream.addProperty("drawing:scaleY", getScaleY());
24301        stream.addProperty("drawing:pivotX", getPivotX());
24302        stream.addProperty("drawing:pivotY", getPivotY());
24303        stream.addProperty("drawing:opaque", isOpaque());
24304        stream.addProperty("drawing:alpha", getAlpha());
24305        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
24306        stream.addProperty("drawing:shadow", hasShadow());
24307        stream.addProperty("drawing:solidColor", getSolidColor());
24308        stream.addProperty("drawing:layerType", mLayerType);
24309        stream.addProperty("drawing:willNotDraw", willNotDraw());
24310        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
24311        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
24312        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
24313        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
24314
24315        // focus
24316        stream.addProperty("focus:hasFocus", hasFocus());
24317        stream.addProperty("focus:isFocused", isFocused());
24318        stream.addProperty("focus:isFocusable", isFocusable());
24319        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
24320
24321        stream.addProperty("misc:clickable", isClickable());
24322        stream.addProperty("misc:pressed", isPressed());
24323        stream.addProperty("misc:selected", isSelected());
24324        stream.addProperty("misc:touchMode", isInTouchMode());
24325        stream.addProperty("misc:hovered", isHovered());
24326        stream.addProperty("misc:activated", isActivated());
24327
24328        stream.addProperty("misc:visibility", getVisibility());
24329        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
24330        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
24331
24332        stream.addProperty("misc:enabled", isEnabled());
24333        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
24334        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
24335
24336        // theme attributes
24337        Resources.Theme theme = getContext().getTheme();
24338        if (theme != null) {
24339            stream.addPropertyKey("theme");
24340            theme.encode(stream);
24341        }
24342
24343        // view attribute information
24344        int n = mAttributes != null ? mAttributes.length : 0;
24345        stream.addProperty("meta:__attrCount__", n/2);
24346        for (int i = 0; i < n; i += 2) {
24347            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
24348        }
24349
24350        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
24351
24352        // text
24353        stream.addProperty("text:textDirection", getTextDirection());
24354        stream.addProperty("text:textAlignment", getTextAlignment());
24355
24356        // accessibility
24357        CharSequence contentDescription = getContentDescription();
24358        stream.addProperty("accessibility:contentDescription",
24359                contentDescription == null ? "" : contentDescription.toString());
24360        stream.addProperty("accessibility:labelFor", getLabelFor());
24361        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
24362    }
24363
24364    /**
24365     * Determine if this view is rendered on a round wearable device and is the main view
24366     * on the screen.
24367     */
24368    private boolean shouldDrawRoundScrollbar() {
24369        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
24370            return false;
24371        }
24372
24373        final View rootView = getRootView();
24374        final WindowInsets insets = getRootWindowInsets();
24375
24376        int height = getHeight();
24377        int width = getWidth();
24378        int displayHeight = rootView.getHeight();
24379        int displayWidth = rootView.getWidth();
24380
24381        if (height != displayHeight || width != displayWidth) {
24382            return false;
24383        }
24384
24385        getLocationOnScreen(mAttachInfo.mTmpLocation);
24386        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
24387                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
24388    }
24389
24390    /**
24391     * Sets the tooltip text which will be displayed in a small popup next to the view.
24392     * <p>
24393     * The tooltip will be displayed:
24394     * <li>On long click, unless is not handled otherwise (by OnLongClickListener or a context
24395     * menu). </li>
24396     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
24397     *
24398     * @param tooltip the tooltip text, or null if no tooltip is required
24399     */
24400    public final void setTooltip(@Nullable CharSequence tooltip) {
24401        if (TextUtils.isEmpty(tooltip)) {
24402            setFlags(0, TOOLTIP);
24403            hideTooltip();
24404            mTooltipInfo = null;
24405        } else {
24406            setFlags(TOOLTIP, TOOLTIP);
24407            if (mTooltipInfo == null) {
24408                mTooltipInfo = new TooltipInfo();
24409                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
24410                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
24411            }
24412            mTooltipInfo.mTooltip = tooltip;
24413            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
24414                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltip);
24415            }
24416        }
24417    }
24418
24419    /**
24420     * Returns the view's tooltip text.
24421     *
24422     * @return the tooltip text
24423     */
24424    @Nullable
24425    public final CharSequence getTooltip() {
24426        return mTooltipInfo != null ? mTooltipInfo.mTooltip : null;
24427    }
24428
24429    private boolean showTooltip(int x, int y, boolean fromLongClick) {
24430        if (mAttachInfo == null) {
24431            return false;
24432        }
24433        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
24434            return false;
24435        }
24436        final CharSequence tooltipText = getTooltip();
24437        if (TextUtils.isEmpty(tooltipText)) {
24438            return false;
24439        }
24440        hideTooltip();
24441        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
24442        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
24443        mTooltipInfo.mTooltipPopup.show(this, x, y, tooltipText);
24444        mAttachInfo.mTooltipHost = this;
24445        return true;
24446    }
24447
24448    void hideTooltip() {
24449        if (mTooltipInfo == null) {
24450            return;
24451        }
24452        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
24453        if (mTooltipInfo.mTooltipPopup == null) {
24454            return;
24455        }
24456        mTooltipInfo.mTooltipPopup.hide();
24457        mTooltipInfo.mTooltipPopup = null;
24458        mTooltipInfo.mTooltipFromLongClick = false;
24459        if (mAttachInfo != null) {
24460            mAttachInfo.mTooltipHost = null;
24461        }
24462    }
24463
24464    private boolean showLongClickTooltip(int x, int y) {
24465        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
24466        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
24467        return showTooltip(x, y, true);
24468    }
24469
24470    private void showHoverTooltip() {
24471        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
24472    }
24473
24474    boolean dispatchTooltipHoverEvent(MotionEvent event) {
24475        if (mTooltipInfo == null) {
24476            return false;
24477        }
24478        switch(event.getAction()) {
24479            case MotionEvent.ACTION_HOVER_MOVE:
24480                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
24481                    break;
24482                }
24483                if (!mTooltipInfo.mTooltipFromLongClick) {
24484                    if (mTooltipInfo.mTooltipPopup == null) {
24485                        // Schedule showing the tooltip after a timeout.
24486                        mTooltipInfo.mAnchorX = (int) event.getX();
24487                        mTooltipInfo.mAnchorY = (int) event.getY();
24488                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
24489                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
24490                                ViewConfiguration.getHoverTooltipShowTimeout());
24491                    }
24492
24493                    // Hide hover-triggered tooltip after a period of inactivity.
24494                    // Match the timeout used by NativeInputManager to hide the mouse pointer
24495                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
24496                    final int timeout;
24497                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
24498                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
24499                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
24500                    } else {
24501                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
24502                    }
24503                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
24504                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
24505                }
24506                return true;
24507
24508            case MotionEvent.ACTION_HOVER_EXIT:
24509                if (!mTooltipInfo.mTooltipFromLongClick) {
24510                    hideTooltip();
24511                }
24512                break;
24513        }
24514        return false;
24515    }
24516
24517    void handleTooltipKey(KeyEvent event) {
24518        switch (event.getAction()) {
24519            case KeyEvent.ACTION_DOWN:
24520                if (event.getRepeatCount() == 0) {
24521                    hideTooltip();
24522                }
24523                break;
24524
24525            case KeyEvent.ACTION_UP:
24526                handleTooltipUp();
24527                break;
24528        }
24529    }
24530
24531    private void handleTooltipUp() {
24532        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
24533            return;
24534        }
24535        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
24536        postDelayed(mTooltipInfo.mHideTooltipRunnable,
24537                ViewConfiguration.getLongPressTooltipHideTimeout());
24538    }
24539
24540    /**
24541     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
24542     * is not showing.
24543     * @hide
24544     */
24545    @TestApi
24546    public View getTooltipView() {
24547        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
24548            return null;
24549        }
24550        return mTooltipInfo.mTooltipPopup.getContentView();
24551    }
24552}
24553