View.java revision 04b926a68b85d9b93f7de2647f9f4770532b2e0f
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.app.Application.OnProvideAssistDataListener;
43import android.content.ClipData;
44import android.content.Context;
45import android.content.ContextWrapper;
46import android.content.Intent;
47import android.content.res.ColorStateList;
48import android.content.res.Configuration;
49import android.content.res.Resources;
50import android.content.res.TypedArray;
51import android.graphics.Bitmap;
52import android.graphics.Canvas;
53import android.graphics.Color;
54import android.graphics.Insets;
55import android.graphics.Interpolator;
56import android.graphics.LinearGradient;
57import android.graphics.Matrix;
58import android.graphics.Outline;
59import android.graphics.Paint;
60import android.graphics.PixelFormat;
61import android.graphics.Point;
62import android.graphics.PorterDuff;
63import android.graphics.PorterDuffXfermode;
64import android.graphics.Rect;
65import android.graphics.RectF;
66import android.graphics.Region;
67import android.graphics.Shader;
68import android.graphics.drawable.ColorDrawable;
69import android.graphics.drawable.Drawable;
70import android.hardware.display.DisplayManagerGlobal;
71import android.os.Build.VERSION_CODES;
72import android.os.Bundle;
73import android.os.Handler;
74import android.os.IBinder;
75import android.os.Parcel;
76import android.os.Parcelable;
77import android.os.RemoteException;
78import android.os.SystemClock;
79import android.os.SystemProperties;
80import android.os.Trace;
81import android.text.TextUtils;
82import android.util.AttributeSet;
83import android.util.FloatProperty;
84import android.util.LayoutDirection;
85import android.util.Log;
86import android.util.LongSparseLongArray;
87import android.util.Pools.SynchronizedPool;
88import android.util.Property;
89import android.util.SparseArray;
90import android.util.StateSet;
91import android.util.SuperNotCalledException;
92import android.util.TypedValue;
93import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
94import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
95import android.view.AccessibilityIterators.TextSegmentIterator;
96import android.view.AccessibilityIterators.WordTextSegmentIterator;
97import android.view.ContextMenu.ContextMenuInfo;
98import android.view.accessibility.AccessibilityEvent;
99import android.view.accessibility.AccessibilityEventSource;
100import android.view.accessibility.AccessibilityManager;
101import android.view.accessibility.AccessibilityNodeInfo;
102import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
103import android.view.accessibility.AccessibilityNodeProvider;
104import android.view.animation.Animation;
105import android.view.animation.AnimationUtils;
106import android.view.animation.Transformation;
107import android.view.autofill.AutoFillType;
108import android.view.autofill.AutoFillValue;
109import android.view.autofill.VirtualViewDelegate;
110import android.view.inputmethod.EditorInfo;
111import android.view.inputmethod.InputConnection;
112import android.view.inputmethod.InputMethodManager;
113import android.widget.Checkable;
114import android.widget.FrameLayout;
115import android.widget.ScrollBarDrawable;
116
117import com.android.internal.R;
118import com.android.internal.util.Predicate;
119import com.android.internal.view.TooltipPopup;
120import com.android.internal.view.menu.MenuBuilder;
121import com.android.internal.widget.ScrollBarUtils;
122
123import com.google.android.collect.Lists;
124import com.google.android.collect.Maps;
125
126import java.lang.annotation.Retention;
127import java.lang.annotation.RetentionPolicy;
128import java.lang.ref.WeakReference;
129import java.lang.reflect.Field;
130import java.lang.reflect.InvocationTargetException;
131import java.lang.reflect.Method;
132import java.lang.reflect.Modifier;
133import java.util.ArrayList;
134import java.util.Arrays;
135import java.util.Collection;
136import java.util.Collections;
137import java.util.HashMap;
138import java.util.List;
139import java.util.Locale;
140import java.util.Map;
141import java.util.concurrent.CopyOnWriteArrayList;
142import java.util.concurrent.atomic.AtomicInteger;
143
144/**
145 * <p>
146 * This class represents the basic building block for user interface components. A View
147 * occupies a rectangular area on the screen and is responsible for drawing and
148 * event handling. View is the base class for <em>widgets</em>, which are
149 * used to create interactive UI components (buttons, text fields, etc.). The
150 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
151 * are invisible containers that hold other Views (or other ViewGroups) and define
152 * their layout properties.
153 * </p>
154 *
155 * <div class="special reference">
156 * <h3>Developer Guides</h3>
157 * <p>For information about using this class to develop your application's user interface,
158 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
159 * </div>
160 *
161 * <a name="Using"></a>
162 * <h3>Using Views</h3>
163 * <p>
164 * All of the views in a window are arranged in a single tree. You can add views
165 * either from code or by specifying a tree of views in one or more XML layout
166 * files. There are many specialized subclasses of views that act as controls or
167 * are capable of displaying text, images, or other content.
168 * </p>
169 * <p>
170 * Once you have created a tree of views, there are typically a few types of
171 * common operations you may wish to perform:
172 * <ul>
173 * <li><strong>Set properties:</strong> for example setting the text of a
174 * {@link android.widget.TextView}. The available properties and the methods
175 * that set them will vary among the different subclasses of views. Note that
176 * properties that are known at build time can be set in the XML layout
177 * files.</li>
178 * <li><strong>Set focus:</strong> The framework will handle moving focus in
179 * response to user input. To force focus to a specific view, call
180 * {@link #requestFocus}.</li>
181 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
182 * that will be notified when something interesting happens to the view. For
183 * example, all views will let you set a listener to be notified when the view
184 * gains or loses focus. You can register such a listener using
185 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
186 * Other view subclasses offer more specialized listeners. For example, a Button
187 * exposes a listener to notify clients when the button is clicked.</li>
188 * <li><strong>Set visibility:</strong> You can hide or show views using
189 * {@link #setVisibility(int)}.</li>
190 * </ul>
191 * </p>
192 * <p><em>
193 * Note: The Android framework is responsible for measuring, laying out and
194 * drawing views. You should not call methods that perform these actions on
195 * views yourself unless you are actually implementing a
196 * {@link android.view.ViewGroup}.
197 * </em></p>
198 *
199 * <a name="Lifecycle"></a>
200 * <h3>Implementing a Custom View</h3>
201 *
202 * <p>
203 * To implement a custom view, you will usually begin by providing overrides for
204 * some of the standard methods that the framework calls on all views. You do
205 * not need to override all of these methods. In fact, you can start by just
206 * overriding {@link #onDraw(android.graphics.Canvas)}.
207 * <table border="2" width="85%" align="center" cellpadding="5">
208 *     <thead>
209 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
210 *     </thead>
211 *
212 *     <tbody>
213 *     <tr>
214 *         <td rowspan="2">Creation</td>
215 *         <td>Constructors</td>
216 *         <td>There is a form of the constructor that are called when the view
217 *         is created from code and a form that is called when the view is
218 *         inflated from a layout file. The second form should parse and apply
219 *         any attributes defined in the layout file.
220 *         </td>
221 *     </tr>
222 *     <tr>
223 *         <td><code>{@link #onFinishInflate()}</code></td>
224 *         <td>Called after a view and all of its children has been inflated
225 *         from XML.</td>
226 *     </tr>
227 *
228 *     <tr>
229 *         <td rowspan="3">Layout</td>
230 *         <td><code>{@link #onMeasure(int, int)}</code></td>
231 *         <td>Called to determine the size requirements for this view and all
232 *         of its children.
233 *         </td>
234 *     </tr>
235 *     <tr>
236 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
237 *         <td>Called when this view should assign a size and position to all
238 *         of its children.
239 *         </td>
240 *     </tr>
241 *     <tr>
242 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
243 *         <td>Called when the size of this view has changed.
244 *         </td>
245 *     </tr>
246 *
247 *     <tr>
248 *         <td>Drawing</td>
249 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
250 *         <td>Called when the view should render its content.
251 *         </td>
252 *     </tr>
253 *
254 *     <tr>
255 *         <td rowspan="4">Event processing</td>
256 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
257 *         <td>Called when a new hardware key event occurs.
258 *         </td>
259 *     </tr>
260 *     <tr>
261 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
262 *         <td>Called when a hardware key up event occurs.
263 *         </td>
264 *     </tr>
265 *     <tr>
266 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
267 *         <td>Called when a trackball motion event occurs.
268 *         </td>
269 *     </tr>
270 *     <tr>
271 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
272 *         <td>Called when a touch screen motion event occurs.
273 *         </td>
274 *     </tr>
275 *
276 *     <tr>
277 *         <td rowspan="2">Focus</td>
278 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
279 *         <td>Called when the view gains or loses focus.
280 *         </td>
281 *     </tr>
282 *
283 *     <tr>
284 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
285 *         <td>Called when the window containing the view gains or loses focus.
286 *         </td>
287 *     </tr>
288 *
289 *     <tr>
290 *         <td rowspan="3">Attaching</td>
291 *         <td><code>{@link #onAttachedToWindow()}</code></td>
292 *         <td>Called when the view is attached to a window.
293 *         </td>
294 *     </tr>
295 *
296 *     <tr>
297 *         <td><code>{@link #onDetachedFromWindow}</code></td>
298 *         <td>Called when the view is detached from its window.
299 *         </td>
300 *     </tr>
301 *
302 *     <tr>
303 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
304 *         <td>Called when the visibility of the window containing the view
305 *         has changed.
306 *         </td>
307 *     </tr>
308 *     </tbody>
309 *
310 * </table>
311 * </p>
312 *
313 * <a name="IDs"></a>
314 * <h3>IDs</h3>
315 * Views may have an integer id associated with them. These ids are typically
316 * assigned in the layout XML files, and are used to find specific views within
317 * the view tree. A common pattern is to:
318 * <ul>
319 * <li>Define a Button in the layout file and assign it a unique ID.
320 * <pre>
321 * &lt;Button
322 *     android:id="@+id/my_button"
323 *     android:layout_width="wrap_content"
324 *     android:layout_height="wrap_content"
325 *     android:text="@string/my_button_text"/&gt;
326 * </pre></li>
327 * <li>From the onCreate method of an Activity, find the Button
328 * <pre class="prettyprint">
329 *      Button myButton = (Button) findViewById(R.id.my_button);
330 * </pre></li>
331 * </ul>
332 * <p>
333 * View IDs need not be unique throughout the tree, but it is good practice to
334 * ensure that they are at least unique within the part of the tree you are
335 * searching.
336 * </p>
337 *
338 * <a name="Position"></a>
339 * <h3>Position</h3>
340 * <p>
341 * The geometry of a view is that of a rectangle. A view has a location,
342 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
343 * two dimensions, expressed as a width and a height. The unit for location
344 * and dimensions is the pixel.
345 * </p>
346 *
347 * <p>
348 * It is possible to retrieve the location of a view by invoking the methods
349 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
350 * coordinate of the rectangle representing the view. The latter returns the
351 * top, or Y, coordinate of the rectangle representing the view. These methods
352 * both return the location of the view relative to its parent. For instance,
353 * when getLeft() returns 20, that means the view is located 20 pixels to the
354 * right of the left edge of its direct parent.
355 * </p>
356 *
357 * <p>
358 * In addition, several convenience methods are offered to avoid unnecessary
359 * computations, namely {@link #getRight()} and {@link #getBottom()}.
360 * These methods return the coordinates of the right and bottom edges of the
361 * rectangle representing the view. For instance, calling {@link #getRight()}
362 * is similar to the following computation: <code>getLeft() + getWidth()</code>
363 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
364 * </p>
365 *
366 * <a name="SizePaddingMargins"></a>
367 * <h3>Size, padding and margins</h3>
368 * <p>
369 * The size of a view is expressed with a width and a height. A view actually
370 * possess two pairs of width and height values.
371 * </p>
372 *
373 * <p>
374 * The first pair is known as <em>measured width</em> and
375 * <em>measured height</em>. These dimensions define how big a view wants to be
376 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
377 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
378 * and {@link #getMeasuredHeight()}.
379 * </p>
380 *
381 * <p>
382 * The second pair is simply known as <em>width</em> and <em>height</em>, or
383 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
384 * dimensions define the actual size of the view on screen, at drawing time and
385 * after layout. These values may, but do not have to, be different from the
386 * measured width and height. The width and height can be obtained by calling
387 * {@link #getWidth()} and {@link #getHeight()}.
388 * </p>
389 *
390 * <p>
391 * To measure its dimensions, a view takes into account its padding. The padding
392 * is expressed in pixels for the left, top, right and bottom parts of the view.
393 * Padding can be used to offset the content of the view by a specific amount of
394 * pixels. For instance, a left padding of 2 will push the view's content by
395 * 2 pixels to the right of the left edge. Padding can be set using the
396 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
397 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
398 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
399 * {@link #getPaddingEnd()}.
400 * </p>
401 *
402 * <p>
403 * Even though a view can define a padding, it does not provide any support for
404 * margins. However, view groups provide such a support. Refer to
405 * {@link android.view.ViewGroup} and
406 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
407 * </p>
408 *
409 * <a name="Layout"></a>
410 * <h3>Layout</h3>
411 * <p>
412 * Layout is a two pass process: a measure pass and a layout pass. The measuring
413 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
414 * of the view tree. Each view pushes dimension specifications down the tree
415 * during the recursion. At the end of the measure pass, every view has stored
416 * its measurements. The second pass happens in
417 * {@link #layout(int,int,int,int)} and is also top-down. During
418 * this pass each parent is responsible for positioning all of its children
419 * using the sizes computed in the measure pass.
420 * </p>
421 *
422 * <p>
423 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
424 * {@link #getMeasuredHeight()} values must be set, along with those for all of
425 * that view's descendants. A view's measured width and measured height values
426 * must respect the constraints imposed by the view's parents. This guarantees
427 * that at the end of the measure pass, all parents accept all of their
428 * children's measurements. A parent view may call measure() more than once on
429 * its children. For example, the parent may measure each child once with
430 * unspecified dimensions to find out how big they want to be, then call
431 * measure() on them again with actual numbers if the sum of all the children's
432 * unconstrained sizes is too big or too small.
433 * </p>
434 *
435 * <p>
436 * The measure pass uses two classes to communicate dimensions. The
437 * {@link MeasureSpec} class is used by views to tell their parents how they
438 * want to be measured and positioned. The base LayoutParams class just
439 * describes how big the view wants to be for both width and height. For each
440 * dimension, it can specify one of:
441 * <ul>
442 * <li> an exact number
443 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
444 * (minus padding)
445 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
446 * enclose its content (plus padding).
447 * </ul>
448 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
449 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
450 * an X and Y value.
451 * </p>
452 *
453 * <p>
454 * MeasureSpecs are used to push requirements down the tree from parent to
455 * child. A MeasureSpec can be in one of three modes:
456 * <ul>
457 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
458 * of a child view. For example, a LinearLayout may call measure() on its child
459 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
460 * tall the child view wants to be given a width of 240 pixels.
461 * <li>EXACTLY: This is used by the parent to impose an exact size on the
462 * child. The child must use this size, and guarantee that all of its
463 * descendants will fit within this size.
464 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
465 * child. The child must guarantee that it and all of its descendants will fit
466 * within this size.
467 * </ul>
468 * </p>
469 *
470 * <p>
471 * To initiate a layout, call {@link #requestLayout}. This method is typically
472 * called by a view on itself when it believes that is can no longer fit within
473 * its current bounds.
474 * </p>
475 *
476 * <a name="Drawing"></a>
477 * <h3>Drawing</h3>
478 * <p>
479 * Drawing is handled by walking the tree and recording the drawing commands of
480 * any View that needs to update. After this, the drawing commands of the
481 * entire tree are issued to screen, clipped to the newly damaged area.
482 * </p>
483 *
484 * <p>
485 * The tree is largely recorded and drawn in order, with parents drawn before
486 * (i.e., behind) their children, with siblings drawn in the order they appear
487 * in the tree. If you set a background drawable for a View, then the View will
488 * draw it before calling back to its <code>onDraw()</code> method. The child
489 * drawing order can be overridden with
490 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
491 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
492 * </p>
493 *
494 * <p>
495 * To force a view to draw, call {@link #invalidate()}.
496 * </p>
497 *
498 * <a name="EventHandlingThreading"></a>
499 * <h3>Event Handling and Threading</h3>
500 * <p>
501 * The basic cycle of a view is as follows:
502 * <ol>
503 * <li>An event comes in and is dispatched to the appropriate view. The view
504 * handles the event and notifies any listeners.</li>
505 * <li>If in the course of processing the event, the view's bounds may need
506 * to be changed, the view will call {@link #requestLayout()}.</li>
507 * <li>Similarly, if in the course of processing the event the view's appearance
508 * may need to be changed, the view will call {@link #invalidate()}.</li>
509 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
510 * the framework will take care of measuring, laying out, and drawing the tree
511 * as appropriate.</li>
512 * </ol>
513 * </p>
514 *
515 * <p><em>Note: The entire view tree is single threaded. You must always be on
516 * the UI thread when calling any method on any view.</em>
517 * If you are doing work on other threads and want to update the state of a view
518 * from that thread, you should use a {@link Handler}.
519 * </p>
520 *
521 * <a name="FocusHandling"></a>
522 * <h3>Focus Handling</h3>
523 * <p>
524 * The framework will handle routine focus movement in response to user input.
525 * This includes changing the focus as views are removed or hidden, or as new
526 * views become available. Views indicate their willingness to take focus
527 * through the {@link #isFocusable} method. To change whether a view can take
528 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
529 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
530 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
531 * </p>
532 * <p>
533 * Focus movement is based on an algorithm which finds the nearest neighbor in a
534 * given direction. In rare cases, the default algorithm may not match the
535 * intended behavior of the developer. In these situations, you can provide
536 * explicit overrides by using these XML attributes in the layout file:
537 * <pre>
538 * nextFocusDown
539 * nextFocusLeft
540 * nextFocusRight
541 * nextFocusUp
542 * </pre>
543 * </p>
544 *
545 *
546 * <p>
547 * To get a particular view to take focus, call {@link #requestFocus()}.
548 * </p>
549 *
550 * <a name="TouchMode"></a>
551 * <h3>Touch Mode</h3>
552 * <p>
553 * When a user is navigating a user interface via directional keys such as a D-pad, it is
554 * necessary to give focus to actionable items such as buttons so the user can see
555 * what will take input.  If the device has touch capabilities, however, and the user
556 * begins interacting with the interface by touching it, it is no longer necessary to
557 * always highlight, or give focus to, a particular view.  This motivates a mode
558 * for interaction named 'touch mode'.
559 * </p>
560 * <p>
561 * For a touch capable device, once the user touches the screen, the device
562 * will enter touch mode.  From this point onward, only views for which
563 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
564 * Other views that are touchable, like buttons, will not take focus when touched; they will
565 * only fire the on click listeners.
566 * </p>
567 * <p>
568 * Any time a user hits a directional key, such as a D-pad direction, the view device will
569 * exit touch mode, and find a view to take focus, so that the user may resume interacting
570 * with the user interface without touching the screen again.
571 * </p>
572 * <p>
573 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
574 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
575 * </p>
576 *
577 * <a name="Scrolling"></a>
578 * <h3>Scrolling</h3>
579 * <p>
580 * The framework provides basic support for views that wish to internally
581 * scroll their content. This includes keeping track of the X and Y scroll
582 * offset as well as mechanisms for drawing scrollbars. See
583 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
584 * {@link #awakenScrollBars()} for more details.
585 * </p>
586 *
587 * <a name="Tags"></a>
588 * <h3>Tags</h3>
589 * <p>
590 * Unlike IDs, tags are not used to identify views. Tags are essentially an
591 * extra piece of information that can be associated with a view. They are most
592 * often used as a convenience to store data related to views in the views
593 * themselves rather than by putting them in a separate structure.
594 * </p>
595 * <p>
596 * Tags may be specified with character sequence values in layout XML as either
597 * a single tag using the {@link android.R.styleable#View_tag android:tag}
598 * attribute or multiple tags using the {@code <tag>} child element:
599 * <pre>
600 *     &ltView ...
601 *           android:tag="@string/mytag_value" /&gt;
602 *     &ltView ...&gt;
603 *         &lttag android:id="@+id/mytag"
604 *              android:value="@string/mytag_value" /&gt;
605 *     &lt/View>
606 * </pre>
607 * </p>
608 * <p>
609 * Tags may also be specified with arbitrary objects from code using
610 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
611 * </p>
612 *
613 * <a name="Themes"></a>
614 * <h3>Themes</h3>
615 * <p>
616 * By default, Views are created using the theme of the Context object supplied
617 * to their constructor; however, a different theme may be specified by using
618 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
619 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
620 * code.
621 * </p>
622 * <p>
623 * When the {@link android.R.styleable#View_theme android:theme} attribute is
624 * used in XML, the specified theme is applied on top of the inflation
625 * context's theme (see {@link LayoutInflater}) and used for the view itself as
626 * well as any child elements.
627 * </p>
628 * <p>
629 * In the following example, both views will be created using the Material dark
630 * color scheme; however, because an overlay theme is used which only defines a
631 * subset of attributes, the value of
632 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
633 * the inflation context's theme (e.g. the Activity theme) will be preserved.
634 * <pre>
635 *     &ltLinearLayout
636 *             ...
637 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
638 *         &ltView ...&gt;
639 *     &lt/LinearLayout&gt;
640 * </pre>
641 * </p>
642 *
643 * <a name="Properties"></a>
644 * <h3>Properties</h3>
645 * <p>
646 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
647 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
648 * available both in the {@link Property} form as well as in similarly-named setter/getter
649 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
650 * be used to set persistent state associated with these rendering-related properties on the view.
651 * The properties and methods can also be used in conjunction with
652 * {@link android.animation.Animator Animator}-based animations, described more in the
653 * <a href="#Animation">Animation</a> section.
654 * </p>
655 *
656 * <a name="Animation"></a>
657 * <h3>Animation</h3>
658 * <p>
659 * Starting with Android 3.0, the preferred way of animating views is to use the
660 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
661 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
662 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
663 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
664 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
665 * makes animating these View properties particularly easy and efficient.
666 * </p>
667 * <p>
668 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
669 * You can attach an {@link Animation} object to a view using
670 * {@link #setAnimation(Animation)} or
671 * {@link #startAnimation(Animation)}. The animation can alter the scale,
672 * rotation, translation and alpha of a view over time. If the animation is
673 * attached to a view that has children, the animation will affect the entire
674 * subtree rooted by that node. When an animation is started, the framework will
675 * take care of redrawing the appropriate views until the animation completes.
676 * </p>
677 *
678 * <a name="Security"></a>
679 * <h3>Security</h3>
680 * <p>
681 * Sometimes it is essential that an application be able to verify that an action
682 * is being performed with the full knowledge and consent of the user, such as
683 * granting a permission request, making a purchase or clicking on an advertisement.
684 * Unfortunately, a malicious application could try to spoof the user into
685 * performing these actions, unaware, by concealing the intended purpose of the view.
686 * As a remedy, the framework offers a touch filtering mechanism that can be used to
687 * improve the security of views that provide access to sensitive functionality.
688 * </p><p>
689 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
690 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
691 * will discard touches that are received whenever the view's window is obscured by
692 * another visible window.  As a result, the view will not receive touches whenever a
693 * toast, dialog or other window appears above the view's window.
694 * </p><p>
695 * For more fine-grained control over security, consider overriding the
696 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
697 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
698 * </p>
699 *
700 * @attr ref android.R.styleable#View_alpha
701 * @attr ref android.R.styleable#View_background
702 * @attr ref android.R.styleable#View_clickable
703 * @attr ref android.R.styleable#View_contentDescription
704 * @attr ref android.R.styleable#View_drawingCacheQuality
705 * @attr ref android.R.styleable#View_duplicateParentState
706 * @attr ref android.R.styleable#View_id
707 * @attr ref android.R.styleable#View_requiresFadingEdge
708 * @attr ref android.R.styleable#View_fadeScrollbars
709 * @attr ref android.R.styleable#View_fadingEdgeLength
710 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
711 * @attr ref android.R.styleable#View_fitsSystemWindows
712 * @attr ref android.R.styleable#View_isScrollContainer
713 * @attr ref android.R.styleable#View_focusable
714 * @attr ref android.R.styleable#View_focusableInTouchMode
715 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
716 * @attr ref android.R.styleable#View_keepScreenOn
717 * @attr ref android.R.styleable#View_layerType
718 * @attr ref android.R.styleable#View_layoutDirection
719 * @attr ref android.R.styleable#View_longClickable
720 * @attr ref android.R.styleable#View_minHeight
721 * @attr ref android.R.styleable#View_minWidth
722 * @attr ref android.R.styleable#View_nextFocusDown
723 * @attr ref android.R.styleable#View_nextFocusLeft
724 * @attr ref android.R.styleable#View_nextFocusRight
725 * @attr ref android.R.styleable#View_nextFocusUp
726 * @attr ref android.R.styleable#View_onClick
727 * @attr ref android.R.styleable#View_padding
728 * @attr ref android.R.styleable#View_paddingBottom
729 * @attr ref android.R.styleable#View_paddingLeft
730 * @attr ref android.R.styleable#View_paddingRight
731 * @attr ref android.R.styleable#View_paddingTop
732 * @attr ref android.R.styleable#View_paddingStart
733 * @attr ref android.R.styleable#View_paddingEnd
734 * @attr ref android.R.styleable#View_saveEnabled
735 * @attr ref android.R.styleable#View_rotation
736 * @attr ref android.R.styleable#View_rotationX
737 * @attr ref android.R.styleable#View_rotationY
738 * @attr ref android.R.styleable#View_scaleX
739 * @attr ref android.R.styleable#View_scaleY
740 * @attr ref android.R.styleable#View_scrollX
741 * @attr ref android.R.styleable#View_scrollY
742 * @attr ref android.R.styleable#View_scrollbarSize
743 * @attr ref android.R.styleable#View_scrollbarStyle
744 * @attr ref android.R.styleable#View_scrollbars
745 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
746 * @attr ref android.R.styleable#View_scrollbarFadeDuration
747 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
748 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
749 * @attr ref android.R.styleable#View_scrollbarThumbVertical
750 * @attr ref android.R.styleable#View_scrollbarTrackVertical
751 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
752 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
753 * @attr ref android.R.styleable#View_stateListAnimator
754 * @attr ref android.R.styleable#View_transitionName
755 * @attr ref android.R.styleable#View_soundEffectsEnabled
756 * @attr ref android.R.styleable#View_tag
757 * @attr ref android.R.styleable#View_textAlignment
758 * @attr ref android.R.styleable#View_textDirection
759 * @attr ref android.R.styleable#View_transformPivotX
760 * @attr ref android.R.styleable#View_transformPivotY
761 * @attr ref android.R.styleable#View_translationX
762 * @attr ref android.R.styleable#View_translationY
763 * @attr ref android.R.styleable#View_translationZ
764 * @attr ref android.R.styleable#View_visibility
765 * @attr ref android.R.styleable#View_theme
766 *
767 * @see android.view.ViewGroup
768 */
769@UiThread
770public class View implements Drawable.Callback, KeyEvent.Callback,
771        AccessibilityEventSource {
772    private static final boolean DBG = false;
773
774    /** @hide */
775    public static boolean DEBUG_DRAW = false;
776
777    /**
778     * The logging tag used by this class with android.util.Log.
779     */
780    protected static final String VIEW_LOG_TAG = "View";
781
782    /**
783     * When set to true, apps will draw debugging information about their layouts.
784     *
785     * @hide
786     */
787    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
788
789    /**
790     * When set to true, this view will save its attribute data.
791     *
792     * @hide
793     */
794    public static boolean mDebugViewAttributes = false;
795
796    /**
797     * Used to mark a View that has no ID.
798     */
799    public static final int NO_ID = -1;
800
801    /**
802     * Signals that compatibility booleans have been initialized according to
803     * target SDK versions.
804     */
805    private static boolean sCompatibilityDone = false;
806
807    /**
808     * Use the old (broken) way of building MeasureSpecs.
809     */
810    private static boolean sUseBrokenMakeMeasureSpec = false;
811
812    /**
813     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
814     */
815    static boolean sUseZeroUnspecifiedMeasureSpec = false;
816
817    /**
818     * Ignore any optimizations using the measure cache.
819     */
820    private static boolean sIgnoreMeasureCache = false;
821
822    /**
823     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
824     */
825    private static boolean sAlwaysRemeasureExactly = false;
826
827    /**
828     * Relax constraints around whether setLayoutParams() must be called after
829     * modifying the layout params.
830     */
831    private static boolean sLayoutParamsAlwaysChanged = false;
832
833    /**
834     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
835     * without throwing
836     */
837    static boolean sTextureViewIgnoresDrawableSetters = false;
838
839    /**
840     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
841     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
842     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
843     * check is implemented for backwards compatibility.
844     *
845     * {@hide}
846     */
847    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
848
849    /**
850     * Prior to N, when drag enters into child of a view that has already received an
851     * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
852     * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
853     * false from its event handler for these events.
854     * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
855     * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
856     * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
857     */
858    static boolean sCascadedDragDrop;
859
860    /** @hide */
861    @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
862    @Retention(RetentionPolicy.SOURCE)
863    public @interface Focusable {}
864
865    /**
866     * This view does not want keystrokes.
867     * <p>
868     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
869     * android:focusable}.
870     */
871    public static final int NOT_FOCUSABLE = 0x00000000;
872
873    /**
874     * This view wants keystrokes.
875     * <p>
876     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
877     * android:focusable}.
878     */
879    public static final int FOCUSABLE = 0x00000001;
880
881    /**
882     * This view determines focusability automatically. This is the default.
883     * <p>
884     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
885     * android:focusable}.
886     */
887    public static final int FOCUSABLE_AUTO = 0x00000010;
888
889    /**
890     * Mask for use with setFlags indicating bits used for focus.
891     */
892    private static final int FOCUSABLE_MASK = 0x00000011;
893
894    /**
895     * This view will adjust its padding to fit sytem windows (e.g. status bar)
896     */
897    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
898
899    /** @hide */
900    @IntDef({VISIBLE, INVISIBLE, GONE})
901    @Retention(RetentionPolicy.SOURCE)
902    public @interface Visibility {}
903
904    /**
905     * This view is visible.
906     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
907     * android:visibility}.
908     */
909    public static final int VISIBLE = 0x00000000;
910
911    /**
912     * This view is invisible, but it still takes up space for layout purposes.
913     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
914     * android:visibility}.
915     */
916    public static final int INVISIBLE = 0x00000004;
917
918    /**
919     * This view is invisible, and it doesn't take any space for layout
920     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
921     * android:visibility}.
922     */
923    public static final int GONE = 0x00000008;
924
925    /**
926     * Mask for use with setFlags indicating bits used for visibility.
927     * {@hide}
928     */
929    static final int VISIBILITY_MASK = 0x0000000C;
930
931    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
932
933    /**
934     * This view is enabled. Interpretation varies by subclass.
935     * Use with ENABLED_MASK when calling setFlags.
936     * {@hide}
937     */
938    static final int ENABLED = 0x00000000;
939
940    /**
941     * This view is disabled. Interpretation varies by subclass.
942     * Use with ENABLED_MASK when calling setFlags.
943     * {@hide}
944     */
945    static final int DISABLED = 0x00000020;
946
947   /**
948    * Mask for use with setFlags indicating bits used for indicating whether
949    * this view is enabled
950    * {@hide}
951    */
952    static final int ENABLED_MASK = 0x00000020;
953
954    /**
955     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
956     * called and further optimizations will be performed. It is okay to have
957     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
958     * {@hide}
959     */
960    static final int WILL_NOT_DRAW = 0x00000080;
961
962    /**
963     * Mask for use with setFlags indicating bits used for indicating whether
964     * this view is will draw
965     * {@hide}
966     */
967    static final int DRAW_MASK = 0x00000080;
968
969    /**
970     * <p>This view doesn't show scrollbars.</p>
971     * {@hide}
972     */
973    static final int SCROLLBARS_NONE = 0x00000000;
974
975    /**
976     * <p>This view shows horizontal scrollbars.</p>
977     * {@hide}
978     */
979    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
980
981    /**
982     * <p>This view shows vertical scrollbars.</p>
983     * {@hide}
984     */
985    static final int SCROLLBARS_VERTICAL = 0x00000200;
986
987    /**
988     * <p>Mask for use with setFlags indicating bits used for indicating which
989     * scrollbars are enabled.</p>
990     * {@hide}
991     */
992    static final int SCROLLBARS_MASK = 0x00000300;
993
994    /**
995     * Indicates that the view should filter touches when its window is obscured.
996     * Refer to the class comments for more information about this security feature.
997     * {@hide}
998     */
999    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1000
1001    /**
1002     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1003     * that they are optional and should be skipped if the window has
1004     * requested system UI flags that ignore those insets for layout.
1005     */
1006    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1007
1008    /**
1009     * <p>This view doesn't show fading edges.</p>
1010     * {@hide}
1011     */
1012    static final int FADING_EDGE_NONE = 0x00000000;
1013
1014    /**
1015     * <p>This view shows horizontal fading edges.</p>
1016     * {@hide}
1017     */
1018    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1019
1020    /**
1021     * <p>This view shows vertical fading edges.</p>
1022     * {@hide}
1023     */
1024    static final int FADING_EDGE_VERTICAL = 0x00002000;
1025
1026    /**
1027     * <p>Mask for use with setFlags indicating bits used for indicating which
1028     * fading edges are enabled.</p>
1029     * {@hide}
1030     */
1031    static final int FADING_EDGE_MASK = 0x00003000;
1032
1033    /**
1034     * <p>Indicates this view can be clicked. When clickable, a View reacts
1035     * to clicks by notifying the OnClickListener.<p>
1036     * {@hide}
1037     */
1038    static final int CLICKABLE = 0x00004000;
1039
1040    /**
1041     * <p>Indicates this view is caching its drawing into a bitmap.</p>
1042     * {@hide}
1043     */
1044    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1045
1046    /**
1047     * <p>Indicates that no icicle should be saved for this view.<p>
1048     * {@hide}
1049     */
1050    static final int SAVE_DISABLED = 0x000010000;
1051
1052    /**
1053     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1054     * property.</p>
1055     * {@hide}
1056     */
1057    static final int SAVE_DISABLED_MASK = 0x000010000;
1058
1059    /**
1060     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1061     * {@hide}
1062     */
1063    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1064
1065    /**
1066     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1067     * {@hide}
1068     */
1069    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1070
1071    /** @hide */
1072    @Retention(RetentionPolicy.SOURCE)
1073    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1074    public @interface DrawingCacheQuality {}
1075
1076    /**
1077     * <p>Enables low quality mode for the drawing cache.</p>
1078     */
1079    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1080
1081    /**
1082     * <p>Enables high quality mode for the drawing cache.</p>
1083     */
1084    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1085
1086    /**
1087     * <p>Enables automatic quality mode for the drawing cache.</p>
1088     */
1089    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1090
1091    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1092            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1093    };
1094
1095    /**
1096     * <p>Mask for use with setFlags indicating bits used for the cache
1097     * quality property.</p>
1098     * {@hide}
1099     */
1100    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1101
1102    /**
1103     * <p>
1104     * Indicates this view can be long clicked. When long clickable, a View
1105     * reacts to long clicks by notifying the OnLongClickListener or showing a
1106     * context menu.
1107     * </p>
1108     * {@hide}
1109     */
1110    static final int LONG_CLICKABLE = 0x00200000;
1111
1112    /**
1113     * <p>Indicates that this view gets its drawable states from its direct parent
1114     * and ignores its original internal states.</p>
1115     *
1116     * @hide
1117     */
1118    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1119
1120    /**
1121     * <p>
1122     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1123     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1124     * OnContextClickListener.
1125     * </p>
1126     * {@hide}
1127     */
1128    static final int CONTEXT_CLICKABLE = 0x00800000;
1129
1130
1131    /** @hide */
1132    @IntDef({
1133        SCROLLBARS_INSIDE_OVERLAY,
1134        SCROLLBARS_INSIDE_INSET,
1135        SCROLLBARS_OUTSIDE_OVERLAY,
1136        SCROLLBARS_OUTSIDE_INSET
1137    })
1138    @Retention(RetentionPolicy.SOURCE)
1139    public @interface ScrollBarStyle {}
1140
1141    /**
1142     * The scrollbar style to display the scrollbars inside the content area,
1143     * without increasing the padding. The scrollbars will be overlaid with
1144     * translucency on the view's content.
1145     */
1146    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1147
1148    /**
1149     * The scrollbar style to display the scrollbars inside the padded area,
1150     * increasing the padding of the view. The scrollbars will not overlap the
1151     * content area of the view.
1152     */
1153    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1154
1155    /**
1156     * The scrollbar style to display the scrollbars at the edge of the view,
1157     * without increasing the padding. The scrollbars will be overlaid with
1158     * translucency.
1159     */
1160    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1161
1162    /**
1163     * The scrollbar style to display the scrollbars at the edge of the view,
1164     * increasing the padding of the view. The scrollbars will only overlap the
1165     * background, if any.
1166     */
1167    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1168
1169    /**
1170     * Mask to check if the scrollbar style is overlay or inset.
1171     * {@hide}
1172     */
1173    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1174
1175    /**
1176     * Mask to check if the scrollbar style is inside or outside.
1177     * {@hide}
1178     */
1179    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1180
1181    /**
1182     * Mask for scrollbar style.
1183     * {@hide}
1184     */
1185    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1186
1187    /**
1188     * View flag indicating that the screen should remain on while the
1189     * window containing this view is visible to the user.  This effectively
1190     * takes care of automatically setting the WindowManager's
1191     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1192     */
1193    public static final int KEEP_SCREEN_ON = 0x04000000;
1194
1195    /**
1196     * View flag indicating whether this view should have sound effects enabled
1197     * for events such as clicking and touching.
1198     */
1199    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1200
1201    /**
1202     * View flag indicating whether this view should have haptic feedback
1203     * enabled for events such as long presses.
1204     */
1205    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1206
1207    /**
1208     * <p>Indicates that the view hierarchy should stop saving state when
1209     * it reaches this view.  If state saving is initiated immediately at
1210     * the view, it will be allowed.
1211     * {@hide}
1212     */
1213    static final int PARENT_SAVE_DISABLED = 0x20000000;
1214
1215    /**
1216     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1217     * {@hide}
1218     */
1219    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1220
1221    private static Paint sDebugPaint;
1222
1223    /**
1224     * <p>Indicates this view can display a tooltip on hover or long press.</p>
1225     * {@hide}
1226     */
1227    static final int TOOLTIP = 0x40000000;
1228
1229    /** @hide */
1230    @IntDef(flag = true,
1231            value = {
1232                FOCUSABLES_ALL,
1233                FOCUSABLES_TOUCH_MODE
1234            })
1235    @Retention(RetentionPolicy.SOURCE)
1236    public @interface FocusableMode {}
1237
1238    /**
1239     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1240     * should add all focusable Views regardless if they are focusable in touch mode.
1241     */
1242    public static final int FOCUSABLES_ALL = 0x00000000;
1243
1244    /**
1245     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1246     * should add only Views focusable in touch mode.
1247     */
1248    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1249
1250    /** @hide */
1251    @IntDef({
1252            FOCUS_BACKWARD,
1253            FOCUS_FORWARD,
1254            FOCUS_LEFT,
1255            FOCUS_UP,
1256            FOCUS_RIGHT,
1257            FOCUS_DOWN
1258    })
1259    @Retention(RetentionPolicy.SOURCE)
1260    public @interface FocusDirection {}
1261
1262    /** @hide */
1263    @IntDef({
1264            FOCUS_LEFT,
1265            FOCUS_UP,
1266            FOCUS_RIGHT,
1267            FOCUS_DOWN
1268    })
1269    @Retention(RetentionPolicy.SOURCE)
1270    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1271
1272    /**
1273     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1274     * item.
1275     */
1276    public static final int FOCUS_BACKWARD = 0x00000001;
1277
1278    /**
1279     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1280     * item.
1281     */
1282    public static final int FOCUS_FORWARD = 0x00000002;
1283
1284    /**
1285     * Use with {@link #focusSearch(int)}. Move focus to the left.
1286     */
1287    public static final int FOCUS_LEFT = 0x00000011;
1288
1289    /**
1290     * Use with {@link #focusSearch(int)}. Move focus up.
1291     */
1292    public static final int FOCUS_UP = 0x00000021;
1293
1294    /**
1295     * Use with {@link #focusSearch(int)}. Move focus to the right.
1296     */
1297    public static final int FOCUS_RIGHT = 0x00000042;
1298
1299    /**
1300     * Use with {@link #focusSearch(int)}. Move focus down.
1301     */
1302    public static final int FOCUS_DOWN = 0x00000082;
1303
1304    /**
1305     * Bits of {@link #getMeasuredWidthAndState()} and
1306     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1307     */
1308    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1309
1310    /**
1311     * Bits of {@link #getMeasuredWidthAndState()} and
1312     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1313     */
1314    public static final int MEASURED_STATE_MASK = 0xff000000;
1315
1316    /**
1317     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1318     * for functions that combine both width and height into a single int,
1319     * such as {@link #getMeasuredState()} and the childState argument of
1320     * {@link #resolveSizeAndState(int, int, int)}.
1321     */
1322    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1323
1324    /**
1325     * Bit of {@link #getMeasuredWidthAndState()} and
1326     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1327     * is smaller that the space the view would like to have.
1328     */
1329    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1330
1331    /**
1332     * Base View state sets
1333     */
1334    // Singles
1335    /**
1336     * Indicates the view has no states set. States are used with
1337     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1338     * view depending on its state.
1339     *
1340     * @see android.graphics.drawable.Drawable
1341     * @see #getDrawableState()
1342     */
1343    protected static final int[] EMPTY_STATE_SET;
1344    /**
1345     * Indicates the view is enabled. States are used with
1346     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1347     * view depending on its state.
1348     *
1349     * @see android.graphics.drawable.Drawable
1350     * @see #getDrawableState()
1351     */
1352    protected static final int[] ENABLED_STATE_SET;
1353    /**
1354     * Indicates the view is focused. States are used with
1355     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1356     * view depending on its state.
1357     *
1358     * @see android.graphics.drawable.Drawable
1359     * @see #getDrawableState()
1360     */
1361    protected static final int[] FOCUSED_STATE_SET;
1362    /**
1363     * Indicates the view is selected. States are used with
1364     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1365     * view depending on its state.
1366     *
1367     * @see android.graphics.drawable.Drawable
1368     * @see #getDrawableState()
1369     */
1370    protected static final int[] SELECTED_STATE_SET;
1371    /**
1372     * Indicates the view is pressed. States are used with
1373     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1374     * view depending on its state.
1375     *
1376     * @see android.graphics.drawable.Drawable
1377     * @see #getDrawableState()
1378     */
1379    protected static final int[] PRESSED_STATE_SET;
1380    /**
1381     * Indicates the view's window has focus. States are used with
1382     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1383     * view depending on its state.
1384     *
1385     * @see android.graphics.drawable.Drawable
1386     * @see #getDrawableState()
1387     */
1388    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1389    // Doubles
1390    /**
1391     * Indicates the view is enabled and has the focus.
1392     *
1393     * @see #ENABLED_STATE_SET
1394     * @see #FOCUSED_STATE_SET
1395     */
1396    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1397    /**
1398     * Indicates the view is enabled and selected.
1399     *
1400     * @see #ENABLED_STATE_SET
1401     * @see #SELECTED_STATE_SET
1402     */
1403    protected static final int[] ENABLED_SELECTED_STATE_SET;
1404    /**
1405     * Indicates the view is enabled and that its window has focus.
1406     *
1407     * @see #ENABLED_STATE_SET
1408     * @see #WINDOW_FOCUSED_STATE_SET
1409     */
1410    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1411    /**
1412     * Indicates the view is focused and selected.
1413     *
1414     * @see #FOCUSED_STATE_SET
1415     * @see #SELECTED_STATE_SET
1416     */
1417    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1418    /**
1419     * Indicates the view has the focus and that its window has the focus.
1420     *
1421     * @see #FOCUSED_STATE_SET
1422     * @see #WINDOW_FOCUSED_STATE_SET
1423     */
1424    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1425    /**
1426     * Indicates the view is selected and that its window has the focus.
1427     *
1428     * @see #SELECTED_STATE_SET
1429     * @see #WINDOW_FOCUSED_STATE_SET
1430     */
1431    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1432    // Triples
1433    /**
1434     * Indicates the view is enabled, focused and selected.
1435     *
1436     * @see #ENABLED_STATE_SET
1437     * @see #FOCUSED_STATE_SET
1438     * @see #SELECTED_STATE_SET
1439     */
1440    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1441    /**
1442     * Indicates the view is enabled, focused and its window has the focus.
1443     *
1444     * @see #ENABLED_STATE_SET
1445     * @see #FOCUSED_STATE_SET
1446     * @see #WINDOW_FOCUSED_STATE_SET
1447     */
1448    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1449    /**
1450     * Indicates the view is enabled, selected and its window has the focus.
1451     *
1452     * @see #ENABLED_STATE_SET
1453     * @see #SELECTED_STATE_SET
1454     * @see #WINDOW_FOCUSED_STATE_SET
1455     */
1456    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1457    /**
1458     * Indicates the view is focused, selected and its window has the focus.
1459     *
1460     * @see #FOCUSED_STATE_SET
1461     * @see #SELECTED_STATE_SET
1462     * @see #WINDOW_FOCUSED_STATE_SET
1463     */
1464    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1465    /**
1466     * Indicates the view is enabled, focused, selected and its window
1467     * has the focus.
1468     *
1469     * @see #ENABLED_STATE_SET
1470     * @see #FOCUSED_STATE_SET
1471     * @see #SELECTED_STATE_SET
1472     * @see #WINDOW_FOCUSED_STATE_SET
1473     */
1474    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1475    /**
1476     * Indicates the view is pressed and its window has the focus.
1477     *
1478     * @see #PRESSED_STATE_SET
1479     * @see #WINDOW_FOCUSED_STATE_SET
1480     */
1481    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1482    /**
1483     * Indicates the view is pressed and selected.
1484     *
1485     * @see #PRESSED_STATE_SET
1486     * @see #SELECTED_STATE_SET
1487     */
1488    protected static final int[] PRESSED_SELECTED_STATE_SET;
1489    /**
1490     * Indicates the view is pressed, selected and its window has the focus.
1491     *
1492     * @see #PRESSED_STATE_SET
1493     * @see #SELECTED_STATE_SET
1494     * @see #WINDOW_FOCUSED_STATE_SET
1495     */
1496    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1497    /**
1498     * Indicates the view is pressed and focused.
1499     *
1500     * @see #PRESSED_STATE_SET
1501     * @see #FOCUSED_STATE_SET
1502     */
1503    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1504    /**
1505     * Indicates the view is pressed, focused and its window has the focus.
1506     *
1507     * @see #PRESSED_STATE_SET
1508     * @see #FOCUSED_STATE_SET
1509     * @see #WINDOW_FOCUSED_STATE_SET
1510     */
1511    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1512    /**
1513     * Indicates the view is pressed, focused and selected.
1514     *
1515     * @see #PRESSED_STATE_SET
1516     * @see #SELECTED_STATE_SET
1517     * @see #FOCUSED_STATE_SET
1518     */
1519    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1520    /**
1521     * Indicates the view is pressed, focused, selected and its window has the focus.
1522     *
1523     * @see #PRESSED_STATE_SET
1524     * @see #FOCUSED_STATE_SET
1525     * @see #SELECTED_STATE_SET
1526     * @see #WINDOW_FOCUSED_STATE_SET
1527     */
1528    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1529    /**
1530     * Indicates the view is pressed and enabled.
1531     *
1532     * @see #PRESSED_STATE_SET
1533     * @see #ENABLED_STATE_SET
1534     */
1535    protected static final int[] PRESSED_ENABLED_STATE_SET;
1536    /**
1537     * Indicates the view is pressed, enabled and its window has the focus.
1538     *
1539     * @see #PRESSED_STATE_SET
1540     * @see #ENABLED_STATE_SET
1541     * @see #WINDOW_FOCUSED_STATE_SET
1542     */
1543    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1544    /**
1545     * Indicates the view is pressed, enabled and selected.
1546     *
1547     * @see #PRESSED_STATE_SET
1548     * @see #ENABLED_STATE_SET
1549     * @see #SELECTED_STATE_SET
1550     */
1551    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1552    /**
1553     * Indicates the view is pressed, enabled, selected and its window has the
1554     * focus.
1555     *
1556     * @see #PRESSED_STATE_SET
1557     * @see #ENABLED_STATE_SET
1558     * @see #SELECTED_STATE_SET
1559     * @see #WINDOW_FOCUSED_STATE_SET
1560     */
1561    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1562    /**
1563     * Indicates the view is pressed, enabled and focused.
1564     *
1565     * @see #PRESSED_STATE_SET
1566     * @see #ENABLED_STATE_SET
1567     * @see #FOCUSED_STATE_SET
1568     */
1569    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1570    /**
1571     * Indicates the view is pressed, enabled, focused and its window has the
1572     * focus.
1573     *
1574     * @see #PRESSED_STATE_SET
1575     * @see #ENABLED_STATE_SET
1576     * @see #FOCUSED_STATE_SET
1577     * @see #WINDOW_FOCUSED_STATE_SET
1578     */
1579    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1580    /**
1581     * Indicates the view is pressed, enabled, focused and selected.
1582     *
1583     * @see #PRESSED_STATE_SET
1584     * @see #ENABLED_STATE_SET
1585     * @see #SELECTED_STATE_SET
1586     * @see #FOCUSED_STATE_SET
1587     */
1588    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1589    /**
1590     * Indicates the view is pressed, enabled, focused, selected and its window
1591     * has the focus.
1592     *
1593     * @see #PRESSED_STATE_SET
1594     * @see #ENABLED_STATE_SET
1595     * @see #SELECTED_STATE_SET
1596     * @see #FOCUSED_STATE_SET
1597     * @see #WINDOW_FOCUSED_STATE_SET
1598     */
1599    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1600
1601    static {
1602        EMPTY_STATE_SET = StateSet.get(0);
1603
1604        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1605
1606        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1607        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1608                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1609
1610        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1611        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1612                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1613        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1614                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1615        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1616                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1617                        | StateSet.VIEW_STATE_FOCUSED);
1618
1619        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1620        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1621                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1622        ENABLED_SELECTED_STATE_SET = StateSet.get(
1623                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1624        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1625                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1626                        | StateSet.VIEW_STATE_ENABLED);
1627        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1628                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1629        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1630                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1631                        | StateSet.VIEW_STATE_ENABLED);
1632        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1633                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1634                        | StateSet.VIEW_STATE_ENABLED);
1635        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1636                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1637                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1638
1639        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1640        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1641                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1642        PRESSED_SELECTED_STATE_SET = StateSet.get(
1643                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1644        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1645                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1646                        | StateSet.VIEW_STATE_PRESSED);
1647        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1648                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1649        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1650                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1651                        | StateSet.VIEW_STATE_PRESSED);
1652        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1653                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1654                        | StateSet.VIEW_STATE_PRESSED);
1655        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1656                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1657                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1658        PRESSED_ENABLED_STATE_SET = StateSet.get(
1659                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1660        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1661                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1662                        | StateSet.VIEW_STATE_PRESSED);
1663        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1664                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1665                        | StateSet.VIEW_STATE_PRESSED);
1666        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1667                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1668                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1669        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1670                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1671                        | StateSet.VIEW_STATE_PRESSED);
1672        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1673                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1674                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1675        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1676                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1677                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1678        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1679                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1680                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1681                        | StateSet.VIEW_STATE_PRESSED);
1682    }
1683
1684    /**
1685     * Accessibility event types that are dispatched for text population.
1686     */
1687    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1688            AccessibilityEvent.TYPE_VIEW_CLICKED
1689            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1690            | AccessibilityEvent.TYPE_VIEW_SELECTED
1691            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1692            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1693            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1694            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1695            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1696            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1697            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1698            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1699
1700    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
1701
1702    static final int DEBUG_CORNERS_SIZE_DIP = 8;
1703
1704    /**
1705     * Temporary Rect currently for use in setBackground().  This will probably
1706     * be extended in the future to hold our own class with more than just
1707     * a Rect. :)
1708     */
1709    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1710
1711    /**
1712     * Map used to store views' tags.
1713     */
1714    private SparseArray<Object> mKeyedTags;
1715
1716    /**
1717     * The next available accessibility id.
1718     */
1719    private static int sNextAccessibilityViewId;
1720
1721    /**
1722     * The animation currently associated with this view.
1723     * @hide
1724     */
1725    protected Animation mCurrentAnimation = null;
1726
1727    /**
1728     * Width as measured during measure pass.
1729     * {@hide}
1730     */
1731    @ViewDebug.ExportedProperty(category = "measurement")
1732    int mMeasuredWidth;
1733
1734    /**
1735     * Height as measured during measure pass.
1736     * {@hide}
1737     */
1738    @ViewDebug.ExportedProperty(category = "measurement")
1739    int mMeasuredHeight;
1740
1741    /**
1742     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1743     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1744     * its display list. This flag, used only when hw accelerated, allows us to clear the
1745     * flag while retaining this information until it's needed (at getDisplayList() time and
1746     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1747     *
1748     * {@hide}
1749     */
1750    boolean mRecreateDisplayList = false;
1751
1752    /**
1753     * The view's identifier.
1754     * {@hide}
1755     *
1756     * @see #setId(int)
1757     * @see #getId()
1758     */
1759    @IdRes
1760    @ViewDebug.ExportedProperty(resolveId = true)
1761    int mID = NO_ID;
1762
1763    /**
1764     * The stable ID of this view for accessibility purposes.
1765     */
1766    int mAccessibilityViewId = NO_ID;
1767
1768    /**
1769     * The stable ID of this view for auto-fill purposes.
1770     */
1771    private int mAutoFillId = NO_ID;
1772
1773
1774    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1775
1776    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1777
1778    /**
1779     * The view's tag.
1780     * {@hide}
1781     *
1782     * @see #setTag(Object)
1783     * @see #getTag()
1784     */
1785    protected Object mTag = null;
1786
1787    // for mPrivateFlags:
1788    /** {@hide} */
1789    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1790    /** {@hide} */
1791    static final int PFLAG_FOCUSED                     = 0x00000002;
1792    /** {@hide} */
1793    static final int PFLAG_SELECTED                    = 0x00000004;
1794    /** {@hide} */
1795    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1796    /** {@hide} */
1797    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1798    /** {@hide} */
1799    static final int PFLAG_DRAWN                       = 0x00000020;
1800    /**
1801     * When this flag is set, this view is running an animation on behalf of its
1802     * children and should therefore not cancel invalidate requests, even if they
1803     * lie outside of this view's bounds.
1804     *
1805     * {@hide}
1806     */
1807    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1808    /** {@hide} */
1809    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1810    /** {@hide} */
1811    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1812    /** {@hide} */
1813    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1814    /** {@hide} */
1815    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1816    /** {@hide} */
1817    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1818    /** {@hide} */
1819    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1820
1821    private static final int PFLAG_PRESSED             = 0x00004000;
1822
1823    /** {@hide} */
1824    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1825    /**
1826     * Flag used to indicate that this view should be drawn once more (and only once
1827     * more) after its animation has completed.
1828     * {@hide}
1829     */
1830    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1831
1832    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1833
1834    /**
1835     * Indicates that the View returned true when onSetAlpha() was called and that
1836     * the alpha must be restored.
1837     * {@hide}
1838     */
1839    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1840
1841    /**
1842     * Set by {@link #setScrollContainer(boolean)}.
1843     */
1844    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1845
1846    /**
1847     * Set by {@link #setScrollContainer(boolean)}.
1848     */
1849    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1850
1851    /**
1852     * View flag indicating whether this view was invalidated (fully or partially.)
1853     *
1854     * @hide
1855     */
1856    static final int PFLAG_DIRTY                       = 0x00200000;
1857
1858    /**
1859     * View flag indicating whether this view was invalidated by an opaque
1860     * invalidate request.
1861     *
1862     * @hide
1863     */
1864    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1865
1866    /**
1867     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1868     *
1869     * @hide
1870     */
1871    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1872
1873    /**
1874     * Indicates whether the background is opaque.
1875     *
1876     * @hide
1877     */
1878    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1879
1880    /**
1881     * Indicates whether the scrollbars are opaque.
1882     *
1883     * @hide
1884     */
1885    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1886
1887    /**
1888     * Indicates whether the view is opaque.
1889     *
1890     * @hide
1891     */
1892    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1893
1894    /**
1895     * Indicates a prepressed state;
1896     * the short time between ACTION_DOWN and recognizing
1897     * a 'real' press. Prepressed is used to recognize quick taps
1898     * even when they are shorter than ViewConfiguration.getTapTimeout().
1899     *
1900     * @hide
1901     */
1902    private static final int PFLAG_PREPRESSED          = 0x02000000;
1903
1904    /**
1905     * Indicates whether the view is temporarily detached.
1906     *
1907     * @hide
1908     */
1909    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1910
1911    /**
1912     * Indicates that we should awaken scroll bars once attached
1913     *
1914     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1915     * during window attachment and it is no longer needed. Feel free to repurpose it.
1916     *
1917     * @hide
1918     */
1919    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1920
1921    /**
1922     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1923     * @hide
1924     */
1925    private static final int PFLAG_HOVERED             = 0x10000000;
1926
1927    /**
1928     * no longer needed, should be reused
1929     */
1930    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1931
1932    /** {@hide} */
1933    static final int PFLAG_ACTIVATED                   = 0x40000000;
1934
1935    /**
1936     * Indicates that this view was specifically invalidated, not just dirtied because some
1937     * child view was invalidated. The flag is used to determine when we need to recreate
1938     * a view's display list (as opposed to just returning a reference to its existing
1939     * display list).
1940     *
1941     * @hide
1942     */
1943    static final int PFLAG_INVALIDATED                 = 0x80000000;
1944
1945    /**
1946     * Masks for mPrivateFlags2, as generated by dumpFlags():
1947     *
1948     * |-------|-------|-------|-------|
1949     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1950     *                                1  PFLAG2_DRAG_HOVERED
1951     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1952     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1953     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1954     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1955     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1956     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1957     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1958     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1959     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1960     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1961     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1962     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1963     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1964     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1965     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1966     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1967     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1968     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1969     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1970     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1971     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1972     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1973     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1974     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1975     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1976     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1977     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1978     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1979     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1980     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1981     *    1                              PFLAG2_PADDING_RESOLVED
1982     *   1                               PFLAG2_DRAWABLE_RESOLVED
1983     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1984     * |-------|-------|-------|-------|
1985     */
1986
1987    /**
1988     * Indicates that this view has reported that it can accept the current drag's content.
1989     * Cleared when the drag operation concludes.
1990     * @hide
1991     */
1992    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1993
1994    /**
1995     * Indicates that this view is currently directly under the drag location in a
1996     * drag-and-drop operation involving content that it can accept.  Cleared when
1997     * the drag exits the view, or when the drag operation concludes.
1998     * @hide
1999     */
2000    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2001
2002    /** @hide */
2003    @IntDef({
2004        LAYOUT_DIRECTION_LTR,
2005        LAYOUT_DIRECTION_RTL,
2006        LAYOUT_DIRECTION_INHERIT,
2007        LAYOUT_DIRECTION_LOCALE
2008    })
2009    @Retention(RetentionPolicy.SOURCE)
2010    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2011    public @interface LayoutDir {}
2012
2013    /** @hide */
2014    @IntDef({
2015        LAYOUT_DIRECTION_LTR,
2016        LAYOUT_DIRECTION_RTL
2017    })
2018    @Retention(RetentionPolicy.SOURCE)
2019    public @interface ResolvedLayoutDir {}
2020
2021    /**
2022     * A flag to indicate that the layout direction of this view has not been defined yet.
2023     * @hide
2024     */
2025    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2026
2027    /**
2028     * Horizontal layout direction of this view is from Left to Right.
2029     * Use with {@link #setLayoutDirection}.
2030     */
2031    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2032
2033    /**
2034     * Horizontal layout direction of this view is from Right to Left.
2035     * Use with {@link #setLayoutDirection}.
2036     */
2037    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2038
2039    /**
2040     * Horizontal layout direction of this view is inherited from its parent.
2041     * Use with {@link #setLayoutDirection}.
2042     */
2043    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2044
2045    /**
2046     * Horizontal layout direction of this view is from deduced from the default language
2047     * script for the locale. Use with {@link #setLayoutDirection}.
2048     */
2049    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2050
2051    /**
2052     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2053     * @hide
2054     */
2055    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2056
2057    /**
2058     * Mask for use with private flags indicating bits used for horizontal layout direction.
2059     * @hide
2060     */
2061    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2062
2063    /**
2064     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2065     * right-to-left direction.
2066     * @hide
2067     */
2068    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2069
2070    /**
2071     * Indicates whether the view horizontal layout direction has been resolved.
2072     * @hide
2073     */
2074    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2075
2076    /**
2077     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2078     * @hide
2079     */
2080    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2081            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2082
2083    /*
2084     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2085     * flag value.
2086     * @hide
2087     */
2088    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2089            LAYOUT_DIRECTION_LTR,
2090            LAYOUT_DIRECTION_RTL,
2091            LAYOUT_DIRECTION_INHERIT,
2092            LAYOUT_DIRECTION_LOCALE
2093    };
2094
2095    /**
2096     * Default horizontal layout direction.
2097     */
2098    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2099
2100    /**
2101     * Default horizontal layout direction.
2102     * @hide
2103     */
2104    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2105
2106    /**
2107     * Text direction is inherited through {@link ViewGroup}
2108     */
2109    public static final int TEXT_DIRECTION_INHERIT = 0;
2110
2111    /**
2112     * Text direction is using "first strong algorithm". The first strong directional character
2113     * determines the paragraph direction. If there is no strong directional character, the
2114     * paragraph direction is the view's resolved layout direction.
2115     */
2116    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2117
2118    /**
2119     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2120     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2121     * If there are neither, the paragraph direction is the view's resolved layout direction.
2122     */
2123    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2124
2125    /**
2126     * Text direction is forced to LTR.
2127     */
2128    public static final int TEXT_DIRECTION_LTR = 3;
2129
2130    /**
2131     * Text direction is forced to RTL.
2132     */
2133    public static final int TEXT_DIRECTION_RTL = 4;
2134
2135    /**
2136     * Text direction is coming from the system Locale.
2137     */
2138    public static final int TEXT_DIRECTION_LOCALE = 5;
2139
2140    /**
2141     * Text direction is using "first strong algorithm". The first strong directional character
2142     * determines the paragraph direction. If there is no strong directional character, the
2143     * paragraph direction is LTR.
2144     */
2145    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2146
2147    /**
2148     * Text direction is using "first strong algorithm". The first strong directional character
2149     * determines the paragraph direction. If there is no strong directional character, the
2150     * paragraph direction is RTL.
2151     */
2152    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2153
2154    /**
2155     * Default text direction is inherited
2156     */
2157    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2158
2159    /**
2160     * Default resolved text direction
2161     * @hide
2162     */
2163    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2164
2165    /**
2166     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2167     * @hide
2168     */
2169    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2170
2171    /**
2172     * Mask for use with private flags indicating bits used for text direction.
2173     * @hide
2174     */
2175    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2176            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2177
2178    /**
2179     * Array of text direction flags for mapping attribute "textDirection" to correct
2180     * flag value.
2181     * @hide
2182     */
2183    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2184            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2185            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2186            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2187            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2188            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2189            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2190            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2191            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2192    };
2193
2194    /**
2195     * Indicates whether the view text direction has been resolved.
2196     * @hide
2197     */
2198    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2199            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2200
2201    /**
2202     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2203     * @hide
2204     */
2205    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2206
2207    /**
2208     * Mask for use with private flags indicating bits used for resolved text direction.
2209     * @hide
2210     */
2211    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2212            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2213
2214    /**
2215     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2216     * @hide
2217     */
2218    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2219            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2220
2221    /** @hide */
2222    @IntDef({
2223        TEXT_ALIGNMENT_INHERIT,
2224        TEXT_ALIGNMENT_GRAVITY,
2225        TEXT_ALIGNMENT_CENTER,
2226        TEXT_ALIGNMENT_TEXT_START,
2227        TEXT_ALIGNMENT_TEXT_END,
2228        TEXT_ALIGNMENT_VIEW_START,
2229        TEXT_ALIGNMENT_VIEW_END
2230    })
2231    @Retention(RetentionPolicy.SOURCE)
2232    public @interface TextAlignment {}
2233
2234    /**
2235     * Default text alignment. The text alignment of this View is inherited from its parent.
2236     * Use with {@link #setTextAlignment(int)}
2237     */
2238    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2239
2240    /**
2241     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2242     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2243     *
2244     * Use with {@link #setTextAlignment(int)}
2245     */
2246    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2247
2248    /**
2249     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2250     *
2251     * Use with {@link #setTextAlignment(int)}
2252     */
2253    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2254
2255    /**
2256     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2257     *
2258     * Use with {@link #setTextAlignment(int)}
2259     */
2260    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2261
2262    /**
2263     * Center the paragraph, e.g. ALIGN_CENTER.
2264     *
2265     * Use with {@link #setTextAlignment(int)}
2266     */
2267    public static final int TEXT_ALIGNMENT_CENTER = 4;
2268
2269    /**
2270     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2271     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2272     *
2273     * Use with {@link #setTextAlignment(int)}
2274     */
2275    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2276
2277    /**
2278     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2279     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2280     *
2281     * Use with {@link #setTextAlignment(int)}
2282     */
2283    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2284
2285    /**
2286     * Default text alignment is inherited
2287     */
2288    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2289
2290    /**
2291     * Default resolved text alignment
2292     * @hide
2293     */
2294    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2295
2296    /**
2297      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2298      * @hide
2299      */
2300    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2301
2302    /**
2303      * Mask for use with private flags indicating bits used for text alignment.
2304      * @hide
2305      */
2306    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2307
2308    /**
2309     * Array of text direction flags for mapping attribute "textAlignment" to correct
2310     * flag value.
2311     * @hide
2312     */
2313    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2314            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2315            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2316            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2317            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2318            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2319            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2320            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2321    };
2322
2323    /**
2324     * Indicates whether the view text alignment has been resolved.
2325     * @hide
2326     */
2327    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2328
2329    /**
2330     * Bit shift to get the resolved text alignment.
2331     * @hide
2332     */
2333    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2334
2335    /**
2336     * Mask for use with private flags indicating bits used for text alignment.
2337     * @hide
2338     */
2339    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2340            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2341
2342    /**
2343     * Indicates whether if the view text alignment has been resolved to gravity
2344     */
2345    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2346            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2347
2348    // Accessiblity constants for mPrivateFlags2
2349
2350    /**
2351     * Shift for the bits in {@link #mPrivateFlags2} related to the
2352     * "importantForAccessibility" attribute.
2353     */
2354    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2355
2356    /**
2357     * Automatically determine whether a view is important for accessibility.
2358     */
2359    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2360
2361    /**
2362     * The view is important for accessibility.
2363     */
2364    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2365
2366    /**
2367     * The view is not important for accessibility.
2368     */
2369    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2370
2371    /**
2372     * The view is not important for accessibility, nor are any of its
2373     * descendant views.
2374     */
2375    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2376
2377    /**
2378     * The default whether the view is important for accessibility.
2379     */
2380    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2381
2382    /**
2383     * Mask for obtaining the bits which specify how to determine
2384     * whether a view is important for accessibility.
2385     */
2386    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2387        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2388        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2389        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2390
2391    /**
2392     * Shift for the bits in {@link #mPrivateFlags2} related to the
2393     * "accessibilityLiveRegion" attribute.
2394     */
2395    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2396
2397    /**
2398     * Live region mode specifying that accessibility services should not
2399     * automatically announce changes to this view. This is the default live
2400     * region mode for most views.
2401     * <p>
2402     * Use with {@link #setAccessibilityLiveRegion(int)}.
2403     */
2404    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2405
2406    /**
2407     * Live region mode specifying that accessibility services should announce
2408     * changes to this view.
2409     * <p>
2410     * Use with {@link #setAccessibilityLiveRegion(int)}.
2411     */
2412    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2413
2414    /**
2415     * Live region mode specifying that accessibility services should interrupt
2416     * ongoing speech to immediately announce changes to this view.
2417     * <p>
2418     * Use with {@link #setAccessibilityLiveRegion(int)}.
2419     */
2420    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2421
2422    /**
2423     * The default whether the view is important for accessibility.
2424     */
2425    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2426
2427    /**
2428     * Mask for obtaining the bits which specify a view's accessibility live
2429     * region mode.
2430     */
2431    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2432            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2433            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2434
2435    /**
2436     * Flag indicating whether a view has accessibility focus.
2437     */
2438    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2439
2440    /**
2441     * Flag whether the accessibility state of the subtree rooted at this view changed.
2442     */
2443    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2444
2445    /**
2446     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2447     * is used to check whether later changes to the view's transform should invalidate the
2448     * view to force the quickReject test to run again.
2449     */
2450    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2451
2452    /**
2453     * Flag indicating that start/end padding has been resolved into left/right padding
2454     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2455     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2456     * during measurement. In some special cases this is required such as when an adapter-based
2457     * view measures prospective children without attaching them to a window.
2458     */
2459    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2460
2461    /**
2462     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2463     */
2464    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2465
2466    /**
2467     * Indicates that the view is tracking some sort of transient state
2468     * that the app should not need to be aware of, but that the framework
2469     * should take special care to preserve.
2470     */
2471    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2472
2473    /**
2474     * Group of bits indicating that RTL properties resolution is done.
2475     */
2476    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2477            PFLAG2_TEXT_DIRECTION_RESOLVED |
2478            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2479            PFLAG2_PADDING_RESOLVED |
2480            PFLAG2_DRAWABLE_RESOLVED;
2481
2482    // There are a couple of flags left in mPrivateFlags2
2483
2484    /* End of masks for mPrivateFlags2 */
2485
2486    /**
2487     * Masks for mPrivateFlags3, as generated by dumpFlags():
2488     *
2489     * |-------|-------|-------|-------|
2490     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2491     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2492     *                               1   PFLAG3_IS_LAID_OUT
2493     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2494     *                             1     PFLAG3_CALLED_SUPER
2495     *                            1      PFLAG3_APPLYING_INSETS
2496     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2497     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2498     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2499     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2500     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2501     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2502     *                     1             PFLAG3_SCROLL_INDICATOR_START
2503     *                    1              PFLAG3_SCROLL_INDICATOR_END
2504     *                   1               PFLAG3_ASSIST_BLOCKED
2505     *                  1                PFLAG3_CLUSTER
2506     *                 x                 * NO LONGER NEEDED, SHOULD BE REUSED *
2507     *                1                  PFLAG3_FINGER_DOWN
2508     *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2509     *           xxxx                    * NO LONGER NEEDED, SHOULD BE REUSED *
2510     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2511     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2512     *        1                          PFLAG3_TEMPORARY_DETACH
2513     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2514     * |-------|-------|-------|-------|
2515     */
2516
2517    /**
2518     * Flag indicating that view has a transform animation set on it. This is used to track whether
2519     * an animation is cleared between successive frames, in order to tell the associated
2520     * DisplayList to clear its animation matrix.
2521     */
2522    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2523
2524    /**
2525     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2526     * animation is cleared between successive frames, in order to tell the associated
2527     * DisplayList to restore its alpha value.
2528     */
2529    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2530
2531    /**
2532     * Flag indicating that the view has been through at least one layout since it
2533     * was last attached to a window.
2534     */
2535    static final int PFLAG3_IS_LAID_OUT = 0x4;
2536
2537    /**
2538     * Flag indicating that a call to measure() was skipped and should be done
2539     * instead when layout() is invoked.
2540     */
2541    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2542
2543    /**
2544     * Flag indicating that an overridden method correctly called down to
2545     * the superclass implementation as required by the API spec.
2546     */
2547    static final int PFLAG3_CALLED_SUPER = 0x10;
2548
2549    /**
2550     * Flag indicating that we're in the process of applying window insets.
2551     */
2552    static final int PFLAG3_APPLYING_INSETS = 0x20;
2553
2554    /**
2555     * Flag indicating that we're in the process of fitting system windows using the old method.
2556     */
2557    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2558
2559    /**
2560     * Flag indicating that nested scrolling is enabled for this view.
2561     * The view will optionally cooperate with views up its parent chain to allow for
2562     * integrated nested scrolling along the same axis.
2563     */
2564    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2565
2566    /**
2567     * Flag indicating that the bottom scroll indicator should be displayed
2568     * when this view can scroll up.
2569     */
2570    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2571
2572    /**
2573     * Flag indicating that the bottom scroll indicator should be displayed
2574     * when this view can scroll down.
2575     */
2576    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2577
2578    /**
2579     * Flag indicating that the left scroll indicator should be displayed
2580     * when this view can scroll left.
2581     */
2582    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2583
2584    /**
2585     * Flag indicating that the right scroll indicator should be displayed
2586     * when this view can scroll right.
2587     */
2588    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2589
2590    /**
2591     * Flag indicating that the start scroll indicator should be displayed
2592     * when this view can scroll in the start direction.
2593     */
2594    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2595
2596    /**
2597     * Flag indicating that the end scroll indicator should be displayed
2598     * when this view can scroll in the end direction.
2599     */
2600    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2601
2602    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2603
2604    static final int SCROLL_INDICATORS_NONE = 0x0000;
2605
2606    /**
2607     * Mask for use with setFlags indicating bits used for indicating which
2608     * scroll indicators are enabled.
2609     */
2610    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2611            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2612            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2613            | PFLAG3_SCROLL_INDICATOR_END;
2614
2615    /**
2616     * Left-shift required to translate between public scroll indicator flags
2617     * and internal PFLAGS3 flags. When used as a right-shift, translates
2618     * PFLAGS3 flags to public flags.
2619     */
2620    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2621
2622    /** @hide */
2623    @Retention(RetentionPolicy.SOURCE)
2624    @IntDef(flag = true,
2625            value = {
2626                    SCROLL_INDICATOR_TOP,
2627                    SCROLL_INDICATOR_BOTTOM,
2628                    SCROLL_INDICATOR_LEFT,
2629                    SCROLL_INDICATOR_RIGHT,
2630                    SCROLL_INDICATOR_START,
2631                    SCROLL_INDICATOR_END,
2632            })
2633    public @interface ScrollIndicators {}
2634
2635    /**
2636     * Scroll indicator direction for the top edge of the view.
2637     *
2638     * @see #setScrollIndicators(int)
2639     * @see #setScrollIndicators(int, int)
2640     * @see #getScrollIndicators()
2641     */
2642    public static final int SCROLL_INDICATOR_TOP =
2643            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2644
2645    /**
2646     * Scroll indicator direction for the bottom edge of the view.
2647     *
2648     * @see #setScrollIndicators(int)
2649     * @see #setScrollIndicators(int, int)
2650     * @see #getScrollIndicators()
2651     */
2652    public static final int SCROLL_INDICATOR_BOTTOM =
2653            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2654
2655    /**
2656     * Scroll indicator direction for the left edge of the view.
2657     *
2658     * @see #setScrollIndicators(int)
2659     * @see #setScrollIndicators(int, int)
2660     * @see #getScrollIndicators()
2661     */
2662    public static final int SCROLL_INDICATOR_LEFT =
2663            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2664
2665    /**
2666     * Scroll indicator direction for the right edge of the view.
2667     *
2668     * @see #setScrollIndicators(int)
2669     * @see #setScrollIndicators(int, int)
2670     * @see #getScrollIndicators()
2671     */
2672    public static final int SCROLL_INDICATOR_RIGHT =
2673            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2674
2675    /**
2676     * Scroll indicator direction for the starting edge of the view.
2677     * <p>
2678     * Resolved according to the view's layout direction, see
2679     * {@link #getLayoutDirection()} for more information.
2680     *
2681     * @see #setScrollIndicators(int)
2682     * @see #setScrollIndicators(int, int)
2683     * @see #getScrollIndicators()
2684     */
2685    public static final int SCROLL_INDICATOR_START =
2686            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2687
2688    /**
2689     * Scroll indicator direction for the ending edge of the view.
2690     * <p>
2691     * Resolved according to the view's layout direction, see
2692     * {@link #getLayoutDirection()} for more information.
2693     *
2694     * @see #setScrollIndicators(int)
2695     * @see #setScrollIndicators(int, int)
2696     * @see #getScrollIndicators()
2697     */
2698    public static final int SCROLL_INDICATOR_END =
2699            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2700
2701    /**
2702     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2703     * into this view.<p>
2704     */
2705    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2706
2707    /**
2708     * Flag indicating that the view is a root of a keyboard navigation cluster.
2709     *
2710     * @see #isKeyboardNavigationCluster()
2711     * @see #setKeyboardNavigationCluster(boolean)
2712     */
2713    private static final int PFLAG3_CLUSTER = 0x8000;
2714
2715    /**
2716     * Indicates that the user is currently touching the screen.
2717     * Currently used for the tooltip positioning only.
2718     */
2719    private static final int PFLAG3_FINGER_DOWN = 0x20000;
2720
2721    /**
2722     * Flag indicating that this view is the default-focus view.
2723     *
2724     * @see #isFocusedByDefault()
2725     * @see #setFocusedByDefault(boolean)
2726     */
2727    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
2728
2729    /**
2730     * Whether this view has rendered elements that overlap (see {@link
2731     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2732     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2733     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2734     * determined by whatever {@link #hasOverlappingRendering()} returns.
2735     */
2736    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2737
2738    /**
2739     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2740     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2741     */
2742    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2743
2744    /**
2745     * Flag indicating that the view is temporarily detached from the parent view.
2746     *
2747     * @see #onStartTemporaryDetach()
2748     * @see #onFinishTemporaryDetach()
2749     */
2750    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
2751
2752    /**
2753     * Flag indicating that the view does not wish to be revealed within its parent
2754     * hierarchy when it gains focus. Expressed in the negative since the historical
2755     * default behavior is to reveal on focus; this flag suppresses that behavior.
2756     *
2757     * @see #setRevealOnFocusHint(boolean)
2758     * @see #getRevealOnFocusHint()
2759     */
2760    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
2761
2762    /* End of masks for mPrivateFlags3 */
2763
2764    /**
2765     * Always allow a user to over-scroll this view, provided it is a
2766     * view that can scroll.
2767     *
2768     * @see #getOverScrollMode()
2769     * @see #setOverScrollMode(int)
2770     */
2771    public static final int OVER_SCROLL_ALWAYS = 0;
2772
2773    /**
2774     * Allow a user to over-scroll this view only if the content is large
2775     * enough to meaningfully scroll, provided it is a view that can scroll.
2776     *
2777     * @see #getOverScrollMode()
2778     * @see #setOverScrollMode(int)
2779     */
2780    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2781
2782    /**
2783     * Never allow a user to over-scroll this view.
2784     *
2785     * @see #getOverScrollMode()
2786     * @see #setOverScrollMode(int)
2787     */
2788    public static final int OVER_SCROLL_NEVER = 2;
2789
2790    /**
2791     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2792     * requested the system UI (status bar) to be visible (the default).
2793     *
2794     * @see #setSystemUiVisibility(int)
2795     */
2796    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2797
2798    /**
2799     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2800     * system UI to enter an unobtrusive "low profile" mode.
2801     *
2802     * <p>This is for use in games, book readers, video players, or any other
2803     * "immersive" application where the usual system chrome is deemed too distracting.
2804     *
2805     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2806     *
2807     * @see #setSystemUiVisibility(int)
2808     */
2809    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2810
2811    /**
2812     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2813     * system navigation be temporarily hidden.
2814     *
2815     * <p>This is an even less obtrusive state than that called for by
2816     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2817     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2818     * those to disappear. This is useful (in conjunction with the
2819     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2820     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2821     * window flags) for displaying content using every last pixel on the display.
2822     *
2823     * <p>There is a limitation: because navigation controls are so important, the least user
2824     * interaction will cause them to reappear immediately.  When this happens, both
2825     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2826     * so that both elements reappear at the same time.
2827     *
2828     * @see #setSystemUiVisibility(int)
2829     */
2830    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2831
2832    /**
2833     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2834     * into the normal fullscreen mode so that its content can take over the screen
2835     * while still allowing the user to interact with the application.
2836     *
2837     * <p>This has the same visual effect as
2838     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2839     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2840     * meaning that non-critical screen decorations (such as the status bar) will be
2841     * hidden while the user is in the View's window, focusing the experience on
2842     * that content.  Unlike the window flag, if you are using ActionBar in
2843     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2844     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2845     * hide the action bar.
2846     *
2847     * <p>This approach to going fullscreen is best used over the window flag when
2848     * it is a transient state -- that is, the application does this at certain
2849     * points in its user interaction where it wants to allow the user to focus
2850     * on content, but not as a continuous state.  For situations where the application
2851     * would like to simply stay full screen the entire time (such as a game that
2852     * wants to take over the screen), the
2853     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2854     * is usually a better approach.  The state set here will be removed by the system
2855     * in various situations (such as the user moving to another application) like
2856     * the other system UI states.
2857     *
2858     * <p>When using this flag, the application should provide some easy facility
2859     * for the user to go out of it.  A common example would be in an e-book
2860     * reader, where tapping on the screen brings back whatever screen and UI
2861     * decorations that had been hidden while the user was immersed in reading
2862     * the book.
2863     *
2864     * @see #setSystemUiVisibility(int)
2865     */
2866    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2867
2868    /**
2869     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2870     * flags, we would like a stable view of the content insets given to
2871     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2872     * will always represent the worst case that the application can expect
2873     * as a continuous state.  In the stock Android UI this is the space for
2874     * the system bar, nav bar, and status bar, but not more transient elements
2875     * such as an input method.
2876     *
2877     * The stable layout your UI sees is based on the system UI modes you can
2878     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2879     * then you will get a stable layout for changes of the
2880     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2881     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2882     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2883     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2884     * with a stable layout.  (Note that you should avoid using
2885     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2886     *
2887     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2888     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2889     * then a hidden status bar will be considered a "stable" state for purposes
2890     * here.  This allows your UI to continually hide the status bar, while still
2891     * using the system UI flags to hide the action bar while still retaining
2892     * a stable layout.  Note that changing the window fullscreen flag will never
2893     * provide a stable layout for a clean transition.
2894     *
2895     * <p>If you are using ActionBar in
2896     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2897     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2898     * insets it adds to those given to the application.
2899     */
2900    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2901
2902    /**
2903     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2904     * to be laid out as if it has requested
2905     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2906     * allows it to avoid artifacts when switching in and out of that mode, at
2907     * the expense that some of its user interface may be covered by screen
2908     * decorations when they are shown.  You can perform layout of your inner
2909     * UI elements to account for the navigation system UI through the
2910     * {@link #fitSystemWindows(Rect)} method.
2911     */
2912    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2913
2914    /**
2915     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2916     * to be laid out as if it has requested
2917     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2918     * allows it to avoid artifacts when switching in and out of that mode, at
2919     * the expense that some of its user interface may be covered by screen
2920     * decorations when they are shown.  You can perform layout of your inner
2921     * UI elements to account for non-fullscreen system UI through the
2922     * {@link #fitSystemWindows(Rect)} method.
2923     */
2924    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2925
2926    /**
2927     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2928     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2929     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2930     * user interaction.
2931     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2932     * has an effect when used in combination with that flag.</p>
2933     */
2934    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2935
2936    /**
2937     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2938     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2939     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2940     * experience while also hiding the system bars.  If this flag is not set,
2941     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2942     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2943     * if the user swipes from the top of the screen.
2944     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2945     * system gestures, such as swiping from the top of the screen.  These transient system bars
2946     * will overlay app’s content, may have some degree of transparency, and will automatically
2947     * hide after a short timeout.
2948     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2949     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2950     * with one or both of those flags.</p>
2951     */
2952    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2953
2954    /**
2955     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2956     * is compatible with light status bar backgrounds.
2957     *
2958     * <p>For this to take effect, the window must request
2959     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2960     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2961     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2962     *         FLAG_TRANSLUCENT_STATUS}.
2963     *
2964     * @see android.R.attr#windowLightStatusBar
2965     */
2966    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2967
2968    /**
2969     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
2970     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
2971     */
2972    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
2973
2974    /**
2975     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
2976     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
2977     */
2978    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
2979
2980    /**
2981     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
2982     * that is compatible with light navigation bar backgrounds.
2983     *
2984     * <p>For this to take effect, the window must request
2985     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2986     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2987     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
2988     *         FLAG_TRANSLUCENT_NAVIGATION}.
2989     */
2990    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
2991
2992    /**
2993     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2994     */
2995    @Deprecated
2996    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2997
2998    /**
2999     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3000     */
3001    @Deprecated
3002    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3003
3004    /**
3005     * @hide
3006     *
3007     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3008     * out of the public fields to keep the undefined bits out of the developer's way.
3009     *
3010     * Flag to make the status bar not expandable.  Unless you also
3011     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3012     */
3013    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3014
3015    /**
3016     * @hide
3017     *
3018     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3019     * out of the public fields to keep the undefined bits out of the developer's way.
3020     *
3021     * Flag to hide notification icons and scrolling ticker text.
3022     */
3023    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3024
3025    /**
3026     * @hide
3027     *
3028     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3029     * out of the public fields to keep the undefined bits out of the developer's way.
3030     *
3031     * Flag to disable incoming notification alerts.  This will not block
3032     * icons, but it will block sound, vibrating and other visual or aural notifications.
3033     */
3034    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3035
3036    /**
3037     * @hide
3038     *
3039     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3040     * out of the public fields to keep the undefined bits out of the developer's way.
3041     *
3042     * Flag to hide only the scrolling ticker.  Note that
3043     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3044     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3045     */
3046    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3047
3048    /**
3049     * @hide
3050     *
3051     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3052     * out of the public fields to keep the undefined bits out of the developer's way.
3053     *
3054     * Flag to hide the center system info area.
3055     */
3056    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3057
3058    /**
3059     * @hide
3060     *
3061     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3062     * out of the public fields to keep the undefined bits out of the developer's way.
3063     *
3064     * Flag to hide only the home button.  Don't use this
3065     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3066     */
3067    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3068
3069    /**
3070     * @hide
3071     *
3072     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3073     * out of the public fields to keep the undefined bits out of the developer's way.
3074     *
3075     * Flag to hide only the back button. Don't use this
3076     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3077     */
3078    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3079
3080    /**
3081     * @hide
3082     *
3083     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3084     * out of the public fields to keep the undefined bits out of the developer's way.
3085     *
3086     * Flag to hide only the clock.  You might use this if your activity has
3087     * its own clock making the status bar's clock redundant.
3088     */
3089    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3090
3091    /**
3092     * @hide
3093     *
3094     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3095     * out of the public fields to keep the undefined bits out of the developer's way.
3096     *
3097     * Flag to hide only the recent apps button. Don't use this
3098     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3099     */
3100    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3101
3102    /**
3103     * @hide
3104     *
3105     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3106     * out of the public fields to keep the undefined bits out of the developer's way.
3107     *
3108     * Flag to disable the global search gesture. Don't use this
3109     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3110     */
3111    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3112
3113    /**
3114     * @hide
3115     *
3116     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3117     * out of the public fields to keep the undefined bits out of the developer's way.
3118     *
3119     * Flag to specify that the status bar is displayed in transient mode.
3120     */
3121    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3122
3123    /**
3124     * @hide
3125     *
3126     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3127     * out of the public fields to keep the undefined bits out of the developer's way.
3128     *
3129     * Flag to specify that the navigation bar is displayed in transient mode.
3130     */
3131    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3132
3133    /**
3134     * @hide
3135     *
3136     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3137     * out of the public fields to keep the undefined bits out of the developer's way.
3138     *
3139     * Flag to specify that the hidden status bar would like to be shown.
3140     */
3141    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3142
3143    /**
3144     * @hide
3145     *
3146     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3147     * out of the public fields to keep the undefined bits out of the developer's way.
3148     *
3149     * Flag to specify that the hidden navigation bar would like to be shown.
3150     */
3151    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3152
3153    /**
3154     * @hide
3155     *
3156     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3157     * out of the public fields to keep the undefined bits out of the developer's way.
3158     *
3159     * Flag to specify that the status bar is displayed in translucent mode.
3160     */
3161    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3162
3163    /**
3164     * @hide
3165     *
3166     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3167     * out of the public fields to keep the undefined bits out of the developer's way.
3168     *
3169     * Flag to specify that the navigation bar is displayed in translucent mode.
3170     */
3171    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3172
3173    /**
3174     * @hide
3175     *
3176     * Makes navigation bar transparent (but not the status bar).
3177     */
3178    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3179
3180    /**
3181     * @hide
3182     *
3183     * Makes status bar transparent (but not the navigation bar).
3184     */
3185    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3186
3187    /**
3188     * @hide
3189     *
3190     * Makes both status bar and navigation bar transparent.
3191     */
3192    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3193            | STATUS_BAR_TRANSPARENT;
3194
3195    /**
3196     * @hide
3197     */
3198    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3199
3200    /**
3201     * These are the system UI flags that can be cleared by events outside
3202     * of an application.  Currently this is just the ability to tap on the
3203     * screen while hiding the navigation bar to have it return.
3204     * @hide
3205     */
3206    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3207            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3208            | SYSTEM_UI_FLAG_FULLSCREEN;
3209
3210    /**
3211     * Flags that can impact the layout in relation to system UI.
3212     */
3213    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3214            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3215            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3216
3217    /** @hide */
3218    @IntDef(flag = true,
3219            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3220    @Retention(RetentionPolicy.SOURCE)
3221    public @interface FindViewFlags {}
3222
3223    /**
3224     * Find views that render the specified text.
3225     *
3226     * @see #findViewsWithText(ArrayList, CharSequence, int)
3227     */
3228    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3229
3230    /**
3231     * Find find views that contain the specified content description.
3232     *
3233     * @see #findViewsWithText(ArrayList, CharSequence, int)
3234     */
3235    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3236
3237    /**
3238     * Find views that contain {@link AccessibilityNodeProvider}. Such
3239     * a View is a root of virtual view hierarchy and may contain the searched
3240     * text. If this flag is set Views with providers are automatically
3241     * added and it is a responsibility of the client to call the APIs of
3242     * the provider to determine whether the virtual tree rooted at this View
3243     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3244     * representing the virtual views with this text.
3245     *
3246     * @see #findViewsWithText(ArrayList, CharSequence, int)
3247     *
3248     * @hide
3249     */
3250    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3251
3252    /**
3253     * The undefined cursor position.
3254     *
3255     * @hide
3256     */
3257    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3258
3259    /**
3260     * Indicates that the screen has changed state and is now off.
3261     *
3262     * @see #onScreenStateChanged(int)
3263     */
3264    public static final int SCREEN_STATE_OFF = 0x0;
3265
3266    /**
3267     * Indicates that the screen has changed state and is now on.
3268     *
3269     * @see #onScreenStateChanged(int)
3270     */
3271    public static final int SCREEN_STATE_ON = 0x1;
3272
3273    /**
3274     * Indicates no axis of view scrolling.
3275     */
3276    public static final int SCROLL_AXIS_NONE = 0;
3277
3278    /**
3279     * Indicates scrolling along the horizontal axis.
3280     */
3281    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3282
3283    /**
3284     * Indicates scrolling along the vertical axis.
3285     */
3286    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3287
3288    /**
3289     * Controls the over-scroll mode for this view.
3290     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3291     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3292     * and {@link #OVER_SCROLL_NEVER}.
3293     */
3294    private int mOverScrollMode;
3295
3296    /**
3297     * The parent this view is attached to.
3298     * {@hide}
3299     *
3300     * @see #getParent()
3301     */
3302    protected ViewParent mParent;
3303
3304    /**
3305     * {@hide}
3306     */
3307    AttachInfo mAttachInfo;
3308
3309    /**
3310     * {@hide}
3311     */
3312    @ViewDebug.ExportedProperty(flagMapping = {
3313        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3314                name = "FORCE_LAYOUT"),
3315        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3316                name = "LAYOUT_REQUIRED"),
3317        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3318            name = "DRAWING_CACHE_INVALID", outputIf = false),
3319        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3320        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3321        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3322        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3323    }, formatToHexString = true)
3324
3325    /* @hide */
3326    public int mPrivateFlags;
3327    int mPrivateFlags2;
3328    int mPrivateFlags3;
3329
3330    /**
3331     * This view's request for the visibility of the status bar.
3332     * @hide
3333     */
3334    @ViewDebug.ExportedProperty(flagMapping = {
3335        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3336                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3337                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3338        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3339                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3340                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3341        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3342                                equals = SYSTEM_UI_FLAG_VISIBLE,
3343                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3344    }, formatToHexString = true)
3345    int mSystemUiVisibility;
3346
3347    /**
3348     * Reference count for transient state.
3349     * @see #setHasTransientState(boolean)
3350     */
3351    int mTransientStateCount = 0;
3352
3353    /**
3354     * Count of how many windows this view has been attached to.
3355     */
3356    int mWindowAttachCount;
3357
3358    /**
3359     * The layout parameters associated with this view and used by the parent
3360     * {@link android.view.ViewGroup} to determine how this view should be
3361     * laid out.
3362     * {@hide}
3363     */
3364    protected ViewGroup.LayoutParams mLayoutParams;
3365
3366    /**
3367     * The view flags hold various views states.
3368     * {@hide}
3369     */
3370    @ViewDebug.ExportedProperty(formatToHexString = true)
3371    int mViewFlags;
3372
3373    static class TransformationInfo {
3374        /**
3375         * The transform matrix for the View. This transform is calculated internally
3376         * based on the translation, rotation, and scale properties.
3377         *
3378         * Do *not* use this variable directly; instead call getMatrix(), which will
3379         * load the value from the View's RenderNode.
3380         */
3381        private final Matrix mMatrix = new Matrix();
3382
3383        /**
3384         * The inverse transform matrix for the View. This transform is calculated
3385         * internally based on the translation, rotation, and scale properties.
3386         *
3387         * Do *not* use this variable directly; instead call getInverseMatrix(),
3388         * which will load the value from the View's RenderNode.
3389         */
3390        private Matrix mInverseMatrix;
3391
3392        /**
3393         * The opacity of the View. This is a value from 0 to 1, where 0 means
3394         * completely transparent and 1 means completely opaque.
3395         */
3396        @ViewDebug.ExportedProperty
3397        float mAlpha = 1f;
3398
3399        /**
3400         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3401         * property only used by transitions, which is composited with the other alpha
3402         * values to calculate the final visual alpha value.
3403         */
3404        float mTransitionAlpha = 1f;
3405    }
3406
3407    /** @hide */
3408    public TransformationInfo mTransformationInfo;
3409
3410    /**
3411     * Current clip bounds. to which all drawing of this view are constrained.
3412     */
3413    Rect mClipBounds = null;
3414
3415    private boolean mLastIsOpaque;
3416
3417    /**
3418     * The distance in pixels from the left edge of this view's parent
3419     * to the left edge of this view.
3420     * {@hide}
3421     */
3422    @ViewDebug.ExportedProperty(category = "layout")
3423    protected int mLeft;
3424    /**
3425     * The distance in pixels from the left edge of this view's parent
3426     * to the right edge of this view.
3427     * {@hide}
3428     */
3429    @ViewDebug.ExportedProperty(category = "layout")
3430    protected int mRight;
3431    /**
3432     * The distance in pixels from the top edge of this view's parent
3433     * to the top edge of this view.
3434     * {@hide}
3435     */
3436    @ViewDebug.ExportedProperty(category = "layout")
3437    protected int mTop;
3438    /**
3439     * The distance in pixels from the top edge of this view's parent
3440     * to the bottom edge of this view.
3441     * {@hide}
3442     */
3443    @ViewDebug.ExportedProperty(category = "layout")
3444    protected int mBottom;
3445
3446    /**
3447     * The offset, in pixels, by which the content of this view is scrolled
3448     * horizontally.
3449     * {@hide}
3450     */
3451    @ViewDebug.ExportedProperty(category = "scrolling")
3452    protected int mScrollX;
3453    /**
3454     * The offset, in pixels, by which the content of this view is scrolled
3455     * vertically.
3456     * {@hide}
3457     */
3458    @ViewDebug.ExportedProperty(category = "scrolling")
3459    protected int mScrollY;
3460
3461    /**
3462     * The left padding in pixels, that is the distance in pixels between the
3463     * left edge of this view and the left edge of its content.
3464     * {@hide}
3465     */
3466    @ViewDebug.ExportedProperty(category = "padding")
3467    protected int mPaddingLeft = 0;
3468    /**
3469     * The right padding in pixels, that is the distance in pixels between the
3470     * right edge of this view and the right edge of its content.
3471     * {@hide}
3472     */
3473    @ViewDebug.ExportedProperty(category = "padding")
3474    protected int mPaddingRight = 0;
3475    /**
3476     * The top padding in pixels, that is the distance in pixels between the
3477     * top edge of this view and the top edge of its content.
3478     * {@hide}
3479     */
3480    @ViewDebug.ExportedProperty(category = "padding")
3481    protected int mPaddingTop;
3482    /**
3483     * The bottom padding in pixels, that is the distance in pixels between the
3484     * bottom edge of this view and the bottom edge of its content.
3485     * {@hide}
3486     */
3487    @ViewDebug.ExportedProperty(category = "padding")
3488    protected int mPaddingBottom;
3489
3490    /**
3491     * The layout insets in pixels, that is the distance in pixels between the
3492     * visible edges of this view its bounds.
3493     */
3494    private Insets mLayoutInsets;
3495
3496    /**
3497     * Briefly describes the view and is primarily used for accessibility support.
3498     */
3499    private CharSequence mContentDescription;
3500
3501    /**
3502     * Specifies the id of a view for which this view serves as a label for
3503     * accessibility purposes.
3504     */
3505    private int mLabelForId = View.NO_ID;
3506
3507    /**
3508     * Predicate for matching labeled view id with its label for
3509     * accessibility purposes.
3510     */
3511    private MatchLabelForPredicate mMatchLabelForPredicate;
3512
3513    /**
3514     * Specifies a view before which this one is visited in accessibility traversal.
3515     */
3516    private int mAccessibilityTraversalBeforeId = NO_ID;
3517
3518    /**
3519     * Specifies a view after which this one is visited in accessibility traversal.
3520     */
3521    private int mAccessibilityTraversalAfterId = NO_ID;
3522
3523    /**
3524     * Predicate for matching a view by its id.
3525     */
3526    private MatchIdPredicate mMatchIdPredicate;
3527
3528    /**
3529     * Cache the paddingRight set by the user to append to the scrollbar's size.
3530     *
3531     * @hide
3532     */
3533    @ViewDebug.ExportedProperty(category = "padding")
3534    protected int mUserPaddingRight;
3535
3536    /**
3537     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3538     *
3539     * @hide
3540     */
3541    @ViewDebug.ExportedProperty(category = "padding")
3542    protected int mUserPaddingBottom;
3543
3544    /**
3545     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3546     *
3547     * @hide
3548     */
3549    @ViewDebug.ExportedProperty(category = "padding")
3550    protected int mUserPaddingLeft;
3551
3552    /**
3553     * Cache the paddingStart set by the user to append to the scrollbar's size.
3554     *
3555     */
3556    @ViewDebug.ExportedProperty(category = "padding")
3557    int mUserPaddingStart;
3558
3559    /**
3560     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3561     *
3562     */
3563    @ViewDebug.ExportedProperty(category = "padding")
3564    int mUserPaddingEnd;
3565
3566    /**
3567     * Cache initial left padding.
3568     *
3569     * @hide
3570     */
3571    int mUserPaddingLeftInitial;
3572
3573    /**
3574     * Cache initial right padding.
3575     *
3576     * @hide
3577     */
3578    int mUserPaddingRightInitial;
3579
3580    /**
3581     * Default undefined padding
3582     */
3583    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3584
3585    /**
3586     * Cache if a left padding has been defined
3587     */
3588    private boolean mLeftPaddingDefined = false;
3589
3590    /**
3591     * Cache if a right padding has been defined
3592     */
3593    private boolean mRightPaddingDefined = false;
3594
3595    /**
3596     * @hide
3597     */
3598    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3599    /**
3600     * @hide
3601     */
3602    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3603
3604    private LongSparseLongArray mMeasureCache;
3605
3606    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3607    private Drawable mBackground;
3608    private TintInfo mBackgroundTint;
3609
3610    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3611    private ForegroundInfo mForegroundInfo;
3612
3613    private Drawable mScrollIndicatorDrawable;
3614
3615    /**
3616     * RenderNode used for backgrounds.
3617     * <p>
3618     * When non-null and valid, this is expected to contain an up-to-date copy
3619     * of the background drawable. It is cleared on temporary detach, and reset
3620     * on cleanup.
3621     */
3622    private RenderNode mBackgroundRenderNode;
3623
3624    private int mBackgroundResource;
3625    private boolean mBackgroundSizeChanged;
3626
3627    private String mTransitionName;
3628
3629    static class TintInfo {
3630        ColorStateList mTintList;
3631        PorterDuff.Mode mTintMode;
3632        boolean mHasTintMode;
3633        boolean mHasTintList;
3634    }
3635
3636    private static class ForegroundInfo {
3637        private Drawable mDrawable;
3638        private TintInfo mTintInfo;
3639        private int mGravity = Gravity.FILL;
3640        private boolean mInsidePadding = true;
3641        private boolean mBoundsChanged = true;
3642        private final Rect mSelfBounds = new Rect();
3643        private final Rect mOverlayBounds = new Rect();
3644    }
3645
3646    static class ListenerInfo {
3647        /**
3648         * Listener used to dispatch focus change events.
3649         * This field should be made private, so it is hidden from the SDK.
3650         * {@hide}
3651         */
3652        protected OnFocusChangeListener mOnFocusChangeListener;
3653
3654        /**
3655         * Listeners for layout change events.
3656         */
3657        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3658
3659        protected OnScrollChangeListener mOnScrollChangeListener;
3660
3661        /**
3662         * Listeners for attach events.
3663         */
3664        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3665
3666        /**
3667         * Listener used to dispatch click events.
3668         * This field should be made private, so it is hidden from the SDK.
3669         * {@hide}
3670         */
3671        public OnClickListener mOnClickListener;
3672
3673        /**
3674         * Listener used to dispatch long click events.
3675         * This field should be made private, so it is hidden from the SDK.
3676         * {@hide}
3677         */
3678        protected OnLongClickListener mOnLongClickListener;
3679
3680        /**
3681         * Listener used to dispatch context click events. This field should be made private, so it
3682         * is hidden from the SDK.
3683         * {@hide}
3684         */
3685        protected OnContextClickListener mOnContextClickListener;
3686
3687        /**
3688         * Listener used to build the context menu.
3689         * This field should be made private, so it is hidden from the SDK.
3690         * {@hide}
3691         */
3692        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3693
3694        private OnKeyListener mOnKeyListener;
3695
3696        private OnTouchListener mOnTouchListener;
3697
3698        private OnHoverListener mOnHoverListener;
3699
3700        private OnGenericMotionListener mOnGenericMotionListener;
3701
3702        private OnDragListener mOnDragListener;
3703
3704        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3705
3706        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3707    }
3708
3709    ListenerInfo mListenerInfo;
3710
3711    private static class TooltipInfo {
3712        /**
3713         * Text to be displayed in a tooltip popup.
3714         */
3715        @Nullable
3716        CharSequence mTooltipText;
3717
3718        /**
3719         * View-relative position of the tooltip anchor point.
3720         */
3721        int mAnchorX;
3722        int mAnchorY;
3723
3724        /**
3725         * The tooltip popup.
3726         */
3727        @Nullable
3728        TooltipPopup mTooltipPopup;
3729
3730        /**
3731         * Set to true if the tooltip was shown as a result of a long click.
3732         */
3733        boolean mTooltipFromLongClick;
3734
3735        /**
3736         * Keep these Runnables so that they can be used to reschedule.
3737         */
3738        Runnable mShowTooltipRunnable;
3739        Runnable mHideTooltipRunnable;
3740    }
3741
3742    TooltipInfo mTooltipInfo;
3743
3744    // Temporary values used to hold (x,y) coordinates when delegating from the
3745    // two-arg performLongClick() method to the legacy no-arg version.
3746    private float mLongClickX = Float.NaN;
3747    private float mLongClickY = Float.NaN;
3748
3749    /**
3750     * The application environment this view lives in.
3751     * This field should be made private, so it is hidden from the SDK.
3752     * {@hide}
3753     */
3754    @ViewDebug.ExportedProperty(deepExport = true)
3755    protected Context mContext;
3756
3757    private final Resources mResources;
3758
3759    private ScrollabilityCache mScrollCache;
3760
3761    private int[] mDrawableState = null;
3762
3763    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3764
3765    /**
3766     * Animator that automatically runs based on state changes.
3767     */
3768    private StateListAnimator mStateListAnimator;
3769
3770    /**
3771     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3772     * the user may specify which view to go to next.
3773     */
3774    private int mNextFocusLeftId = View.NO_ID;
3775
3776    /**
3777     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3778     * the user may specify which view to go to next.
3779     */
3780    private int mNextFocusRightId = View.NO_ID;
3781
3782    /**
3783     * When this view has focus and the next focus is {@link #FOCUS_UP},
3784     * the user may specify which view to go to next.
3785     */
3786    private int mNextFocusUpId = View.NO_ID;
3787
3788    /**
3789     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3790     * the user may specify which view to go to next.
3791     */
3792    private int mNextFocusDownId = View.NO_ID;
3793
3794    /**
3795     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3796     * the user may specify which view to go to next.
3797     */
3798    int mNextFocusForwardId = View.NO_ID;
3799
3800    /**
3801     * User-specified next keyboard navigation cluster.
3802     */
3803    int mNextClusterForwardId = View.NO_ID;
3804
3805    private CheckForLongPress mPendingCheckForLongPress;
3806    private CheckForTap mPendingCheckForTap = null;
3807    private PerformClick mPerformClick;
3808    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3809
3810    private UnsetPressedState mUnsetPressedState;
3811
3812    /**
3813     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3814     * up event while a long press is invoked as soon as the long press duration is reached, so
3815     * a long press could be performed before the tap is checked, in which case the tap's action
3816     * should not be invoked.
3817     */
3818    private boolean mHasPerformedLongPress;
3819
3820    /**
3821     * Whether a context click button is currently pressed down. This is true when the stylus is
3822     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3823     * pressed. This is false once the button is released or if the stylus has been lifted.
3824     */
3825    private boolean mInContextButtonPress;
3826
3827    /**
3828     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3829     * true after a stylus button press has occured, when the next up event should not be recognized
3830     * as a tap.
3831     */
3832    private boolean mIgnoreNextUpEvent;
3833
3834    /**
3835     * The minimum height of the view. We'll try our best to have the height
3836     * of this view to at least this amount.
3837     */
3838    @ViewDebug.ExportedProperty(category = "measurement")
3839    private int mMinHeight;
3840
3841    /**
3842     * The minimum width of the view. We'll try our best to have the width
3843     * of this view to at least this amount.
3844     */
3845    @ViewDebug.ExportedProperty(category = "measurement")
3846    private int mMinWidth;
3847
3848    /**
3849     * The delegate to handle touch events that are physically in this view
3850     * but should be handled by another view.
3851     */
3852    private TouchDelegate mTouchDelegate = null;
3853
3854    /**
3855     * Solid color to use as a background when creating the drawing cache. Enables
3856     * the cache to use 16 bit bitmaps instead of 32 bit.
3857     */
3858    private int mDrawingCacheBackgroundColor = 0;
3859
3860    /**
3861     * Special tree observer used when mAttachInfo is null.
3862     */
3863    private ViewTreeObserver mFloatingTreeObserver;
3864
3865    /**
3866     * Cache the touch slop from the context that created the view.
3867     */
3868    private int mTouchSlop;
3869
3870    /**
3871     * Object that handles automatic animation of view properties.
3872     */
3873    private ViewPropertyAnimator mAnimator = null;
3874
3875    /**
3876     * List of registered FrameMetricsObservers.
3877     */
3878    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
3879
3880    /**
3881     * Flag indicating that a drag can cross window boundaries.  When
3882     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3883     * with this flag set, all visible applications with targetSdkVersion >=
3884     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
3885     * in the drag operation and receive the dragged content.
3886     *
3887     * <p>If this is the only flag set, then the drag recipient will only have access to text data
3888     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3889     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
3890     */
3891    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3892
3893    /**
3894     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3895     * request read access to the content URI(s) contained in the {@link ClipData} object.
3896     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3897     */
3898    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3899
3900    /**
3901     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3902     * request write access to the content URI(s) contained in the {@link ClipData} object.
3903     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3904     */
3905    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3906
3907    /**
3908     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3909     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3910     * reboots until explicitly revoked with
3911     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3912     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3913     */
3914    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3915            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3916
3917    /**
3918     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3919     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3920     * match against the original granted URI.
3921     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3922     */
3923    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3924            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3925
3926    /**
3927     * Flag indicating that the drag shadow will be opaque.  When
3928     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3929     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3930     */
3931    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3932
3933    /**
3934     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3935     */
3936    private float mVerticalScrollFactor;
3937
3938    /**
3939     * Position of the vertical scroll bar.
3940     */
3941    private int mVerticalScrollbarPosition;
3942
3943    /**
3944     * Position the scroll bar at the default position as determined by the system.
3945     */
3946    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3947
3948    /**
3949     * Position the scroll bar along the left edge.
3950     */
3951    public static final int SCROLLBAR_POSITION_LEFT = 1;
3952
3953    /**
3954     * Position the scroll bar along the right edge.
3955     */
3956    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3957
3958    /**
3959     * Indicates that the view does not have a layer.
3960     *
3961     * @see #getLayerType()
3962     * @see #setLayerType(int, android.graphics.Paint)
3963     * @see #LAYER_TYPE_SOFTWARE
3964     * @see #LAYER_TYPE_HARDWARE
3965     */
3966    public static final int LAYER_TYPE_NONE = 0;
3967
3968    /**
3969     * <p>Indicates that the view has a software layer. A software layer is backed
3970     * by a bitmap and causes the view to be rendered using Android's software
3971     * rendering pipeline, even if hardware acceleration is enabled.</p>
3972     *
3973     * <p>Software layers have various usages:</p>
3974     * <p>When the application is not using hardware acceleration, a software layer
3975     * is useful to apply a specific color filter and/or blending mode and/or
3976     * translucency to a view and all its children.</p>
3977     * <p>When the application is using hardware acceleration, a software layer
3978     * is useful to render drawing primitives not supported by the hardware
3979     * accelerated pipeline. It can also be used to cache a complex view tree
3980     * into a texture and reduce the complexity of drawing operations. For instance,
3981     * when animating a complex view tree with a translation, a software layer can
3982     * be used to render the view tree only once.</p>
3983     * <p>Software layers should be avoided when the affected view tree updates
3984     * often. Every update will require to re-render the software layer, which can
3985     * potentially be slow (particularly when hardware acceleration is turned on
3986     * since the layer will have to be uploaded into a hardware texture after every
3987     * update.)</p>
3988     *
3989     * @see #getLayerType()
3990     * @see #setLayerType(int, android.graphics.Paint)
3991     * @see #LAYER_TYPE_NONE
3992     * @see #LAYER_TYPE_HARDWARE
3993     */
3994    public static final int LAYER_TYPE_SOFTWARE = 1;
3995
3996    /**
3997     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3998     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3999     * OpenGL hardware) and causes the view to be rendered using Android's hardware
4000     * rendering pipeline, but only if hardware acceleration is turned on for the
4001     * view hierarchy. When hardware acceleration is turned off, hardware layers
4002     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4003     *
4004     * <p>A hardware layer is useful to apply a specific color filter and/or
4005     * blending mode and/or translucency to a view and all its children.</p>
4006     * <p>A hardware layer can be used to cache a complex view tree into a
4007     * texture and reduce the complexity of drawing operations. For instance,
4008     * when animating a complex view tree with a translation, a hardware layer can
4009     * be used to render the view tree only once.</p>
4010     * <p>A hardware layer can also be used to increase the rendering quality when
4011     * rotation transformations are applied on a view. It can also be used to
4012     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4013     *
4014     * @see #getLayerType()
4015     * @see #setLayerType(int, android.graphics.Paint)
4016     * @see #LAYER_TYPE_NONE
4017     * @see #LAYER_TYPE_SOFTWARE
4018     */
4019    public static final int LAYER_TYPE_HARDWARE = 2;
4020
4021    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4022            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4023            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4024            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4025    })
4026    int mLayerType = LAYER_TYPE_NONE;
4027    Paint mLayerPaint;
4028
4029
4030    /**
4031     * Set when a request was made to decide if views in an {@link android.app.Activity} can be
4032     * auto-filled by an {@link android.service.autofill.AutoFillService}.
4033     *
4034     * <p>Since this request is made without a explicit user consent, the resulting
4035     * {@link android.app.assist.AssistStructure} should not contain any PII
4036     * (Personally Identifiable Information).
4037     *
4038     * <p>Examples:
4039     * <ul>
4040     * <li>{@link android.widget.TextView} texts should only be included when they were set by
4041     * static resources.
4042     * <li>{@link android.webkit.WebView} virtual children should be restricted to a subset of
4043     * input fields and tags (like {@code id}).
4044     * </ul>
4045     */
4046    // TODO(b/33197203) (b/34078930): improve documentation: mention all cases, show examples, etc.
4047    // In particular, be more specific about webview restrictions
4048    public static final int AUTO_FILL_FLAG_TYPE_FILL = 0x1;
4049
4050    /**
4051     * Set when the user explicitly asked a {@link android.service.autofill.AutoFillService} to save
4052     * the value of the {@link View}s in an {@link android.app.Activity}.
4053     *
4054     * <p>The resulting {@link android.app.assist.AssistStructure} can contain any kind of PII
4055     * (Personally Identifiable Information). For example, the text of password fields should be
4056     * included since that's what's typically saved.
4057     */
4058    public static final int AUTO_FILL_FLAG_TYPE_SAVE = 0x2;
4059
4060    /**
4061     * Set to true when drawing cache is enabled and cannot be created.
4062     *
4063     * @hide
4064     */
4065    public boolean mCachingFailed;
4066    private Bitmap mDrawingCache;
4067    private Bitmap mUnscaledDrawingCache;
4068
4069    /**
4070     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4071     * <p>
4072     * When non-null and valid, this is expected to contain an up-to-date copy
4073     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4074     * cleanup.
4075     */
4076    final RenderNode mRenderNode;
4077
4078    /**
4079     * Set to true when the view is sending hover accessibility events because it
4080     * is the innermost hovered view.
4081     */
4082    private boolean mSendingHoverAccessibilityEvents;
4083
4084    /**
4085     * Delegate for injecting accessibility functionality.
4086     */
4087    AccessibilityDelegate mAccessibilityDelegate;
4088
4089    /**
4090     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4091     * and add/remove objects to/from the overlay directly through the Overlay methods.
4092     */
4093    ViewOverlay mOverlay;
4094
4095    /**
4096     * The currently active parent view for receiving delegated nested scrolling events.
4097     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4098     * by {@link #stopNestedScroll()} at the same point where we clear
4099     * requestDisallowInterceptTouchEvent.
4100     */
4101    private ViewParent mNestedScrollingParent;
4102
4103    /**
4104     * Consistency verifier for debugging purposes.
4105     * @hide
4106     */
4107    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4108            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4109                    new InputEventConsistencyVerifier(this, 0) : null;
4110
4111    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4112
4113    private int[] mTempNestedScrollConsumed;
4114
4115    /**
4116     * An overlay is going to draw this View instead of being drawn as part of this
4117     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4118     * when this view is invalidated.
4119     */
4120    GhostView mGhostView;
4121
4122    /**
4123     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4124     * @hide
4125     */
4126    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4127    public String[] mAttributes;
4128
4129    /**
4130     * Maps a Resource id to its name.
4131     */
4132    private static SparseArray<String> mAttributeMap;
4133
4134    /**
4135     * Queue of pending runnables. Used to postpone calls to post() until this
4136     * view is attached and has a handler.
4137     */
4138    private HandlerActionQueue mRunQueue;
4139
4140    /**
4141     * The pointer icon when the mouse hovers on this view. The default is null.
4142     */
4143    private PointerIcon mPointerIcon;
4144
4145    /**
4146     * @hide
4147     */
4148    String mStartActivityRequestWho;
4149
4150    @Nullable
4151    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4152
4153    /**
4154     * Simple constructor to use when creating a view from code.
4155     *
4156     * @param context The Context the view is running in, through which it can
4157     *        access the current theme, resources, etc.
4158     */
4159    public View(Context context) {
4160        mContext = context;
4161        mResources = context != null ? context.getResources() : null;
4162        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4163        // Set some flags defaults
4164        mPrivateFlags2 =
4165                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4166                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4167                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4168                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4169                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4170                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4171        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4172        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4173        mUserPaddingStart = UNDEFINED_PADDING;
4174        mUserPaddingEnd = UNDEFINED_PADDING;
4175        mRenderNode = RenderNode.create(getClass().getName(), this);
4176
4177        if (!sCompatibilityDone && context != null) {
4178            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4179
4180            // Older apps may need this compatibility hack for measurement.
4181            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
4182
4183            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4184            // of whether a layout was requested on that View.
4185            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
4186
4187            Canvas.sCompatibilityRestore = targetSdkVersion < M;
4188
4189            // In M and newer, our widgets can pass a "hint" value in the size
4190            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4191            // know what the expected parent size is going to be, so e.g. list items can size
4192            // themselves at 1/3 the size of their container. It breaks older apps though,
4193            // specifically apps that use some popular open source libraries.
4194            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
4195
4196            // Old versions of the platform would give different results from
4197            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4198            // modes, so we always need to run an additional EXACTLY pass.
4199            sAlwaysRemeasureExactly = targetSdkVersion <= M;
4200
4201            // Prior to N, layout params could change without requiring a
4202            // subsequent call to setLayoutParams() and they would usually
4203            // work. Partial layout breaks this assumption.
4204            sLayoutParamsAlwaysChanged = targetSdkVersion <= M;
4205
4206            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4207            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4208            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M;
4209
4210            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4211            // in apps so we target check it to avoid breaking existing apps.
4212            sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N;
4213
4214            sCascadedDragDrop = targetSdkVersion < N;
4215
4216            sCompatibilityDone = true;
4217        }
4218    }
4219
4220    /**
4221     * Constructor that is called when inflating a view from XML. This is called
4222     * when a view is being constructed from an XML file, supplying attributes
4223     * that were specified in the XML file. This version uses a default style of
4224     * 0, so the only attribute values applied are those in the Context's Theme
4225     * and the given AttributeSet.
4226     *
4227     * <p>
4228     * The method onFinishInflate() will be called after all children have been
4229     * added.
4230     *
4231     * @param context The Context the view is running in, through which it can
4232     *        access the current theme, resources, etc.
4233     * @param attrs The attributes of the XML tag that is inflating the view.
4234     * @see #View(Context, AttributeSet, int)
4235     */
4236    public View(Context context, @Nullable AttributeSet attrs) {
4237        this(context, attrs, 0);
4238    }
4239
4240    /**
4241     * Perform inflation from XML and apply a class-specific base style from a
4242     * theme attribute. This constructor of View allows subclasses to use their
4243     * own base style when they are inflating. For example, a Button class's
4244     * constructor would call this version of the super class constructor and
4245     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4246     * allows the theme's button style to modify all of the base view attributes
4247     * (in particular its background) as well as the Button class's attributes.
4248     *
4249     * @param context The Context the view is running in, through which it can
4250     *        access the current theme, resources, etc.
4251     * @param attrs The attributes of the XML tag that is inflating the view.
4252     * @param defStyleAttr An attribute in the current theme that contains a
4253     *        reference to a style resource that supplies default values for
4254     *        the view. Can be 0 to not look for defaults.
4255     * @see #View(Context, AttributeSet)
4256     */
4257    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4258        this(context, attrs, defStyleAttr, 0);
4259    }
4260
4261    /**
4262     * Perform inflation from XML and apply a class-specific base style from a
4263     * theme attribute or style resource. This constructor of View allows
4264     * subclasses to use their own base style when they are inflating.
4265     * <p>
4266     * When determining the final value of a particular attribute, there are
4267     * four inputs that come into play:
4268     * <ol>
4269     * <li>Any attribute values in the given AttributeSet.
4270     * <li>The style resource specified in the AttributeSet (named "style").
4271     * <li>The default style specified by <var>defStyleAttr</var>.
4272     * <li>The default style specified by <var>defStyleRes</var>.
4273     * <li>The base values in this theme.
4274     * </ol>
4275     * <p>
4276     * Each of these inputs is considered in-order, with the first listed taking
4277     * precedence over the following ones. In other words, if in the
4278     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4279     * , then the button's text will <em>always</em> be black, regardless of
4280     * what is specified in any of the styles.
4281     *
4282     * @param context The Context the view is running in, through which it can
4283     *        access the current theme, resources, etc.
4284     * @param attrs The attributes of the XML tag that is inflating the view.
4285     * @param defStyleAttr An attribute in the current theme that contains a
4286     *        reference to a style resource that supplies default values for
4287     *        the view. Can be 0 to not look for defaults.
4288     * @param defStyleRes A resource identifier of a style resource that
4289     *        supplies default values for the view, used only if
4290     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4291     *        to not look for defaults.
4292     * @see #View(Context, AttributeSet, int)
4293     */
4294    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4295        this(context);
4296
4297        final TypedArray a = context.obtainStyledAttributes(
4298                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4299
4300        if (mDebugViewAttributes) {
4301            saveAttributeData(attrs, a);
4302        }
4303
4304        Drawable background = null;
4305
4306        int leftPadding = -1;
4307        int topPadding = -1;
4308        int rightPadding = -1;
4309        int bottomPadding = -1;
4310        int startPadding = UNDEFINED_PADDING;
4311        int endPadding = UNDEFINED_PADDING;
4312
4313        int padding = -1;
4314        int paddingHorizontal = -1;
4315        int paddingVertical = -1;
4316
4317        int viewFlagValues = 0;
4318        int viewFlagMasks = 0;
4319
4320        boolean setScrollContainer = false;
4321
4322        int x = 0;
4323        int y = 0;
4324
4325        float tx = 0;
4326        float ty = 0;
4327        float tz = 0;
4328        float elevation = 0;
4329        float rotation = 0;
4330        float rotationX = 0;
4331        float rotationY = 0;
4332        float sx = 1f;
4333        float sy = 1f;
4334        boolean transformSet = false;
4335
4336        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4337        int overScrollMode = mOverScrollMode;
4338        boolean initializeScrollbars = false;
4339        boolean initializeScrollIndicators = false;
4340
4341        boolean startPaddingDefined = false;
4342        boolean endPaddingDefined = false;
4343        boolean leftPaddingDefined = false;
4344        boolean rightPaddingDefined = false;
4345
4346        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4347
4348        // Set default values.
4349        viewFlagValues |= FOCUSABLE_AUTO;
4350        viewFlagMasks |= FOCUSABLE_AUTO;
4351
4352        final int N = a.getIndexCount();
4353        for (int i = 0; i < N; i++) {
4354            int attr = a.getIndex(i);
4355            switch (attr) {
4356                case com.android.internal.R.styleable.View_background:
4357                    background = a.getDrawable(attr);
4358                    break;
4359                case com.android.internal.R.styleable.View_padding:
4360                    padding = a.getDimensionPixelSize(attr, -1);
4361                    mUserPaddingLeftInitial = padding;
4362                    mUserPaddingRightInitial = padding;
4363                    leftPaddingDefined = true;
4364                    rightPaddingDefined = true;
4365                    break;
4366                case com.android.internal.R.styleable.View_paddingHorizontal:
4367                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4368                    mUserPaddingLeftInitial = paddingHorizontal;
4369                    mUserPaddingRightInitial = paddingHorizontal;
4370                    leftPaddingDefined = true;
4371                    rightPaddingDefined = true;
4372                    break;
4373                case com.android.internal.R.styleable.View_paddingVertical:
4374                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4375                    break;
4376                 case com.android.internal.R.styleable.View_paddingLeft:
4377                    leftPadding = a.getDimensionPixelSize(attr, -1);
4378                    mUserPaddingLeftInitial = leftPadding;
4379                    leftPaddingDefined = true;
4380                    break;
4381                case com.android.internal.R.styleable.View_paddingTop:
4382                    topPadding = a.getDimensionPixelSize(attr, -1);
4383                    break;
4384                case com.android.internal.R.styleable.View_paddingRight:
4385                    rightPadding = a.getDimensionPixelSize(attr, -1);
4386                    mUserPaddingRightInitial = rightPadding;
4387                    rightPaddingDefined = true;
4388                    break;
4389                case com.android.internal.R.styleable.View_paddingBottom:
4390                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4391                    break;
4392                case com.android.internal.R.styleable.View_paddingStart:
4393                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4394                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4395                    break;
4396                case com.android.internal.R.styleable.View_paddingEnd:
4397                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4398                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4399                    break;
4400                case com.android.internal.R.styleable.View_scrollX:
4401                    x = a.getDimensionPixelOffset(attr, 0);
4402                    break;
4403                case com.android.internal.R.styleable.View_scrollY:
4404                    y = a.getDimensionPixelOffset(attr, 0);
4405                    break;
4406                case com.android.internal.R.styleable.View_alpha:
4407                    setAlpha(a.getFloat(attr, 1f));
4408                    break;
4409                case com.android.internal.R.styleable.View_transformPivotX:
4410                    setPivotX(a.getDimension(attr, 0));
4411                    break;
4412                case com.android.internal.R.styleable.View_transformPivotY:
4413                    setPivotY(a.getDimension(attr, 0));
4414                    break;
4415                case com.android.internal.R.styleable.View_translationX:
4416                    tx = a.getDimension(attr, 0);
4417                    transformSet = true;
4418                    break;
4419                case com.android.internal.R.styleable.View_translationY:
4420                    ty = a.getDimension(attr, 0);
4421                    transformSet = true;
4422                    break;
4423                case com.android.internal.R.styleable.View_translationZ:
4424                    tz = a.getDimension(attr, 0);
4425                    transformSet = true;
4426                    break;
4427                case com.android.internal.R.styleable.View_elevation:
4428                    elevation = a.getDimension(attr, 0);
4429                    transformSet = true;
4430                    break;
4431                case com.android.internal.R.styleable.View_rotation:
4432                    rotation = a.getFloat(attr, 0);
4433                    transformSet = true;
4434                    break;
4435                case com.android.internal.R.styleable.View_rotationX:
4436                    rotationX = a.getFloat(attr, 0);
4437                    transformSet = true;
4438                    break;
4439                case com.android.internal.R.styleable.View_rotationY:
4440                    rotationY = a.getFloat(attr, 0);
4441                    transformSet = true;
4442                    break;
4443                case com.android.internal.R.styleable.View_scaleX:
4444                    sx = a.getFloat(attr, 1f);
4445                    transformSet = true;
4446                    break;
4447                case com.android.internal.R.styleable.View_scaleY:
4448                    sy = a.getFloat(attr, 1f);
4449                    transformSet = true;
4450                    break;
4451                case com.android.internal.R.styleable.View_id:
4452                    mID = a.getResourceId(attr, NO_ID);
4453                    break;
4454                case com.android.internal.R.styleable.View_tag:
4455                    mTag = a.getText(attr);
4456                    break;
4457                case com.android.internal.R.styleable.View_fitsSystemWindows:
4458                    if (a.getBoolean(attr, false)) {
4459                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4460                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4461                    }
4462                    break;
4463                case com.android.internal.R.styleable.View_focusable:
4464                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4465                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4466                        viewFlagMasks |= FOCUSABLE_MASK;
4467                    }
4468                    break;
4469                case com.android.internal.R.styleable.View_focusableInTouchMode:
4470                    if (a.getBoolean(attr, false)) {
4471                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4472                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4473                    }
4474                    break;
4475                case com.android.internal.R.styleable.View_clickable:
4476                    if (a.getBoolean(attr, false)) {
4477                        viewFlagValues |= CLICKABLE;
4478                        viewFlagMasks |= CLICKABLE;
4479                    }
4480                    break;
4481                case com.android.internal.R.styleable.View_longClickable:
4482                    if (a.getBoolean(attr, false)) {
4483                        viewFlagValues |= LONG_CLICKABLE;
4484                        viewFlagMasks |= LONG_CLICKABLE;
4485                    }
4486                    break;
4487                case com.android.internal.R.styleable.View_contextClickable:
4488                    if (a.getBoolean(attr, false)) {
4489                        viewFlagValues |= CONTEXT_CLICKABLE;
4490                        viewFlagMasks |= CONTEXT_CLICKABLE;
4491                    }
4492                    break;
4493                case com.android.internal.R.styleable.View_saveEnabled:
4494                    if (!a.getBoolean(attr, true)) {
4495                        viewFlagValues |= SAVE_DISABLED;
4496                        viewFlagMasks |= SAVE_DISABLED_MASK;
4497                    }
4498                    break;
4499                case com.android.internal.R.styleable.View_duplicateParentState:
4500                    if (a.getBoolean(attr, false)) {
4501                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4502                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4503                    }
4504                    break;
4505                case com.android.internal.R.styleable.View_visibility:
4506                    final int visibility = a.getInt(attr, 0);
4507                    if (visibility != 0) {
4508                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4509                        viewFlagMasks |= VISIBILITY_MASK;
4510                    }
4511                    break;
4512                case com.android.internal.R.styleable.View_layoutDirection:
4513                    // Clear any layout direction flags (included resolved bits) already set
4514                    mPrivateFlags2 &=
4515                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4516                    // Set the layout direction flags depending on the value of the attribute
4517                    final int layoutDirection = a.getInt(attr, -1);
4518                    final int value = (layoutDirection != -1) ?
4519                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4520                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4521                    break;
4522                case com.android.internal.R.styleable.View_drawingCacheQuality:
4523                    final int cacheQuality = a.getInt(attr, 0);
4524                    if (cacheQuality != 0) {
4525                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4526                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4527                    }
4528                    break;
4529                case com.android.internal.R.styleable.View_contentDescription:
4530                    setContentDescription(a.getString(attr));
4531                    break;
4532                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4533                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4534                    break;
4535                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4536                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4537                    break;
4538                case com.android.internal.R.styleable.View_labelFor:
4539                    setLabelFor(a.getResourceId(attr, NO_ID));
4540                    break;
4541                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4542                    if (!a.getBoolean(attr, true)) {
4543                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4544                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4545                    }
4546                    break;
4547                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4548                    if (!a.getBoolean(attr, true)) {
4549                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4550                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4551                    }
4552                    break;
4553                case R.styleable.View_scrollbars:
4554                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4555                    if (scrollbars != SCROLLBARS_NONE) {
4556                        viewFlagValues |= scrollbars;
4557                        viewFlagMasks |= SCROLLBARS_MASK;
4558                        initializeScrollbars = true;
4559                    }
4560                    break;
4561                //noinspection deprecation
4562                case R.styleable.View_fadingEdge:
4563                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4564                        // Ignore the attribute starting with ICS
4565                        break;
4566                    }
4567                    // With builds < ICS, fall through and apply fading edges
4568                case R.styleable.View_requiresFadingEdge:
4569                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4570                    if (fadingEdge != FADING_EDGE_NONE) {
4571                        viewFlagValues |= fadingEdge;
4572                        viewFlagMasks |= FADING_EDGE_MASK;
4573                        initializeFadingEdgeInternal(a);
4574                    }
4575                    break;
4576                case R.styleable.View_scrollbarStyle:
4577                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4578                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4579                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4580                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4581                    }
4582                    break;
4583                case R.styleable.View_isScrollContainer:
4584                    setScrollContainer = true;
4585                    if (a.getBoolean(attr, false)) {
4586                        setScrollContainer(true);
4587                    }
4588                    break;
4589                case com.android.internal.R.styleable.View_keepScreenOn:
4590                    if (a.getBoolean(attr, false)) {
4591                        viewFlagValues |= KEEP_SCREEN_ON;
4592                        viewFlagMasks |= KEEP_SCREEN_ON;
4593                    }
4594                    break;
4595                case R.styleable.View_filterTouchesWhenObscured:
4596                    if (a.getBoolean(attr, false)) {
4597                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4598                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4599                    }
4600                    break;
4601                case R.styleable.View_nextFocusLeft:
4602                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4603                    break;
4604                case R.styleable.View_nextFocusRight:
4605                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4606                    break;
4607                case R.styleable.View_nextFocusUp:
4608                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4609                    break;
4610                case R.styleable.View_nextFocusDown:
4611                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4612                    break;
4613                case R.styleable.View_nextFocusForward:
4614                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4615                    break;
4616                case R.styleable.View_nextClusterForward:
4617                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4618                    break;
4619                case R.styleable.View_minWidth:
4620                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4621                    break;
4622                case R.styleable.View_minHeight:
4623                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4624                    break;
4625                case R.styleable.View_onClick:
4626                    if (context.isRestricted()) {
4627                        throw new IllegalStateException("The android:onClick attribute cannot "
4628                                + "be used within a restricted context");
4629                    }
4630
4631                    final String handlerName = a.getString(attr);
4632                    if (handlerName != null) {
4633                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4634                    }
4635                    break;
4636                case R.styleable.View_overScrollMode:
4637                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4638                    break;
4639                case R.styleable.View_verticalScrollbarPosition:
4640                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4641                    break;
4642                case R.styleable.View_layerType:
4643                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4644                    break;
4645                case R.styleable.View_textDirection:
4646                    // Clear any text direction flag already set
4647                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4648                    // Set the text direction flags depending on the value of the attribute
4649                    final int textDirection = a.getInt(attr, -1);
4650                    if (textDirection != -1) {
4651                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4652                    }
4653                    break;
4654                case R.styleable.View_textAlignment:
4655                    // Clear any text alignment flag already set
4656                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4657                    // Set the text alignment flag depending on the value of the attribute
4658                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4659                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4660                    break;
4661                case R.styleable.View_importantForAccessibility:
4662                    setImportantForAccessibility(a.getInt(attr,
4663                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4664                    break;
4665                case R.styleable.View_accessibilityLiveRegion:
4666                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4667                    break;
4668                case R.styleable.View_transitionName:
4669                    setTransitionName(a.getString(attr));
4670                    break;
4671                case R.styleable.View_nestedScrollingEnabled:
4672                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4673                    break;
4674                case R.styleable.View_stateListAnimator:
4675                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4676                            a.getResourceId(attr, 0)));
4677                    break;
4678                case R.styleable.View_backgroundTint:
4679                    // This will get applied later during setBackground().
4680                    if (mBackgroundTint == null) {
4681                        mBackgroundTint = new TintInfo();
4682                    }
4683                    mBackgroundTint.mTintList = a.getColorStateList(
4684                            R.styleable.View_backgroundTint);
4685                    mBackgroundTint.mHasTintList = true;
4686                    break;
4687                case R.styleable.View_backgroundTintMode:
4688                    // This will get applied later during setBackground().
4689                    if (mBackgroundTint == null) {
4690                        mBackgroundTint = new TintInfo();
4691                    }
4692                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4693                            R.styleable.View_backgroundTintMode, -1), null);
4694                    mBackgroundTint.mHasTintMode = true;
4695                    break;
4696                case R.styleable.View_outlineProvider:
4697                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4698                            PROVIDER_BACKGROUND));
4699                    break;
4700                case R.styleable.View_foreground:
4701                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4702                        setForeground(a.getDrawable(attr));
4703                    }
4704                    break;
4705                case R.styleable.View_foregroundGravity:
4706                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4707                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4708                    }
4709                    break;
4710                case R.styleable.View_foregroundTintMode:
4711                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4712                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4713                    }
4714                    break;
4715                case R.styleable.View_foregroundTint:
4716                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4717                        setForegroundTintList(a.getColorStateList(attr));
4718                    }
4719                    break;
4720                case R.styleable.View_foregroundInsidePadding:
4721                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4722                        if (mForegroundInfo == null) {
4723                            mForegroundInfo = new ForegroundInfo();
4724                        }
4725                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4726                                mForegroundInfo.mInsidePadding);
4727                    }
4728                    break;
4729                case R.styleable.View_scrollIndicators:
4730                    final int scrollIndicators =
4731                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4732                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4733                    if (scrollIndicators != 0) {
4734                        mPrivateFlags3 |= scrollIndicators;
4735                        initializeScrollIndicators = true;
4736                    }
4737                    break;
4738                case R.styleable.View_pointerIcon:
4739                    final int resourceId = a.getResourceId(attr, 0);
4740                    if (resourceId != 0) {
4741                        setPointerIcon(PointerIcon.load(
4742                                context.getResources(), resourceId));
4743                    } else {
4744                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4745                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4746                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
4747                        }
4748                    }
4749                    break;
4750                case R.styleable.View_forceHasOverlappingRendering:
4751                    if (a.peekValue(attr) != null) {
4752                        forceHasOverlappingRendering(a.getBoolean(attr, true));
4753                    }
4754                    break;
4755                case R.styleable.View_tooltipText:
4756                    setTooltipText(a.getText(attr));
4757                    break;
4758                case R.styleable.View_keyboardNavigationCluster:
4759                    if (a.peekValue(attr) != null) {
4760                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
4761                    }
4762                    break;
4763                case R.styleable.View_focusedByDefault:
4764                    if (a.peekValue(attr) != null) {
4765                        setFocusedByDefault(a.getBoolean(attr, true));
4766                    }
4767                    break;
4768            }
4769        }
4770
4771        setOverScrollMode(overScrollMode);
4772
4773        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4774        // the resolved layout direction). Those cached values will be used later during padding
4775        // resolution.
4776        mUserPaddingStart = startPadding;
4777        mUserPaddingEnd = endPadding;
4778
4779        if (background != null) {
4780            setBackground(background);
4781        }
4782
4783        // setBackground above will record that padding is currently provided by the background.
4784        // If we have padding specified via xml, record that here instead and use it.
4785        mLeftPaddingDefined = leftPaddingDefined;
4786        mRightPaddingDefined = rightPaddingDefined;
4787
4788        if (padding >= 0) {
4789            leftPadding = padding;
4790            topPadding = padding;
4791            rightPadding = padding;
4792            bottomPadding = padding;
4793            mUserPaddingLeftInitial = padding;
4794            mUserPaddingRightInitial = padding;
4795        } else {
4796            if (paddingHorizontal >= 0) {
4797                leftPadding = paddingHorizontal;
4798                rightPadding = paddingHorizontal;
4799                mUserPaddingLeftInitial = paddingHorizontal;
4800                mUserPaddingRightInitial = paddingHorizontal;
4801            }
4802            if (paddingVertical >= 0) {
4803                topPadding = paddingVertical;
4804                bottomPadding = paddingVertical;
4805            }
4806        }
4807
4808        if (isRtlCompatibilityMode()) {
4809            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4810            // left / right padding are used if defined (meaning here nothing to do). If they are not
4811            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4812            // start / end and resolve them as left / right (layout direction is not taken into account).
4813            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4814            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4815            // defined.
4816            if (!mLeftPaddingDefined && startPaddingDefined) {
4817                leftPadding = startPadding;
4818            }
4819            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4820            if (!mRightPaddingDefined && endPaddingDefined) {
4821                rightPadding = endPadding;
4822            }
4823            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4824        } else {
4825            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4826            // values defined. Otherwise, left /right values are used.
4827            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4828            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4829            // defined.
4830            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4831
4832            if (mLeftPaddingDefined && !hasRelativePadding) {
4833                mUserPaddingLeftInitial = leftPadding;
4834            }
4835            if (mRightPaddingDefined && !hasRelativePadding) {
4836                mUserPaddingRightInitial = rightPadding;
4837            }
4838        }
4839
4840        internalSetPadding(
4841                mUserPaddingLeftInitial,
4842                topPadding >= 0 ? topPadding : mPaddingTop,
4843                mUserPaddingRightInitial,
4844                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4845
4846        if (viewFlagMasks != 0) {
4847            setFlags(viewFlagValues, viewFlagMasks);
4848        }
4849
4850        if (initializeScrollbars) {
4851            initializeScrollbarsInternal(a);
4852        }
4853
4854        if (initializeScrollIndicators) {
4855            initializeScrollIndicatorsInternal();
4856        }
4857
4858        a.recycle();
4859
4860        // Needs to be called after mViewFlags is set
4861        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4862            recomputePadding();
4863        }
4864
4865        if (x != 0 || y != 0) {
4866            scrollTo(x, y);
4867        }
4868
4869        if (transformSet) {
4870            setTranslationX(tx);
4871            setTranslationY(ty);
4872            setTranslationZ(tz);
4873            setElevation(elevation);
4874            setRotation(rotation);
4875            setRotationX(rotationX);
4876            setRotationY(rotationY);
4877            setScaleX(sx);
4878            setScaleY(sy);
4879        }
4880
4881        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4882            setScrollContainer(true);
4883        }
4884
4885        computeOpaqueFlags();
4886    }
4887
4888    /**
4889     * An implementation of OnClickListener that attempts to lazily load a
4890     * named click handling method from a parent or ancestor context.
4891     */
4892    private static class DeclaredOnClickListener implements OnClickListener {
4893        private final View mHostView;
4894        private final String mMethodName;
4895
4896        private Method mResolvedMethod;
4897        private Context mResolvedContext;
4898
4899        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4900            mHostView = hostView;
4901            mMethodName = methodName;
4902        }
4903
4904        @Override
4905        public void onClick(@NonNull View v) {
4906            if (mResolvedMethod == null) {
4907                resolveMethod(mHostView.getContext(), mMethodName);
4908            }
4909
4910            try {
4911                mResolvedMethod.invoke(mResolvedContext, v);
4912            } catch (IllegalAccessException e) {
4913                throw new IllegalStateException(
4914                        "Could not execute non-public method for android:onClick", e);
4915            } catch (InvocationTargetException e) {
4916                throw new IllegalStateException(
4917                        "Could not execute method for android:onClick", e);
4918            }
4919        }
4920
4921        @NonNull
4922        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4923            while (context != null) {
4924                try {
4925                    if (!context.isRestricted()) {
4926                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4927                        if (method != null) {
4928                            mResolvedMethod = method;
4929                            mResolvedContext = context;
4930                            return;
4931                        }
4932                    }
4933                } catch (NoSuchMethodException e) {
4934                    // Failed to find method, keep searching up the hierarchy.
4935                }
4936
4937                if (context instanceof ContextWrapper) {
4938                    context = ((ContextWrapper) context).getBaseContext();
4939                } else {
4940                    // Can't search up the hierarchy, null out and fail.
4941                    context = null;
4942                }
4943            }
4944
4945            final int id = mHostView.getId();
4946            final String idText = id == NO_ID ? "" : " with id '"
4947                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4948            throw new IllegalStateException("Could not find method " + mMethodName
4949                    + "(View) in a parent or ancestor Context for android:onClick "
4950                    + "attribute defined on view " + mHostView.getClass() + idText);
4951        }
4952    }
4953
4954    /**
4955     * Non-public constructor for use in testing
4956     */
4957    View() {
4958        mResources = null;
4959        mRenderNode = RenderNode.create(getClass().getName(), this);
4960    }
4961
4962    final boolean debugDraw() {
4963        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
4964    }
4965
4966    private static SparseArray<String> getAttributeMap() {
4967        if (mAttributeMap == null) {
4968            mAttributeMap = new SparseArray<>();
4969        }
4970        return mAttributeMap;
4971    }
4972
4973    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4974        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4975        final int indexCount = t.getIndexCount();
4976        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4977
4978        int i = 0;
4979
4980        // Store raw XML attributes.
4981        for (int j = 0; j < attrsCount; ++j) {
4982            attributes[i] = attrs.getAttributeName(j);
4983            attributes[i + 1] = attrs.getAttributeValue(j);
4984            i += 2;
4985        }
4986
4987        // Store resolved styleable attributes.
4988        final Resources res = t.getResources();
4989        final SparseArray<String> attributeMap = getAttributeMap();
4990        for (int j = 0; j < indexCount; ++j) {
4991            final int index = t.getIndex(j);
4992            if (!t.hasValueOrEmpty(index)) {
4993                // Value is undefined. Skip it.
4994                continue;
4995            }
4996
4997            final int resourceId = t.getResourceId(index, 0);
4998            if (resourceId == 0) {
4999                // Value is not a reference. Skip it.
5000                continue;
5001            }
5002
5003            String resourceName = attributeMap.get(resourceId);
5004            if (resourceName == null) {
5005                try {
5006                    resourceName = res.getResourceName(resourceId);
5007                } catch (Resources.NotFoundException e) {
5008                    resourceName = "0x" + Integer.toHexString(resourceId);
5009                }
5010                attributeMap.put(resourceId, resourceName);
5011            }
5012
5013            attributes[i] = resourceName;
5014            attributes[i + 1] = t.getString(index);
5015            i += 2;
5016        }
5017
5018        // Trim to fit contents.
5019        final String[] trimmed = new String[i];
5020        System.arraycopy(attributes, 0, trimmed, 0, i);
5021        mAttributes = trimmed;
5022    }
5023
5024    public String toString() {
5025        StringBuilder out = new StringBuilder(128);
5026        out.append(getClass().getName());
5027        out.append('{');
5028        out.append(Integer.toHexString(System.identityHashCode(this)));
5029        out.append(' ');
5030        switch (mViewFlags&VISIBILITY_MASK) {
5031            case VISIBLE: out.append('V'); break;
5032            case INVISIBLE: out.append('I'); break;
5033            case GONE: out.append('G'); break;
5034            default: out.append('.'); break;
5035        }
5036        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5037        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5038        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5039        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5040        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5041        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5042        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5043        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5044        out.append(' ');
5045        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5046        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5047        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5048        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5049            out.append('p');
5050        } else {
5051            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5052        }
5053        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5054        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5055        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5056        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5057        out.append(' ');
5058        out.append(mLeft);
5059        out.append(',');
5060        out.append(mTop);
5061        out.append('-');
5062        out.append(mRight);
5063        out.append(',');
5064        out.append(mBottom);
5065        final int id = getId();
5066        if (id != NO_ID) {
5067            out.append(" #");
5068            out.append(Integer.toHexString(id));
5069            final Resources r = mResources;
5070            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5071                try {
5072                    String pkgname;
5073                    switch (id&0xff000000) {
5074                        case 0x7f000000:
5075                            pkgname="app";
5076                            break;
5077                        case 0x01000000:
5078                            pkgname="android";
5079                            break;
5080                        default:
5081                            pkgname = r.getResourcePackageName(id);
5082                            break;
5083                    }
5084                    String typename = r.getResourceTypeName(id);
5085                    String entryname = r.getResourceEntryName(id);
5086                    out.append(" ");
5087                    out.append(pkgname);
5088                    out.append(":");
5089                    out.append(typename);
5090                    out.append("/");
5091                    out.append(entryname);
5092                } catch (Resources.NotFoundException e) {
5093                }
5094            }
5095        }
5096        out.append("}");
5097        return out.toString();
5098    }
5099
5100    /**
5101     * <p>
5102     * Initializes the fading edges from a given set of styled attributes. This
5103     * method should be called by subclasses that need fading edges and when an
5104     * instance of these subclasses is created programmatically rather than
5105     * being inflated from XML. This method is automatically called when the XML
5106     * is inflated.
5107     * </p>
5108     *
5109     * @param a the styled attributes set to initialize the fading edges from
5110     *
5111     * @removed
5112     */
5113    protected void initializeFadingEdge(TypedArray a) {
5114        // This method probably shouldn't have been included in the SDK to begin with.
5115        // It relies on 'a' having been initialized using an attribute filter array that is
5116        // not publicly available to the SDK. The old method has been renamed
5117        // to initializeFadingEdgeInternal and hidden for framework use only;
5118        // this one initializes using defaults to make it safe to call for apps.
5119
5120        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5121
5122        initializeFadingEdgeInternal(arr);
5123
5124        arr.recycle();
5125    }
5126
5127    /**
5128     * <p>
5129     * Initializes the fading edges from a given set of styled attributes. This
5130     * method should be called by subclasses that need fading edges and when an
5131     * instance of these subclasses is created programmatically rather than
5132     * being inflated from XML. This method is automatically called when the XML
5133     * is inflated.
5134     * </p>
5135     *
5136     * @param a the styled attributes set to initialize the fading edges from
5137     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5138     */
5139    protected void initializeFadingEdgeInternal(TypedArray a) {
5140        initScrollCache();
5141
5142        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5143                R.styleable.View_fadingEdgeLength,
5144                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5145    }
5146
5147    /**
5148     * Returns the size of the vertical faded edges used to indicate that more
5149     * content in this view is visible.
5150     *
5151     * @return The size in pixels of the vertical faded edge or 0 if vertical
5152     *         faded edges are not enabled for this view.
5153     * @attr ref android.R.styleable#View_fadingEdgeLength
5154     */
5155    public int getVerticalFadingEdgeLength() {
5156        if (isVerticalFadingEdgeEnabled()) {
5157            ScrollabilityCache cache = mScrollCache;
5158            if (cache != null) {
5159                return cache.fadingEdgeLength;
5160            }
5161        }
5162        return 0;
5163    }
5164
5165    /**
5166     * Set the size of the faded edge used to indicate that more content in this
5167     * view is available.  Will not change whether the fading edge is enabled; use
5168     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5169     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5170     * for the vertical or horizontal fading edges.
5171     *
5172     * @param length The size in pixels of the faded edge used to indicate that more
5173     *        content in this view is visible.
5174     */
5175    public void setFadingEdgeLength(int length) {
5176        initScrollCache();
5177        mScrollCache.fadingEdgeLength = length;
5178    }
5179
5180    /**
5181     * Returns the size of the horizontal faded edges used to indicate that more
5182     * content in this view is visible.
5183     *
5184     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5185     *         faded edges are not enabled for this view.
5186     * @attr ref android.R.styleable#View_fadingEdgeLength
5187     */
5188    public int getHorizontalFadingEdgeLength() {
5189        if (isHorizontalFadingEdgeEnabled()) {
5190            ScrollabilityCache cache = mScrollCache;
5191            if (cache != null) {
5192                return cache.fadingEdgeLength;
5193            }
5194        }
5195        return 0;
5196    }
5197
5198    /**
5199     * Returns the width of the vertical scrollbar.
5200     *
5201     * @return The width in pixels of the vertical scrollbar or 0 if there
5202     *         is no vertical scrollbar.
5203     */
5204    public int getVerticalScrollbarWidth() {
5205        ScrollabilityCache cache = mScrollCache;
5206        if (cache != null) {
5207            ScrollBarDrawable scrollBar = cache.scrollBar;
5208            if (scrollBar != null) {
5209                int size = scrollBar.getSize(true);
5210                if (size <= 0) {
5211                    size = cache.scrollBarSize;
5212                }
5213                return size;
5214            }
5215            return 0;
5216        }
5217        return 0;
5218    }
5219
5220    /**
5221     * Returns the height of the horizontal scrollbar.
5222     *
5223     * @return The height in pixels of the horizontal scrollbar or 0 if
5224     *         there is no horizontal scrollbar.
5225     */
5226    protected int getHorizontalScrollbarHeight() {
5227        ScrollabilityCache cache = mScrollCache;
5228        if (cache != null) {
5229            ScrollBarDrawable scrollBar = cache.scrollBar;
5230            if (scrollBar != null) {
5231                int size = scrollBar.getSize(false);
5232                if (size <= 0) {
5233                    size = cache.scrollBarSize;
5234                }
5235                return size;
5236            }
5237            return 0;
5238        }
5239        return 0;
5240    }
5241
5242    /**
5243     * <p>
5244     * Initializes the scrollbars from a given set of styled attributes. This
5245     * method should be called by subclasses that need scrollbars and when an
5246     * instance of these subclasses is created programmatically rather than
5247     * being inflated from XML. This method is automatically called when the XML
5248     * is inflated.
5249     * </p>
5250     *
5251     * @param a the styled attributes set to initialize the scrollbars from
5252     *
5253     * @removed
5254     */
5255    protected void initializeScrollbars(TypedArray a) {
5256        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5257        // using the View filter array which is not available to the SDK. As such, internal
5258        // framework usage now uses initializeScrollbarsInternal and we grab a default
5259        // TypedArray with the right filter instead here.
5260        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5261
5262        initializeScrollbarsInternal(arr);
5263
5264        // We ignored the method parameter. Recycle the one we actually did use.
5265        arr.recycle();
5266    }
5267
5268    /**
5269     * <p>
5270     * Initializes the scrollbars from a given set of styled attributes. This
5271     * method should be called by subclasses that need scrollbars and when an
5272     * instance of these subclasses is created programmatically rather than
5273     * being inflated from XML. This method is automatically called when the XML
5274     * is inflated.
5275     * </p>
5276     *
5277     * @param a the styled attributes set to initialize the scrollbars from
5278     * @hide
5279     */
5280    protected void initializeScrollbarsInternal(TypedArray a) {
5281        initScrollCache();
5282
5283        final ScrollabilityCache scrollabilityCache = mScrollCache;
5284
5285        if (scrollabilityCache.scrollBar == null) {
5286            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5287            scrollabilityCache.scrollBar.setState(getDrawableState());
5288            scrollabilityCache.scrollBar.setCallback(this);
5289        }
5290
5291        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5292
5293        if (!fadeScrollbars) {
5294            scrollabilityCache.state = ScrollabilityCache.ON;
5295        }
5296        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5297
5298
5299        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5300                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5301                        .getScrollBarFadeDuration());
5302        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5303                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5304                ViewConfiguration.getScrollDefaultDelay());
5305
5306
5307        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5308                com.android.internal.R.styleable.View_scrollbarSize,
5309                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5310
5311        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5312        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5313
5314        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5315        if (thumb != null) {
5316            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5317        }
5318
5319        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5320                false);
5321        if (alwaysDraw) {
5322            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5323        }
5324
5325        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5326        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5327
5328        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5329        if (thumb != null) {
5330            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5331        }
5332
5333        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5334                false);
5335        if (alwaysDraw) {
5336            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5337        }
5338
5339        // Apply layout direction to the new Drawables if needed
5340        final int layoutDirection = getLayoutDirection();
5341        if (track != null) {
5342            track.setLayoutDirection(layoutDirection);
5343        }
5344        if (thumb != null) {
5345            thumb.setLayoutDirection(layoutDirection);
5346        }
5347
5348        // Re-apply user/background padding so that scrollbar(s) get added
5349        resolvePadding();
5350    }
5351
5352    private void initializeScrollIndicatorsInternal() {
5353        // Some day maybe we'll break this into top/left/start/etc. and let the
5354        // client control it. Until then, you can have any scroll indicator you
5355        // want as long as it's a 1dp foreground-colored rectangle.
5356        if (mScrollIndicatorDrawable == null) {
5357            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5358        }
5359    }
5360
5361    /**
5362     * <p>
5363     * Initalizes the scrollability cache if necessary.
5364     * </p>
5365     */
5366    private void initScrollCache() {
5367        if (mScrollCache == null) {
5368            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5369        }
5370    }
5371
5372    private ScrollabilityCache getScrollCache() {
5373        initScrollCache();
5374        return mScrollCache;
5375    }
5376
5377    /**
5378     * Set the position of the vertical scroll bar. Should be one of
5379     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5380     * {@link #SCROLLBAR_POSITION_RIGHT}.
5381     *
5382     * @param position Where the vertical scroll bar should be positioned.
5383     */
5384    public void setVerticalScrollbarPosition(int position) {
5385        if (mVerticalScrollbarPosition != position) {
5386            mVerticalScrollbarPosition = position;
5387            computeOpaqueFlags();
5388            resolvePadding();
5389        }
5390    }
5391
5392    /**
5393     * @return The position where the vertical scroll bar will show, if applicable.
5394     * @see #setVerticalScrollbarPosition(int)
5395     */
5396    public int getVerticalScrollbarPosition() {
5397        return mVerticalScrollbarPosition;
5398    }
5399
5400    boolean isOnScrollbar(float x, float y) {
5401        if (mScrollCache == null) {
5402            return false;
5403        }
5404        x += getScrollX();
5405        y += getScrollY();
5406        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5407            final Rect bounds = mScrollCache.mScrollBarBounds;
5408            getVerticalScrollBarBounds(bounds);
5409            if (bounds.contains((int)x, (int)y)) {
5410                return true;
5411            }
5412        }
5413        if (isHorizontalScrollBarEnabled()) {
5414            final Rect bounds = mScrollCache.mScrollBarBounds;
5415            getHorizontalScrollBarBounds(bounds);
5416            if (bounds.contains((int)x, (int)y)) {
5417                return true;
5418            }
5419        }
5420        return false;
5421    }
5422
5423    boolean isOnScrollbarThumb(float x, float y) {
5424        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5425    }
5426
5427    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5428        if (mScrollCache == null) {
5429            return false;
5430        }
5431        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5432            x += getScrollX();
5433            y += getScrollY();
5434            final Rect bounds = mScrollCache.mScrollBarBounds;
5435            getVerticalScrollBarBounds(bounds);
5436            final int range = computeVerticalScrollRange();
5437            final int offset = computeVerticalScrollOffset();
5438            final int extent = computeVerticalScrollExtent();
5439            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5440                    extent, range);
5441            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5442                    extent, range, offset);
5443            final int thumbTop = bounds.top + thumbOffset;
5444            if (x >= bounds.left && x <= bounds.right && y >= thumbTop
5445                    && y <= thumbTop + thumbLength) {
5446                return true;
5447            }
5448        }
5449        return false;
5450    }
5451
5452    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5453        if (mScrollCache == null) {
5454            return false;
5455        }
5456        if (isHorizontalScrollBarEnabled()) {
5457            x += getScrollX();
5458            y += getScrollY();
5459            final Rect bounds = mScrollCache.mScrollBarBounds;
5460            getHorizontalScrollBarBounds(bounds);
5461            final int range = computeHorizontalScrollRange();
5462            final int offset = computeHorizontalScrollOffset();
5463            final int extent = computeHorizontalScrollExtent();
5464            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5465                    extent, range);
5466            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5467                    extent, range, offset);
5468            final int thumbLeft = bounds.left + thumbOffset;
5469            if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top
5470                    && y <= bounds.bottom) {
5471                return true;
5472            }
5473        }
5474        return false;
5475    }
5476
5477    boolean isDraggingScrollBar() {
5478        return mScrollCache != null
5479                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5480    }
5481
5482    /**
5483     * Sets the state of all scroll indicators.
5484     * <p>
5485     * See {@link #setScrollIndicators(int, int)} for usage information.
5486     *
5487     * @param indicators a bitmask of indicators that should be enabled, or
5488     *                   {@code 0} to disable all indicators
5489     * @see #setScrollIndicators(int, int)
5490     * @see #getScrollIndicators()
5491     * @attr ref android.R.styleable#View_scrollIndicators
5492     */
5493    public void setScrollIndicators(@ScrollIndicators int indicators) {
5494        setScrollIndicators(indicators,
5495                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5496    }
5497
5498    /**
5499     * Sets the state of the scroll indicators specified by the mask. To change
5500     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5501     * <p>
5502     * When a scroll indicator is enabled, it will be displayed if the view
5503     * can scroll in the direction of the indicator.
5504     * <p>
5505     * Multiple indicator types may be enabled or disabled by passing the
5506     * logical OR of the desired types. If multiple types are specified, they
5507     * will all be set to the same enabled state.
5508     * <p>
5509     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5510     *
5511     * @param indicators the indicator direction, or the logical OR of multiple
5512     *             indicator directions. One or more of:
5513     *             <ul>
5514     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5515     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5516     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5517     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5518     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5519     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5520     *             </ul>
5521     * @see #setScrollIndicators(int)
5522     * @see #getScrollIndicators()
5523     * @attr ref android.R.styleable#View_scrollIndicators
5524     */
5525    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5526        // Shift and sanitize mask.
5527        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5528        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5529
5530        // Shift and mask indicators.
5531        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5532        indicators &= mask;
5533
5534        // Merge with non-masked flags.
5535        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5536
5537        if (mPrivateFlags3 != updatedFlags) {
5538            mPrivateFlags3 = updatedFlags;
5539
5540            if (indicators != 0) {
5541                initializeScrollIndicatorsInternal();
5542            }
5543            invalidate();
5544        }
5545    }
5546
5547    /**
5548     * Returns a bitmask representing the enabled scroll indicators.
5549     * <p>
5550     * For example, if the top and left scroll indicators are enabled and all
5551     * other indicators are disabled, the return value will be
5552     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5553     * <p>
5554     * To check whether the bottom scroll indicator is enabled, use the value
5555     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5556     *
5557     * @return a bitmask representing the enabled scroll indicators
5558     */
5559    @ScrollIndicators
5560    public int getScrollIndicators() {
5561        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5562                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5563    }
5564
5565    ListenerInfo getListenerInfo() {
5566        if (mListenerInfo != null) {
5567            return mListenerInfo;
5568        }
5569        mListenerInfo = new ListenerInfo();
5570        return mListenerInfo;
5571    }
5572
5573    /**
5574     * Register a callback to be invoked when the scroll X or Y positions of
5575     * this view change.
5576     * <p>
5577     * <b>Note:</b> Some views handle scrolling independently from View and may
5578     * have their own separate listeners for scroll-type events. For example,
5579     * {@link android.widget.ListView ListView} allows clients to register an
5580     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5581     * to listen for changes in list scroll position.
5582     *
5583     * @param l The listener to notify when the scroll X or Y position changes.
5584     * @see android.view.View#getScrollX()
5585     * @see android.view.View#getScrollY()
5586     */
5587    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5588        getListenerInfo().mOnScrollChangeListener = l;
5589    }
5590
5591    /**
5592     * Register a callback to be invoked when focus of this view changed.
5593     *
5594     * @param l The callback that will run.
5595     */
5596    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5597        getListenerInfo().mOnFocusChangeListener = l;
5598    }
5599
5600    /**
5601     * Add a listener that will be called when the bounds of the view change due to
5602     * layout processing.
5603     *
5604     * @param listener The listener that will be called when layout bounds change.
5605     */
5606    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5607        ListenerInfo li = getListenerInfo();
5608        if (li.mOnLayoutChangeListeners == null) {
5609            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5610        }
5611        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5612            li.mOnLayoutChangeListeners.add(listener);
5613        }
5614    }
5615
5616    /**
5617     * Remove a listener for layout changes.
5618     *
5619     * @param listener The listener for layout bounds change.
5620     */
5621    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5622        ListenerInfo li = mListenerInfo;
5623        if (li == null || li.mOnLayoutChangeListeners == null) {
5624            return;
5625        }
5626        li.mOnLayoutChangeListeners.remove(listener);
5627    }
5628
5629    /**
5630     * Add a listener for attach state changes.
5631     *
5632     * This listener will be called whenever this view is attached or detached
5633     * from a window. Remove the listener using
5634     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5635     *
5636     * @param listener Listener to attach
5637     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5638     */
5639    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5640        ListenerInfo li = getListenerInfo();
5641        if (li.mOnAttachStateChangeListeners == null) {
5642            li.mOnAttachStateChangeListeners
5643                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5644        }
5645        li.mOnAttachStateChangeListeners.add(listener);
5646    }
5647
5648    /**
5649     * Remove a listener for attach state changes. The listener will receive no further
5650     * notification of window attach/detach events.
5651     *
5652     * @param listener Listener to remove
5653     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5654     */
5655    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5656        ListenerInfo li = mListenerInfo;
5657        if (li == null || li.mOnAttachStateChangeListeners == null) {
5658            return;
5659        }
5660        li.mOnAttachStateChangeListeners.remove(listener);
5661    }
5662
5663    /**
5664     * Returns the focus-change callback registered for this view.
5665     *
5666     * @return The callback, or null if one is not registered.
5667     */
5668    public OnFocusChangeListener getOnFocusChangeListener() {
5669        ListenerInfo li = mListenerInfo;
5670        return li != null ? li.mOnFocusChangeListener : null;
5671    }
5672
5673    /**
5674     * Register a callback to be invoked when this view is clicked. If this view is not
5675     * clickable, it becomes clickable.
5676     *
5677     * @param l The callback that will run
5678     *
5679     * @see #setClickable(boolean)
5680     */
5681    public void setOnClickListener(@Nullable OnClickListener l) {
5682        if (!isClickable()) {
5683            setClickable(true);
5684        }
5685        getListenerInfo().mOnClickListener = l;
5686    }
5687
5688    /**
5689     * Return whether this view has an attached OnClickListener.  Returns
5690     * true if there is a listener, false if there is none.
5691     */
5692    public boolean hasOnClickListeners() {
5693        ListenerInfo li = mListenerInfo;
5694        return (li != null && li.mOnClickListener != null);
5695    }
5696
5697    /**
5698     * Register a callback to be invoked when this view is clicked and held. If this view is not
5699     * long clickable, it becomes long clickable.
5700     *
5701     * @param l The callback that will run
5702     *
5703     * @see #setLongClickable(boolean)
5704     */
5705    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5706        if (!isLongClickable()) {
5707            setLongClickable(true);
5708        }
5709        getListenerInfo().mOnLongClickListener = l;
5710    }
5711
5712    /**
5713     * Register a callback to be invoked when this view is context clicked. If the view is not
5714     * context clickable, it becomes context clickable.
5715     *
5716     * @param l The callback that will run
5717     * @see #setContextClickable(boolean)
5718     */
5719    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5720        if (!isContextClickable()) {
5721            setContextClickable(true);
5722        }
5723        getListenerInfo().mOnContextClickListener = l;
5724    }
5725
5726    /**
5727     * Register a callback to be invoked when the context menu for this view is
5728     * being built. If this view is not long clickable, it becomes long clickable.
5729     *
5730     * @param l The callback that will run
5731     *
5732     */
5733    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5734        if (!isLongClickable()) {
5735            setLongClickable(true);
5736        }
5737        getListenerInfo().mOnCreateContextMenuListener = l;
5738    }
5739
5740    /**
5741     * Set an observer to collect stats for each frame rendered for this view.
5742     *
5743     * @hide
5744     */
5745    public void addFrameMetricsListener(Window window,
5746            Window.OnFrameMetricsAvailableListener listener,
5747            Handler handler) {
5748        if (mAttachInfo != null) {
5749            if (mAttachInfo.mThreadedRenderer != null) {
5750                if (mFrameMetricsObservers == null) {
5751                    mFrameMetricsObservers = new ArrayList<>();
5752                }
5753
5754                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5755                        handler.getLooper(), listener);
5756                mFrameMetricsObservers.add(fmo);
5757                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
5758            } else {
5759                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5760            }
5761        } else {
5762            if (mFrameMetricsObservers == null) {
5763                mFrameMetricsObservers = new ArrayList<>();
5764            }
5765
5766            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5767                    handler.getLooper(), listener);
5768            mFrameMetricsObservers.add(fmo);
5769        }
5770    }
5771
5772    /**
5773     * Remove observer configured to collect frame stats for this view.
5774     *
5775     * @hide
5776     */
5777    public void removeFrameMetricsListener(
5778            Window.OnFrameMetricsAvailableListener listener) {
5779        ThreadedRenderer renderer = getThreadedRenderer();
5780        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
5781        if (fmo == null) {
5782            throw new IllegalArgumentException(
5783                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
5784        }
5785
5786        if (mFrameMetricsObservers != null) {
5787            mFrameMetricsObservers.remove(fmo);
5788            if (renderer != null) {
5789                renderer.removeFrameMetricsObserver(fmo);
5790            }
5791        }
5792    }
5793
5794    private void registerPendingFrameMetricsObservers() {
5795        if (mFrameMetricsObservers != null) {
5796            ThreadedRenderer renderer = getThreadedRenderer();
5797            if (renderer != null) {
5798                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
5799                    renderer.addFrameMetricsObserver(fmo);
5800                }
5801            } else {
5802                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5803            }
5804        }
5805    }
5806
5807    private FrameMetricsObserver findFrameMetricsObserver(
5808            Window.OnFrameMetricsAvailableListener listener) {
5809        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
5810            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
5811            if (observer.mListener == listener) {
5812                return observer;
5813            }
5814        }
5815
5816        return null;
5817    }
5818
5819    /**
5820     * Call this view's OnClickListener, if it is defined.  Performs all normal
5821     * actions associated with clicking: reporting accessibility event, playing
5822     * a sound, etc.
5823     *
5824     * @return True there was an assigned OnClickListener that was called, false
5825     *         otherwise is returned.
5826     */
5827    public boolean performClick() {
5828        final boolean result;
5829        final ListenerInfo li = mListenerInfo;
5830        if (li != null && li.mOnClickListener != null) {
5831            playSoundEffect(SoundEffectConstants.CLICK);
5832            li.mOnClickListener.onClick(this);
5833            result = true;
5834        } else {
5835            result = false;
5836        }
5837
5838        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5839        return result;
5840    }
5841
5842    /**
5843     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5844     * this only calls the listener, and does not do any associated clicking
5845     * actions like reporting an accessibility event.
5846     *
5847     * @return True there was an assigned OnClickListener that was called, false
5848     *         otherwise is returned.
5849     */
5850    public boolean callOnClick() {
5851        ListenerInfo li = mListenerInfo;
5852        if (li != null && li.mOnClickListener != null) {
5853            li.mOnClickListener.onClick(this);
5854            return true;
5855        }
5856        return false;
5857    }
5858
5859    /**
5860     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5861     * context menu if the OnLongClickListener did not consume the event.
5862     *
5863     * @return {@code true} if one of the above receivers consumed the event,
5864     *         {@code false} otherwise
5865     */
5866    public boolean performLongClick() {
5867        return performLongClickInternal(mLongClickX, mLongClickY);
5868    }
5869
5870    /**
5871     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5872     * context menu if the OnLongClickListener did not consume the event,
5873     * anchoring it to an (x,y) coordinate.
5874     *
5875     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5876     *          to disable anchoring
5877     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5878     *          to disable anchoring
5879     * @return {@code true} if one of the above receivers consumed the event,
5880     *         {@code false} otherwise
5881     */
5882    public boolean performLongClick(float x, float y) {
5883        mLongClickX = x;
5884        mLongClickY = y;
5885        final boolean handled = performLongClick();
5886        mLongClickX = Float.NaN;
5887        mLongClickY = Float.NaN;
5888        return handled;
5889    }
5890
5891    /**
5892     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5893     * context menu if the OnLongClickListener did not consume the event,
5894     * optionally anchoring it to an (x,y) coordinate.
5895     *
5896     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5897     *          to disable anchoring
5898     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5899     *          to disable anchoring
5900     * @return {@code true} if one of the above receivers consumed the event,
5901     *         {@code false} otherwise
5902     */
5903    private boolean performLongClickInternal(float x, float y) {
5904        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5905
5906        boolean handled = false;
5907        final ListenerInfo li = mListenerInfo;
5908        if (li != null && li.mOnLongClickListener != null) {
5909            handled = li.mOnLongClickListener.onLongClick(View.this);
5910        }
5911        if (!handled) {
5912            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5913            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5914        }
5915        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
5916            if (!handled) {
5917                handled = showLongClickTooltip((int) x, (int) y);
5918            }
5919        }
5920        if (handled) {
5921            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5922        }
5923        return handled;
5924    }
5925
5926    /**
5927     * Call this view's OnContextClickListener, if it is defined.
5928     *
5929     * @param x the x coordinate of the context click
5930     * @param y the y coordinate of the context click
5931     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5932     *         otherwise.
5933     */
5934    public boolean performContextClick(float x, float y) {
5935        return performContextClick();
5936    }
5937
5938    /**
5939     * Call this view's OnContextClickListener, if it is defined.
5940     *
5941     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5942     *         otherwise.
5943     */
5944    public boolean performContextClick() {
5945        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5946
5947        boolean handled = false;
5948        ListenerInfo li = mListenerInfo;
5949        if (li != null && li.mOnContextClickListener != null) {
5950            handled = li.mOnContextClickListener.onContextClick(View.this);
5951        }
5952        if (handled) {
5953            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5954        }
5955        return handled;
5956    }
5957
5958    /**
5959     * Performs button-related actions during a touch down event.
5960     *
5961     * @param event The event.
5962     * @return True if the down was consumed.
5963     *
5964     * @hide
5965     */
5966    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5967        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5968            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5969            showContextMenu(event.getX(), event.getY());
5970            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5971            return true;
5972        }
5973        return false;
5974    }
5975
5976    /**
5977     * Shows the context menu for this view.
5978     *
5979     * @return {@code true} if the context menu was shown, {@code false}
5980     *         otherwise
5981     * @see #showContextMenu(float, float)
5982     */
5983    public boolean showContextMenu() {
5984        return getParent().showContextMenuForChild(this);
5985    }
5986
5987    /**
5988     * Shows the context menu for this view anchored to the specified
5989     * view-relative coordinate.
5990     *
5991     * @param x the X coordinate in pixels relative to the view to which the
5992     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5993     * @param y the Y coordinate in pixels relative to the view to which the
5994     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5995     * @return {@code true} if the context menu was shown, {@code false}
5996     *         otherwise
5997     */
5998    public boolean showContextMenu(float x, float y) {
5999        return getParent().showContextMenuForChild(this, x, y);
6000    }
6001
6002    /**
6003     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6004     *
6005     * @param callback Callback that will control the lifecycle of the action mode
6006     * @return The new action mode if it is started, null otherwise
6007     *
6008     * @see ActionMode
6009     * @see #startActionMode(android.view.ActionMode.Callback, int)
6010     */
6011    public ActionMode startActionMode(ActionMode.Callback callback) {
6012        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6013    }
6014
6015    /**
6016     * Start an action mode with the given type.
6017     *
6018     * @param callback Callback that will control the lifecycle of the action mode
6019     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6020     * @return The new action mode if it is started, null otherwise
6021     *
6022     * @see ActionMode
6023     */
6024    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6025        ViewParent parent = getParent();
6026        if (parent == null) return null;
6027        try {
6028            return parent.startActionModeForChild(this, callback, type);
6029        } catch (AbstractMethodError ame) {
6030            // Older implementations of custom views might not implement this.
6031            return parent.startActionModeForChild(this, callback);
6032        }
6033    }
6034
6035    /**
6036     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6037     * Context, creating a unique View identifier to retrieve the result.
6038     *
6039     * @param intent The Intent to be started.
6040     * @param requestCode The request code to use.
6041     * @hide
6042     */
6043    public void startActivityForResult(Intent intent, int requestCode) {
6044        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6045        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6046    }
6047
6048    /**
6049     * If this View corresponds to the calling who, dispatches the activity result.
6050     * @param who The identifier for the targeted View to receive the result.
6051     * @param requestCode The integer request code originally supplied to
6052     *                    startActivityForResult(), allowing you to identify who this
6053     *                    result came from.
6054     * @param resultCode The integer result code returned by the child activity
6055     *                   through its setResult().
6056     * @param data An Intent, which can return result data to the caller
6057     *               (various data can be attached to Intent "extras").
6058     * @return {@code true} if the activity result was dispatched.
6059     * @hide
6060     */
6061    public boolean dispatchActivityResult(
6062            String who, int requestCode, int resultCode, Intent data) {
6063        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6064            onActivityResult(requestCode, resultCode, data);
6065            mStartActivityRequestWho = null;
6066            return true;
6067        }
6068        return false;
6069    }
6070
6071    /**
6072     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6073     *
6074     * @param requestCode The integer request code originally supplied to
6075     *                    startActivityForResult(), allowing you to identify who this
6076     *                    result came from.
6077     * @param resultCode The integer result code returned by the child activity
6078     *                   through its setResult().
6079     * @param data An Intent, which can return result data to the caller
6080     *               (various data can be attached to Intent "extras").
6081     * @hide
6082     */
6083    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6084        // Do nothing.
6085    }
6086
6087    /**
6088     * Register a callback to be invoked when a hardware key is pressed in this view.
6089     * Key presses in software input methods will generally not trigger the methods of
6090     * this listener.
6091     * @param l the key listener to attach to this view
6092     */
6093    public void setOnKeyListener(OnKeyListener l) {
6094        getListenerInfo().mOnKeyListener = l;
6095    }
6096
6097    /**
6098     * Register a callback to be invoked when a touch event is sent to this view.
6099     * @param l the touch listener to attach to this view
6100     */
6101    public void setOnTouchListener(OnTouchListener l) {
6102        getListenerInfo().mOnTouchListener = l;
6103    }
6104
6105    /**
6106     * Register a callback to be invoked when a generic motion event is sent to this view.
6107     * @param l the generic motion listener to attach to this view
6108     */
6109    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6110        getListenerInfo().mOnGenericMotionListener = l;
6111    }
6112
6113    /**
6114     * Register a callback to be invoked when a hover event is sent to this view.
6115     * @param l the hover listener to attach to this view
6116     */
6117    public void setOnHoverListener(OnHoverListener l) {
6118        getListenerInfo().mOnHoverListener = l;
6119    }
6120
6121    /**
6122     * Register a drag event listener callback object for this View. The parameter is
6123     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6124     * View, the system calls the
6125     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6126     * @param l An implementation of {@link android.view.View.OnDragListener}.
6127     */
6128    public void setOnDragListener(OnDragListener l) {
6129        getListenerInfo().mOnDragListener = l;
6130    }
6131
6132    /**
6133     * Give this view focus. This will cause
6134     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6135     *
6136     * Note: this does not check whether this {@link View} should get focus, it just
6137     * gives it focus no matter what.  It should only be called internally by framework
6138     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6139     *
6140     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6141     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6142     *        focus moved when requestFocus() is called. It may not always
6143     *        apply, in which case use the default View.FOCUS_DOWN.
6144     * @param previouslyFocusedRect The rectangle of the view that had focus
6145     *        prior in this View's coordinate system.
6146     */
6147    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6148        if (DBG) {
6149            System.out.println(this + " requestFocus()");
6150        }
6151
6152        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6153            mPrivateFlags |= PFLAG_FOCUSED;
6154
6155            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6156
6157            if (mParent != null) {
6158                mParent.requestChildFocus(this, this);
6159                if (mParent instanceof ViewGroup) {
6160                    ((ViewGroup) mParent).setDefaultFocus(this);
6161                }
6162            }
6163
6164            if (mAttachInfo != null) {
6165                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6166            }
6167
6168            onFocusChanged(true, direction, previouslyFocusedRect);
6169            refreshDrawableState();
6170        }
6171    }
6172
6173    /**
6174     * Sets this view's preference for reveal behavior when it gains focus.
6175     *
6176     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6177     * this view would prefer to be brought fully into view when it gains focus.
6178     * For example, a text field that a user is meant to type into. Other views such
6179     * as scrolling containers may prefer to opt-out of this behavior.</p>
6180     *
6181     * <p>The default value for views is true, though subclasses may change this
6182     * based on their preferred behavior.</p>
6183     *
6184     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6185     *
6186     * @see #getRevealOnFocusHint()
6187     */
6188    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6189        if (revealOnFocus) {
6190            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6191        } else {
6192            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6193        }
6194    }
6195
6196    /**
6197     * Returns this view's preference for reveal behavior when it gains focus.
6198     *
6199     * <p>When this method returns true for a child view requesting focus, ancestor
6200     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6201     * should make a best effort to make the newly focused child fully visible to the user.
6202     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6203     * other properties affecting visibility to the user as part of the focus change.</p>
6204     *
6205     * @return true if this view would prefer to become fully visible when it gains focus,
6206     *         false if it would prefer not to disrupt scroll positioning
6207     *
6208     * @see #setRevealOnFocusHint(boolean)
6209     */
6210    public final boolean getRevealOnFocusHint() {
6211        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6212    }
6213
6214    /**
6215     * Populates <code>outRect</code> with the hotspot bounds. By default,
6216     * the hotspot bounds are identical to the screen bounds.
6217     *
6218     * @param outRect rect to populate with hotspot bounds
6219     * @hide Only for internal use by views and widgets.
6220     */
6221    public void getHotspotBounds(Rect outRect) {
6222        final Drawable background = getBackground();
6223        if (background != null) {
6224            background.getHotspotBounds(outRect);
6225        } else {
6226            getBoundsOnScreen(outRect);
6227        }
6228    }
6229
6230    /**
6231     * Request that a rectangle of this view be visible on the screen,
6232     * scrolling if necessary just enough.
6233     *
6234     * <p>A View should call this if it maintains some notion of which part
6235     * of its content is interesting.  For example, a text editing view
6236     * should call this when its cursor moves.
6237     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6238     * It should not be affected by which part of the View is currently visible or its scroll
6239     * position.
6240     *
6241     * @param rectangle The rectangle in the View's content coordinate space
6242     * @return Whether any parent scrolled.
6243     */
6244    public boolean requestRectangleOnScreen(Rect rectangle) {
6245        return requestRectangleOnScreen(rectangle, false);
6246    }
6247
6248    /**
6249     * Request that a rectangle of this view be visible on the screen,
6250     * scrolling if necessary just enough.
6251     *
6252     * <p>A View should call this if it maintains some notion of which part
6253     * of its content is interesting.  For example, a text editing view
6254     * should call this when its cursor moves.
6255     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6256     * It should not be affected by which part of the View is currently visible or its scroll
6257     * position.
6258     * <p>When <code>immediate</code> is set to true, scrolling will not be
6259     * animated.
6260     *
6261     * @param rectangle The rectangle in the View's content coordinate space
6262     * @param immediate True to forbid animated scrolling, false otherwise
6263     * @return Whether any parent scrolled.
6264     */
6265    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6266        if (mParent == null) {
6267            return false;
6268        }
6269
6270        View child = this;
6271
6272        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6273        position.set(rectangle);
6274
6275        ViewParent parent = mParent;
6276        boolean scrolled = false;
6277        while (parent != null) {
6278            rectangle.set((int) position.left, (int) position.top,
6279                    (int) position.right, (int) position.bottom);
6280
6281            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6282
6283            if (!(parent instanceof View)) {
6284                break;
6285            }
6286
6287            // move it from child's content coordinate space to parent's content coordinate space
6288            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6289
6290            child = (View) parent;
6291            parent = child.getParent();
6292        }
6293
6294        return scrolled;
6295    }
6296
6297    /**
6298     * Called when this view wants to give up focus. If focus is cleared
6299     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6300     * <p>
6301     * <strong>Note:</strong> When a View clears focus the framework is trying
6302     * to give focus to the first focusable View from the top. Hence, if this
6303     * View is the first from the top that can take focus, then all callbacks
6304     * related to clearing focus will be invoked after which the framework will
6305     * give focus to this view.
6306     * </p>
6307     */
6308    public void clearFocus() {
6309        if (DBG) {
6310            System.out.println(this + " clearFocus()");
6311        }
6312
6313        clearFocusInternal(null, true, true);
6314    }
6315
6316    /**
6317     * Clears focus from the view, optionally propagating the change up through
6318     * the parent hierarchy and requesting that the root view place new focus.
6319     *
6320     * @param propagate whether to propagate the change up through the parent
6321     *            hierarchy
6322     * @param refocus when propagate is true, specifies whether to request the
6323     *            root view place new focus
6324     */
6325    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6326        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6327            mPrivateFlags &= ~PFLAG_FOCUSED;
6328
6329            if (propagate && mParent != null) {
6330                mParent.clearChildFocus(this);
6331            }
6332
6333            onFocusChanged(false, 0, null);
6334            refreshDrawableState();
6335
6336            if (propagate && (!refocus || !rootViewRequestFocus())) {
6337                notifyGlobalFocusCleared(this);
6338            }
6339        }
6340    }
6341
6342    void notifyGlobalFocusCleared(View oldFocus) {
6343        if (oldFocus != null && mAttachInfo != null) {
6344            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6345        }
6346    }
6347
6348    boolean rootViewRequestFocus() {
6349        final View root = getRootView();
6350        return root != null && root.requestFocus();
6351    }
6352
6353    /**
6354     * Called internally by the view system when a new view is getting focus.
6355     * This is what clears the old focus.
6356     * <p>
6357     * <b>NOTE:</b> The parent view's focused child must be updated manually
6358     * after calling this method. Otherwise, the view hierarchy may be left in
6359     * an inconstent state.
6360     */
6361    void unFocus(View focused) {
6362        if (DBG) {
6363            System.out.println(this + " unFocus()");
6364        }
6365
6366        clearFocusInternal(focused, false, false);
6367    }
6368
6369    /**
6370     * Returns true if this view has focus itself, or is the ancestor of the
6371     * view that has focus.
6372     *
6373     * @return True if this view has or contains focus, false otherwise.
6374     */
6375    @ViewDebug.ExportedProperty(category = "focus")
6376    public boolean hasFocus() {
6377        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6378    }
6379
6380    /**
6381     * Returns true if this view is focusable or if it contains a reachable View
6382     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
6383     * is a View whose parents do not block descendants focus.
6384     *
6385     * Only {@link #VISIBLE} views are considered focusable.
6386     *
6387     * @return True if the view is focusable or if the view contains a focusable
6388     *         View, false otherwise.
6389     *
6390     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6391     * @see ViewGroup#getTouchscreenBlocksFocus()
6392     */
6393    public boolean hasFocusable() {
6394        if (!isFocusableInTouchMode()) {
6395            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6396                final ViewGroup g = (ViewGroup) p;
6397                if (g.shouldBlockFocusForTouchscreen()) {
6398                    return false;
6399                }
6400            }
6401        }
6402        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
6403    }
6404
6405    /**
6406     * Called by the view system when the focus state of this view changes.
6407     * When the focus change event is caused by directional navigation, direction
6408     * and previouslyFocusedRect provide insight into where the focus is coming from.
6409     * When overriding, be sure to call up through to the super class so that
6410     * the standard focus handling will occur.
6411     *
6412     * @param gainFocus True if the View has focus; false otherwise.
6413     * @param direction The direction focus has moved when requestFocus()
6414     *                  is called to give this view focus. Values are
6415     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6416     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6417     *                  It may not always apply, in which case use the default.
6418     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6419     *        system, of the previously focused view.  If applicable, this will be
6420     *        passed in as finer grained information about where the focus is coming
6421     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6422     */
6423    @CallSuper
6424    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6425            @Nullable Rect previouslyFocusedRect) {
6426        if (gainFocus) {
6427            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6428        } else {
6429            notifyViewAccessibilityStateChangedIfNeeded(
6430                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6431        }
6432
6433        InputMethodManager imm = InputMethodManager.peekInstance();
6434        if (!gainFocus) {
6435            if (isPressed()) {
6436                setPressed(false);
6437            }
6438            if (imm != null && mAttachInfo != null
6439                    && mAttachInfo.mHasWindowFocus) {
6440                imm.focusOut(this);
6441            }
6442            onFocusLost();
6443        } else if (imm != null && mAttachInfo != null
6444                && mAttachInfo.mHasWindowFocus) {
6445            imm.focusIn(this);
6446        }
6447
6448        invalidate(true);
6449        ListenerInfo li = mListenerInfo;
6450        if (li != null && li.mOnFocusChangeListener != null) {
6451            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6452        }
6453
6454        if (mAttachInfo != null) {
6455            mAttachInfo.mKeyDispatchState.reset(this);
6456        }
6457    }
6458
6459    /**
6460     * Sends an accessibility event of the given type. If accessibility is
6461     * not enabled this method has no effect. The default implementation calls
6462     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6463     * to populate information about the event source (this View), then calls
6464     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6465     * populate the text content of the event source including its descendants,
6466     * and last calls
6467     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6468     * on its parent to request sending of the event to interested parties.
6469     * <p>
6470     * If an {@link AccessibilityDelegate} has been specified via calling
6471     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6472     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6473     * responsible for handling this call.
6474     * </p>
6475     *
6476     * @param eventType The type of the event to send, as defined by several types from
6477     * {@link android.view.accessibility.AccessibilityEvent}, such as
6478     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6479     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6480     *
6481     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6482     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6483     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6484     * @see AccessibilityDelegate
6485     */
6486    public void sendAccessibilityEvent(int eventType) {
6487        if (mAccessibilityDelegate != null) {
6488            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6489        } else {
6490            sendAccessibilityEventInternal(eventType);
6491        }
6492    }
6493
6494    /**
6495     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6496     * {@link AccessibilityEvent} to make an announcement which is related to some
6497     * sort of a context change for which none of the events representing UI transitions
6498     * is a good fit. For example, announcing a new page in a book. If accessibility
6499     * is not enabled this method does nothing.
6500     *
6501     * @param text The announcement text.
6502     */
6503    public void announceForAccessibility(CharSequence text) {
6504        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6505            AccessibilityEvent event = AccessibilityEvent.obtain(
6506                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6507            onInitializeAccessibilityEvent(event);
6508            event.getText().add(text);
6509            event.setContentDescription(null);
6510            mParent.requestSendAccessibilityEvent(this, event);
6511        }
6512    }
6513
6514    /**
6515     * @see #sendAccessibilityEvent(int)
6516     *
6517     * Note: Called from the default {@link AccessibilityDelegate}.
6518     *
6519     * @hide
6520     */
6521    public void sendAccessibilityEventInternal(int eventType) {
6522        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6523            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6524        }
6525    }
6526
6527    /**
6528     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6529     * takes as an argument an empty {@link AccessibilityEvent} and does not
6530     * perform a check whether accessibility is enabled.
6531     * <p>
6532     * If an {@link AccessibilityDelegate} has been specified via calling
6533     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6534     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6535     * is responsible for handling this call.
6536     * </p>
6537     *
6538     * @param event The event to send.
6539     *
6540     * @see #sendAccessibilityEvent(int)
6541     */
6542    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6543        if (mAccessibilityDelegate != null) {
6544            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6545        } else {
6546            sendAccessibilityEventUncheckedInternal(event);
6547        }
6548    }
6549
6550    /**
6551     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6552     *
6553     * Note: Called from the default {@link AccessibilityDelegate}.
6554     *
6555     * @hide
6556     */
6557    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6558        if (!isShown()) {
6559            return;
6560        }
6561        onInitializeAccessibilityEvent(event);
6562        // Only a subset of accessibility events populates text content.
6563        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6564            dispatchPopulateAccessibilityEvent(event);
6565        }
6566        // In the beginning we called #isShown(), so we know that getParent() is not null.
6567        getParent().requestSendAccessibilityEvent(this, event);
6568    }
6569
6570    /**
6571     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6572     * to its children for adding their text content to the event. Note that the
6573     * event text is populated in a separate dispatch path since we add to the
6574     * event not only the text of the source but also the text of all its descendants.
6575     * A typical implementation will call
6576     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6577     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6578     * on each child. Override this method if custom population of the event text
6579     * content is required.
6580     * <p>
6581     * If an {@link AccessibilityDelegate} has been specified via calling
6582     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6583     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6584     * is responsible for handling this call.
6585     * </p>
6586     * <p>
6587     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6588     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6589     * </p>
6590     *
6591     * @param event The event.
6592     *
6593     * @return True if the event population was completed.
6594     */
6595    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6596        if (mAccessibilityDelegate != null) {
6597            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6598        } else {
6599            return dispatchPopulateAccessibilityEventInternal(event);
6600        }
6601    }
6602
6603    /**
6604     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6605     *
6606     * Note: Called from the default {@link AccessibilityDelegate}.
6607     *
6608     * @hide
6609     */
6610    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6611        onPopulateAccessibilityEvent(event);
6612        return false;
6613    }
6614
6615    /**
6616     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6617     * giving a chance to this View to populate the accessibility event with its
6618     * text content. While this method is free to modify event
6619     * attributes other than text content, doing so should normally be performed in
6620     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6621     * <p>
6622     * Example: Adding formatted date string to an accessibility event in addition
6623     *          to the text added by the super implementation:
6624     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6625     *     super.onPopulateAccessibilityEvent(event);
6626     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6627     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6628     *         mCurrentDate.getTimeInMillis(), flags);
6629     *     event.getText().add(selectedDateUtterance);
6630     * }</pre>
6631     * <p>
6632     * If an {@link AccessibilityDelegate} has been specified via calling
6633     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6634     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6635     * is responsible for handling this call.
6636     * </p>
6637     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6638     * information to the event, in case the default implementation has basic information to add.
6639     * </p>
6640     *
6641     * @param event The accessibility event which to populate.
6642     *
6643     * @see #sendAccessibilityEvent(int)
6644     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6645     */
6646    @CallSuper
6647    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6648        if (mAccessibilityDelegate != null) {
6649            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6650        } else {
6651            onPopulateAccessibilityEventInternal(event);
6652        }
6653    }
6654
6655    /**
6656     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6657     *
6658     * Note: Called from the default {@link AccessibilityDelegate}.
6659     *
6660     * @hide
6661     */
6662    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6663    }
6664
6665    /**
6666     * Initializes an {@link AccessibilityEvent} with information about
6667     * this View which is the event source. In other words, the source of
6668     * an accessibility event is the view whose state change triggered firing
6669     * the event.
6670     * <p>
6671     * Example: Setting the password property of an event in addition
6672     *          to properties set by the super implementation:
6673     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6674     *     super.onInitializeAccessibilityEvent(event);
6675     *     event.setPassword(true);
6676     * }</pre>
6677     * <p>
6678     * If an {@link AccessibilityDelegate} has been specified via calling
6679     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6680     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6681     * is responsible for handling this call.
6682     * </p>
6683     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6684     * information to the event, in case the default implementation has basic information to add.
6685     * </p>
6686     * @param event The event to initialize.
6687     *
6688     * @see #sendAccessibilityEvent(int)
6689     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6690     */
6691    @CallSuper
6692    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6693        if (mAccessibilityDelegate != null) {
6694            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6695        } else {
6696            onInitializeAccessibilityEventInternal(event);
6697        }
6698    }
6699
6700    /**
6701     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6702     *
6703     * Note: Called from the default {@link AccessibilityDelegate}.
6704     *
6705     * @hide
6706     */
6707    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6708        event.setSource(this);
6709        event.setClassName(getAccessibilityClassName());
6710        event.setPackageName(getContext().getPackageName());
6711        event.setEnabled(isEnabled());
6712        event.setContentDescription(mContentDescription);
6713
6714        switch (event.getEventType()) {
6715            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6716                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6717                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6718                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6719                event.setItemCount(focusablesTempList.size());
6720                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6721                if (mAttachInfo != null) {
6722                    focusablesTempList.clear();
6723                }
6724            } break;
6725            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6726                CharSequence text = getIterableTextForAccessibility();
6727                if (text != null && text.length() > 0) {
6728                    event.setFromIndex(getAccessibilitySelectionStart());
6729                    event.setToIndex(getAccessibilitySelectionEnd());
6730                    event.setItemCount(text.length());
6731                }
6732            } break;
6733        }
6734    }
6735
6736    /**
6737     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6738     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6739     * This method is responsible for obtaining an accessibility node info from a
6740     * pool of reusable instances and calling
6741     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6742     * initialize the former.
6743     * <p>
6744     * Note: The client is responsible for recycling the obtained instance by calling
6745     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6746     * </p>
6747     *
6748     * @return A populated {@link AccessibilityNodeInfo}.
6749     *
6750     * @see AccessibilityNodeInfo
6751     */
6752    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6753        if (mAccessibilityDelegate != null) {
6754            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6755        } else {
6756            return createAccessibilityNodeInfoInternal();
6757        }
6758    }
6759
6760    /**
6761     * @see #createAccessibilityNodeInfo()
6762     *
6763     * @hide
6764     */
6765    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6766        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6767        if (provider != null) {
6768            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6769        } else {
6770            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6771            onInitializeAccessibilityNodeInfo(info);
6772            return info;
6773        }
6774    }
6775
6776    /**
6777     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6778     * The base implementation sets:
6779     * <ul>
6780     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6781     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6782     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6783     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6784     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6785     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6786     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6787     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6788     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6789     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6790     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6791     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6792     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6793     * </ul>
6794     * <p>
6795     * Subclasses should override this method, call the super implementation,
6796     * and set additional attributes.
6797     * </p>
6798     * <p>
6799     * If an {@link AccessibilityDelegate} has been specified via calling
6800     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6801     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6802     * is responsible for handling this call.
6803     * </p>
6804     *
6805     * @param info The instance to initialize.
6806     */
6807    @CallSuper
6808    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6809        if (mAccessibilityDelegate != null) {
6810            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6811        } else {
6812            onInitializeAccessibilityNodeInfoInternal(info);
6813        }
6814    }
6815
6816    /**
6817     * Gets the location of this view in screen coordinates.
6818     *
6819     * @param outRect The output location
6820     * @hide
6821     */
6822    public void getBoundsOnScreen(Rect outRect) {
6823        getBoundsOnScreen(outRect, false);
6824    }
6825
6826    /**
6827     * Gets the location of this view in screen coordinates.
6828     *
6829     * @param outRect The output location
6830     * @param clipToParent Whether to clip child bounds to the parent ones.
6831     * @hide
6832     */
6833    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6834        if (mAttachInfo == null) {
6835            return;
6836        }
6837
6838        RectF position = mAttachInfo.mTmpTransformRect;
6839        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6840
6841        if (!hasIdentityMatrix()) {
6842            getMatrix().mapRect(position);
6843        }
6844
6845        position.offset(mLeft, mTop);
6846
6847        ViewParent parent = mParent;
6848        while (parent instanceof View) {
6849            View parentView = (View) parent;
6850
6851            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6852
6853            if (clipToParent) {
6854                position.left = Math.max(position.left, 0);
6855                position.top = Math.max(position.top, 0);
6856                position.right = Math.min(position.right, parentView.getWidth());
6857                position.bottom = Math.min(position.bottom, parentView.getHeight());
6858            }
6859
6860            if (!parentView.hasIdentityMatrix()) {
6861                parentView.getMatrix().mapRect(position);
6862            }
6863
6864            position.offset(parentView.mLeft, parentView.mTop);
6865
6866            parent = parentView.mParent;
6867        }
6868
6869        if (parent instanceof ViewRootImpl) {
6870            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6871            position.offset(0, -viewRootImpl.mCurScrollY);
6872        }
6873
6874        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6875
6876        outRect.set(Math.round(position.left), Math.round(position.top),
6877                Math.round(position.right), Math.round(position.bottom));
6878    }
6879
6880    /**
6881     * Return the class name of this object to be used for accessibility purposes.
6882     * Subclasses should only override this if they are implementing something that
6883     * should be seen as a completely new class of view when used by accessibility,
6884     * unrelated to the class it is deriving from.  This is used to fill in
6885     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6886     */
6887    public CharSequence getAccessibilityClassName() {
6888        return View.class.getName();
6889    }
6890
6891    /**
6892     * Called when assist structure is being retrieved from a view as part of
6893     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6894     * @param structure Fill in with structured view data.  The default implementation
6895     * fills in all data that can be inferred from the view itself.
6896     */
6897    public void onProvideStructure(ViewStructure structure) {
6898        onProvideStructureForAssistOrAutoFill(structure, 0);
6899    }
6900
6901    /**
6902     * Called when assist structure is being retrieved from a view as part of an auto-fill request.
6903     *
6904     * <p>The structure must be filled according to the request type, which is set in the
6905     * {@code flags} parameter - see the documentation on each flag for more details.
6906     *
6907     * @param structure Fill in with structured view data.  The default implementation
6908     * fills in all data that can be inferred from the view itself.
6909     * @param flags optional flags (see {@link #AUTO_FILL_FLAG_TYPE_FILL} and
6910     * {@link #AUTO_FILL_FLAG_TYPE_SAVE} for more info).
6911     */
6912    public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
6913        onProvideStructureForAssistOrAutoFill(structure, flags);
6914    }
6915
6916    private void onProvideStructureForAssistOrAutoFill(ViewStructure structure, int flags) {
6917        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
6918        // this method should take a boolean with the type of request.
6919        boolean forAutoFill = (flags
6920                & (View.AUTO_FILL_FLAG_TYPE_FILL
6921                        | View.AUTO_FILL_FLAG_TYPE_SAVE)) != 0;
6922        final int id = mID;
6923        if (id != NO_ID && !isViewIdGenerated(id)) {
6924            String pkg, type, entry;
6925            try {
6926                final Resources res = getResources();
6927                entry = res.getResourceEntryName(id);
6928                type = res.getResourceTypeName(id);
6929                pkg = res.getResourcePackageName(id);
6930            } catch (Resources.NotFoundException e) {
6931                entry = type = pkg = null;
6932            }
6933            structure.setId(id, pkg, type, entry);
6934        } else {
6935            structure.setId(id, null, null, null);
6936        }
6937
6938        if (forAutoFill) {
6939            // The auto-fill id needs to be unique, but its value doesn't matter, so it's better to
6940            // reuse the accessibility id to save space.
6941            mAutoFillId = getAccessibilityViewId();
6942            structure.setAutoFillId(mAutoFillId);
6943            structure.setAutoFillType(getAutoFillType());
6944        }
6945
6946        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6947        if (!hasIdentityMatrix()) {
6948            structure.setTransformation(getMatrix());
6949        }
6950        structure.setElevation(getZ());
6951        structure.setVisibility(getVisibility());
6952        structure.setEnabled(isEnabled());
6953        if (isClickable()) {
6954            structure.setClickable(true);
6955        }
6956        if (isFocusable()) {
6957            structure.setFocusable(true);
6958        }
6959        if (isFocused()) {
6960            structure.setFocused(true);
6961        }
6962        if (isAccessibilityFocused()) {
6963            structure.setAccessibilityFocused(true);
6964        }
6965        if (isSelected()) {
6966            structure.setSelected(true);
6967        }
6968        if (isActivated()) {
6969            structure.setActivated(true);
6970        }
6971        if (isLongClickable()) {
6972            structure.setLongClickable(true);
6973        }
6974        if (this instanceof Checkable) {
6975            structure.setCheckable(true);
6976            if (((Checkable)this).isChecked()) {
6977                structure.setChecked(true);
6978            }
6979        }
6980        if (isContextClickable()) {
6981            structure.setContextClickable(true);
6982        }
6983        structure.setClassName(getAccessibilityClassName().toString());
6984        structure.setContentDescription(getContentDescription());
6985    }
6986
6987    /**
6988     * Called when assist structure is being retrieved from a view as part of
6989     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6990     * generate additional virtual structure under this view.  The defaullt implementation
6991     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6992     * view's virtual accessibility nodes, if any.  You can override this for a more
6993     * optimal implementation providing this data.
6994     */
6995    public void onProvideVirtualStructure(ViewStructure structure) {
6996        onProvideVirtualStructureForAssistOrAutoFill(structure, 0);
6997    }
6998
6999    /**
7000     * Called when assist structure is being retrieved from a view as part of an auto-fill request
7001     * to generate additional virtual structure under this view.
7002     *
7003     * <p>The defaullt implementation uses {@link #getAccessibilityNodeProvider()} to try to
7004     * generate this from the view's virtual accessibility nodes, if any. You can override this
7005     * for a more optimal implementation providing this data.
7006     *
7007     * <p>The structure must be filled according to the request type, which is set in the
7008     * {@code flags} parameter - see the documentation on each flag for more details.
7009     *
7010     * @param structure Fill in with structured view data.
7011     * @param flags optional flags (see {@link #AUTO_FILL_FLAG_TYPE_FILL} and
7012     * {@link #AUTO_FILL_FLAG_TYPE_SAVE} for more info).
7013     */
7014    public void onProvideAutoFillVirtualStructure(ViewStructure structure, int flags) {
7015        onProvideVirtualStructureForAssistOrAutoFill(structure, flags);
7016    }
7017
7018    private void onProvideVirtualStructureForAssistOrAutoFill(ViewStructure structure, int flags) {
7019        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
7020        // this method should take a boolean with the type of request.
7021        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7022        if (provider != null) {
7023            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7024            structure.setChildCount(1);
7025            ViewStructure root = structure.newChild(0);
7026            populateVirtualStructure(root, provider, info, flags);
7027            info.recycle();
7028        }
7029    }
7030
7031    /**
7032     * Gets the {@link VirtualViewDelegate} responsible for auto-filling the virtual children of
7033     * this view.
7034     *
7035     * <p>By default returns {@code null} but should be overridden when view provides a virtual
7036     * hierachy on {@link OnProvideAssistDataListener} that takes flags used by the AutoFill
7037     * Framework (such as {@link #AUTO_FILL_FLAG_TYPE_FILL} and
7038     * {@link #AUTO_FILL_FLAG_TYPE_SAVE}).
7039     */
7040    @Nullable
7041    public VirtualViewDelegate getAutoFillVirtualViewDelegate(
7042            @SuppressWarnings("unused") VirtualViewDelegate.Callback callback) {
7043        return null;
7044    }
7045
7046    /**
7047     * Automatically fills the content of this view with the {@code value}.
7048     *
7049     * <p>By default does nothing, but views should override it (and {@link #getAutoFillType()} to
7050     * support the AutoFill Framework.
7051     *
7052     * <p>Typically, it is implemented by:
7053     *
7054     * <ol>
7055     * <li>Call the proper getter method on {@link AutoFillValue} to fetch the actual value.
7056     * <li>Pass the actual value to the equivalent setter in the view.
7057     * <ol>
7058     *
7059     * <p>For example, a text-field view would call:
7060     *
7061     * <pre class="prettyprint">
7062     * CharSequence text = value.getTextValue();
7063     * if (text != null) {
7064     *     setText(text);
7065     * }
7066     * </pre>
7067     */
7068    public void autoFill(@SuppressWarnings("unused") AutoFillValue value) {
7069    }
7070
7071    /**
7072     * Describes the auto-fill type that should be used on calls to
7073     * {@link #autoFill(AutoFillValue)} and
7074     * {@link VirtualViewDelegate#autoFill(int, AutoFillValue)}.
7075     *
7076     * <p>By default returns {@code null}, but views should override it (and
7077     * {@link #autoFill(AutoFillValue)} to support the AutoFill Framework.
7078     */
7079    @Nullable
7080    public AutoFillType getAutoFillType() {
7081        return null;
7082    }
7083
7084    private void populateVirtualStructure(ViewStructure structure,
7085            AccessibilityNodeProvider provider, AccessibilityNodeInfo info, int flags) {
7086        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
7087        // this method should take a boolean with the type of request.
7088
7089        final boolean sanitized = (flags & View.AUTO_FILL_FLAG_TYPE_FILL) != 0;
7090
7091        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7092                null, null, null);
7093        Rect rect = structure.getTempRect();
7094        info.getBoundsInParent(rect);
7095        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7096        structure.setVisibility(VISIBLE);
7097        structure.setEnabled(info.isEnabled());
7098        if (info.isClickable()) {
7099            structure.setClickable(true);
7100        }
7101        if (info.isFocusable()) {
7102            structure.setFocusable(true);
7103        }
7104        if (info.isFocused()) {
7105            structure.setFocused(true);
7106        }
7107        if (info.isAccessibilityFocused()) {
7108            structure.setAccessibilityFocused(true);
7109        }
7110        if (info.isSelected()) {
7111            structure.setSelected(true);
7112        }
7113        if (info.isLongClickable()) {
7114            structure.setLongClickable(true);
7115        }
7116        if (info.isCheckable()) {
7117            structure.setCheckable(true);
7118            if (info.isChecked()) {
7119                structure.setChecked(true);
7120            }
7121        }
7122        if (info.isContextClickable()) {
7123            structure.setContextClickable(true);
7124        }
7125        CharSequence cname = info.getClassName();
7126        structure.setClassName(cname != null ? cname.toString() : null);
7127        structure.setContentDescription(info.getContentDescription());
7128        if (!sanitized && (info.getText() != null || info.getError() != null)) {
7129            // TODO(b/33197203) (b/33269702): when sanitized, try to use the Accessibility API to
7130            // just set sanitized values (like text coming from resource files), rather than not
7131            // setting it at all.
7132            structure.setText(info.getText(), info.getTextSelectionStart(),
7133                    info.getTextSelectionEnd());
7134        }
7135        final int NCHILDREN = info.getChildCount();
7136        if (NCHILDREN > 0) {
7137            structure.setChildCount(NCHILDREN);
7138            for (int i=0; i<NCHILDREN; i++) {
7139                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
7140                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
7141                ViewStructure child = structure.newChild(i);
7142                populateVirtualStructure(child, provider, cinfo, flags);
7143                cinfo.recycle();
7144            }
7145        }
7146    }
7147
7148    /**
7149     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
7150     * implementation calls {@link #onProvideStructure} and
7151     * {@link #onProvideVirtualStructure}.
7152     */
7153    public void dispatchProvideStructure(ViewStructure structure) {
7154        dispatchProvideStructureForAssistOrAutoFill(structure, 0);
7155    }
7156
7157    /**
7158     * Dispatch creation of {@link ViewStructure} down the hierarchy.
7159     *
7160     * <p>The structure must be filled according to the request type, which is set in the
7161     * {@code flags} parameter - see the documentation on each flag for more details.
7162     *
7163     * <p>The default implementation calls {@link #onProvideAutoFillStructure(ViewStructure, int)}
7164     * and {@link #onProvideAutoFillVirtualStructure(ViewStructure, int)}.
7165     *
7166     * @param structure Fill in with structured view data.
7167     * @param flags optional flags (see {@link #AUTO_FILL_FLAG_TYPE_FILL} and
7168     * {@link #AUTO_FILL_FLAG_TYPE_SAVE} for more info).
7169     */
7170    public void dispatchProvideAutoFillStructure(ViewStructure structure, int flags) {
7171        dispatchProvideStructureForAssistOrAutoFill(structure, flags);
7172    }
7173
7174    private void dispatchProvideStructureForAssistOrAutoFill(ViewStructure structure, int flags) {
7175        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
7176        // this method should take a boolean with the type of request.
7177        boolean forAutoFill = (flags
7178                & (View.AUTO_FILL_FLAG_TYPE_FILL
7179                        | View.AUTO_FILL_FLAG_TYPE_SAVE)) != 0;
7180
7181        boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
7182        if (!blocked) {
7183            if (forAutoFill) {
7184                onProvideAutoFillStructure(structure, flags);
7185                onProvideAutoFillVirtualStructure(structure, flags);
7186            } else {
7187                onProvideStructure(structure);
7188                onProvideVirtualStructure(structure);
7189            }
7190        } else {
7191            structure.setClassName(getAccessibilityClassName().toString());
7192            structure.setAssistBlocked(true);
7193        }
7194    }
7195
7196    /**
7197     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
7198     *
7199     * Note: Called from the default {@link AccessibilityDelegate}.
7200     *
7201     * @hide
7202     */
7203    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
7204        if (mAttachInfo == null) {
7205            return;
7206        }
7207
7208        Rect bounds = mAttachInfo.mTmpInvalRect;
7209
7210        getDrawingRect(bounds);
7211        info.setBoundsInParent(bounds);
7212
7213        getBoundsOnScreen(bounds, true);
7214        info.setBoundsInScreen(bounds);
7215
7216        ViewParent parent = getParentForAccessibility();
7217        if (parent instanceof View) {
7218            info.setParent((View) parent);
7219        }
7220
7221        if (mID != View.NO_ID) {
7222            View rootView = getRootView();
7223            if (rootView == null) {
7224                rootView = this;
7225            }
7226
7227            View label = rootView.findLabelForView(this, mID);
7228            if (label != null) {
7229                info.setLabeledBy(label);
7230            }
7231
7232            if ((mAttachInfo.mAccessibilityFetchFlags
7233                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
7234                    && Resources.resourceHasPackage(mID)) {
7235                try {
7236                    String viewId = getResources().getResourceName(mID);
7237                    info.setViewIdResourceName(viewId);
7238                } catch (Resources.NotFoundException nfe) {
7239                    /* ignore */
7240                }
7241            }
7242        }
7243
7244        if (mLabelForId != View.NO_ID) {
7245            View rootView = getRootView();
7246            if (rootView == null) {
7247                rootView = this;
7248            }
7249            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
7250            if (labeled != null) {
7251                info.setLabelFor(labeled);
7252            }
7253        }
7254
7255        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
7256            View rootView = getRootView();
7257            if (rootView == null) {
7258                rootView = this;
7259            }
7260            View next = rootView.findViewInsideOutShouldExist(this,
7261                    mAccessibilityTraversalBeforeId);
7262            if (next != null && next.includeForAccessibility()) {
7263                info.setTraversalBefore(next);
7264            }
7265        }
7266
7267        if (mAccessibilityTraversalAfterId != View.NO_ID) {
7268            View rootView = getRootView();
7269            if (rootView == null) {
7270                rootView = this;
7271            }
7272            View next = rootView.findViewInsideOutShouldExist(this,
7273                    mAccessibilityTraversalAfterId);
7274            if (next != null && next.includeForAccessibility()) {
7275                info.setTraversalAfter(next);
7276            }
7277        }
7278
7279        info.setVisibleToUser(isVisibleToUser());
7280
7281        info.setImportantForAccessibility(isImportantForAccessibility());
7282        info.setPackageName(mContext.getPackageName());
7283        info.setClassName(getAccessibilityClassName());
7284        info.setContentDescription(getContentDescription());
7285
7286        info.setEnabled(isEnabled());
7287        info.setClickable(isClickable());
7288        info.setFocusable(isFocusable());
7289        info.setFocused(isFocused());
7290        info.setAccessibilityFocused(isAccessibilityFocused());
7291        info.setSelected(isSelected());
7292        info.setLongClickable(isLongClickable());
7293        info.setContextClickable(isContextClickable());
7294        info.setLiveRegion(getAccessibilityLiveRegion());
7295
7296        // TODO: These make sense only if we are in an AdapterView but all
7297        // views can be selected. Maybe from accessibility perspective
7298        // we should report as selectable view in an AdapterView.
7299        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
7300        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
7301
7302        if (isFocusable()) {
7303            if (isFocused()) {
7304                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
7305            } else {
7306                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
7307            }
7308        }
7309
7310        if (!isAccessibilityFocused()) {
7311            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
7312        } else {
7313            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
7314        }
7315
7316        if (isClickable() && isEnabled()) {
7317            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
7318        }
7319
7320        if (isLongClickable() && isEnabled()) {
7321            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
7322        }
7323
7324        if (isContextClickable() && isEnabled()) {
7325            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
7326        }
7327
7328        CharSequence text = getIterableTextForAccessibility();
7329        if (text != null && text.length() > 0) {
7330            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
7331
7332            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
7333            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
7334            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
7335            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
7336                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
7337                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
7338        }
7339
7340        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
7341        populateAccessibilityNodeInfoDrawingOrderInParent(info);
7342    }
7343
7344    /**
7345     * Determine the order in which this view will be drawn relative to its siblings for a11y
7346     *
7347     * @param info The info whose drawing order should be populated
7348     */
7349    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7350        /*
7351         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7352         * drawing order may not be well-defined, and some Views with custom drawing order may
7353         * not be initialized sufficiently to respond properly getChildDrawingOrder.
7354         */
7355        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7356            info.setDrawingOrder(0);
7357            return;
7358        }
7359        int drawingOrderInParent = 1;
7360        // Iterate up the hierarchy if parents are not important for a11y
7361        View viewAtDrawingLevel = this;
7362        final ViewParent parent = getParentForAccessibility();
7363        while (viewAtDrawingLevel != parent) {
7364            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7365            if (!(currentParent instanceof ViewGroup)) {
7366                // Should only happen for the Decor
7367                drawingOrderInParent = 0;
7368                break;
7369            } else {
7370                final ViewGroup parentGroup = (ViewGroup) currentParent;
7371                final int childCount = parentGroup.getChildCount();
7372                if (childCount > 1) {
7373                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7374                    if (preorderedList != null) {
7375                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7376                        for (int i = 0; i < childDrawIndex; i++) {
7377                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7378                        }
7379                    } else {
7380                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7381                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7382                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7383                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7384                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7385                        if (childDrawIndex != 0) {
7386                            for (int i = 0; i < numChildrenToIterate; i++) {
7387                                final int otherDrawIndex = (customOrder ?
7388                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7389                                if (otherDrawIndex < childDrawIndex) {
7390                                    drawingOrderInParent +=
7391                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7392                                }
7393                            }
7394                        }
7395                    }
7396                }
7397            }
7398            viewAtDrawingLevel = (View) currentParent;
7399        }
7400        info.setDrawingOrder(drawingOrderInParent);
7401    }
7402
7403    private static int numViewsForAccessibility(View view) {
7404        if (view != null) {
7405            if (view.includeForAccessibility()) {
7406                return 1;
7407            } else if (view instanceof ViewGroup) {
7408                return ((ViewGroup) view).getNumChildrenForAccessibility();
7409            }
7410        }
7411        return 0;
7412    }
7413
7414    private View findLabelForView(View view, int labeledId) {
7415        if (mMatchLabelForPredicate == null) {
7416            mMatchLabelForPredicate = new MatchLabelForPredicate();
7417        }
7418        mMatchLabelForPredicate.mLabeledId = labeledId;
7419        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7420    }
7421
7422    /**
7423     * Computes whether this view is visible to the user. Such a view is
7424     * attached, visible, all its predecessors are visible, it is not clipped
7425     * entirely by its predecessors, and has an alpha greater than zero.
7426     *
7427     * @return Whether the view is visible on the screen.
7428     *
7429     * @hide
7430     */
7431    protected boolean isVisibleToUser() {
7432        return isVisibleToUser(null);
7433    }
7434
7435    /**
7436     * Computes whether the given portion of this view is visible to the user.
7437     * Such a view is attached, visible, all its predecessors are visible,
7438     * has an alpha greater than zero, and the specified portion is not
7439     * clipped entirely by its predecessors.
7440     *
7441     * @param boundInView the portion of the view to test; coordinates should be relative; may be
7442     *                    <code>null</code>, and the entire view will be tested in this case.
7443     *                    When <code>true</code> is returned by the function, the actual visible
7444     *                    region will be stored in this parameter; that is, if boundInView is fully
7445     *                    contained within the view, no modification will be made, otherwise regions
7446     *                    outside of the visible area of the view will be clipped.
7447     *
7448     * @return Whether the specified portion of the view is visible on the screen.
7449     *
7450     * @hide
7451     */
7452    protected boolean isVisibleToUser(Rect boundInView) {
7453        if (mAttachInfo != null) {
7454            // Attached to invisible window means this view is not visible.
7455            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
7456                return false;
7457            }
7458            // An invisible predecessor or one with alpha zero means
7459            // that this view is not visible to the user.
7460            Object current = this;
7461            while (current instanceof View) {
7462                View view = (View) current;
7463                // We have attach info so this view is attached and there is no
7464                // need to check whether we reach to ViewRootImpl on the way up.
7465                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
7466                        view.getVisibility() != VISIBLE) {
7467                    return false;
7468                }
7469                current = view.mParent;
7470            }
7471            // Check if the view is entirely covered by its predecessors.
7472            Rect visibleRect = mAttachInfo.mTmpInvalRect;
7473            Point offset = mAttachInfo.mPoint;
7474            if (!getGlobalVisibleRect(visibleRect, offset)) {
7475                return false;
7476            }
7477            // Check if the visible portion intersects the rectangle of interest.
7478            if (boundInView != null) {
7479                visibleRect.offset(-offset.x, -offset.y);
7480                return boundInView.intersect(visibleRect);
7481            }
7482            return true;
7483        }
7484        return false;
7485    }
7486
7487    /**
7488     * Returns the delegate for implementing accessibility support via
7489     * composition. For more details see {@link AccessibilityDelegate}.
7490     *
7491     * @return The delegate, or null if none set.
7492     *
7493     * @hide
7494     */
7495    public AccessibilityDelegate getAccessibilityDelegate() {
7496        return mAccessibilityDelegate;
7497    }
7498
7499    /**
7500     * Sets a delegate for implementing accessibility support via composition
7501     * (as opposed to inheritance). For more details, see
7502     * {@link AccessibilityDelegate}.
7503     * <p>
7504     * <strong>Note:</strong> On platform versions prior to
7505     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
7506     * views in the {@code android.widget.*} package are called <i>before</i>
7507     * host methods. This prevents certain properties such as class name from
7508     * being modified by overriding
7509     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
7510     * as any changes will be overwritten by the host class.
7511     * <p>
7512     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
7513     * methods are called <i>after</i> host methods, which all properties to be
7514     * modified without being overwritten by the host class.
7515     *
7516     * @param delegate the object to which accessibility method calls should be
7517     *                 delegated
7518     * @see AccessibilityDelegate
7519     */
7520    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
7521        mAccessibilityDelegate = delegate;
7522    }
7523
7524    /**
7525     * Gets the provider for managing a virtual view hierarchy rooted at this View
7526     * and reported to {@link android.accessibilityservice.AccessibilityService}s
7527     * that explore the window content.
7528     * <p>
7529     * If this method returns an instance, this instance is responsible for managing
7530     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
7531     * View including the one representing the View itself. Similarly the returned
7532     * instance is responsible for performing accessibility actions on any virtual
7533     * view or the root view itself.
7534     * </p>
7535     * <p>
7536     * If an {@link AccessibilityDelegate} has been specified via calling
7537     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7538     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
7539     * is responsible for handling this call.
7540     * </p>
7541     *
7542     * @return The provider.
7543     *
7544     * @see AccessibilityNodeProvider
7545     */
7546    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
7547        if (mAccessibilityDelegate != null) {
7548            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
7549        } else {
7550            return null;
7551        }
7552    }
7553
7554    /**
7555     * Gets the unique identifier of this view on the screen for accessibility purposes.
7556     *
7557     * @return The view accessibility id.
7558     *
7559     * @hide
7560     */
7561    public int getAccessibilityViewId() {
7562        if (mAccessibilityViewId == NO_ID) {
7563            mAccessibilityViewId = sNextAccessibilityViewId++;
7564        }
7565        return mAccessibilityViewId;
7566    }
7567
7568    /**
7569     * Gets the unique identifier of this view for auto-fill purposes.
7570     *
7571     * <p>It's only set after {@link #onProvideAutoFillStructure(ViewStructure, int)} is called.
7572     *
7573     * @return The view autofill id or {@link #NO_ID} if
7574     * {@link #onProvideAutoFillStructure(ViewStructure, int)}  was not called yet.
7575     *
7576     * @hide
7577     */
7578    public int getAutoFillViewId() {
7579        return mAutoFillId;
7580    }
7581
7582    /**
7583     * Gets the unique identifier of the window in which this View reseides.
7584     *
7585     * @return The window accessibility id.
7586     *
7587     * @hide
7588     */
7589    public int getAccessibilityWindowId() {
7590        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
7591                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
7592    }
7593
7594    /**
7595     * Returns the {@link View}'s content description.
7596     * <p>
7597     * <strong>Note:</strong> Do not override this method, as it will have no
7598     * effect on the content description presented to accessibility services.
7599     * You must call {@link #setContentDescription(CharSequence)} to modify the
7600     * content description.
7601     *
7602     * @return the content description
7603     * @see #setContentDescription(CharSequence)
7604     * @attr ref android.R.styleable#View_contentDescription
7605     */
7606    @ViewDebug.ExportedProperty(category = "accessibility")
7607    public CharSequence getContentDescription() {
7608        return mContentDescription;
7609    }
7610
7611    /**
7612     * Sets the {@link View}'s content description.
7613     * <p>
7614     * A content description briefly describes the view and is primarily used
7615     * for accessibility support to determine how a view should be presented to
7616     * the user. In the case of a view with no textual representation, such as
7617     * {@link android.widget.ImageButton}, a useful content description
7618     * explains what the view does. For example, an image button with a phone
7619     * icon that is used to place a call may use "Call" as its content
7620     * description. An image of a floppy disk that is used to save a file may
7621     * use "Save".
7622     *
7623     * @param contentDescription The content description.
7624     * @see #getContentDescription()
7625     * @attr ref android.R.styleable#View_contentDescription
7626     */
7627    @RemotableViewMethod
7628    public void setContentDescription(CharSequence contentDescription) {
7629        if (mContentDescription == null) {
7630            if (contentDescription == null) {
7631                return;
7632            }
7633        } else if (mContentDescription.equals(contentDescription)) {
7634            return;
7635        }
7636        mContentDescription = contentDescription;
7637        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
7638        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
7639            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
7640            notifySubtreeAccessibilityStateChangedIfNeeded();
7641        } else {
7642            notifyViewAccessibilityStateChangedIfNeeded(
7643                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
7644        }
7645    }
7646
7647    /**
7648     * Sets the id of a view before which this one is visited in accessibility traversal.
7649     * A screen-reader must visit the content of this view before the content of the one
7650     * it precedes. For example, if view B is set to be before view A, then a screen-reader
7651     * will traverse the entire content of B before traversing the entire content of A,
7652     * regardles of what traversal strategy it is using.
7653     * <p>
7654     * Views that do not have specified before/after relationships are traversed in order
7655     * determined by the screen-reader.
7656     * </p>
7657     * <p>
7658     * Setting that this view is before a view that is not important for accessibility
7659     * or if this view is not important for accessibility will have no effect as the
7660     * screen-reader is not aware of unimportant views.
7661     * </p>
7662     *
7663     * @param beforeId The id of a view this one precedes in accessibility traversal.
7664     *
7665     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
7666     *
7667     * @see #setImportantForAccessibility(int)
7668     */
7669    @RemotableViewMethod
7670    public void setAccessibilityTraversalBefore(int beforeId) {
7671        if (mAccessibilityTraversalBeforeId == beforeId) {
7672            return;
7673        }
7674        mAccessibilityTraversalBeforeId = beforeId;
7675        notifyViewAccessibilityStateChangedIfNeeded(
7676                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7677    }
7678
7679    /**
7680     * Gets the id of a view before which this one is visited in accessibility traversal.
7681     *
7682     * @return The id of a view this one precedes in accessibility traversal if
7683     *         specified, otherwise {@link #NO_ID}.
7684     *
7685     * @see #setAccessibilityTraversalBefore(int)
7686     */
7687    public int getAccessibilityTraversalBefore() {
7688        return mAccessibilityTraversalBeforeId;
7689    }
7690
7691    /**
7692     * Sets the id of a view after which this one is visited in accessibility traversal.
7693     * A screen-reader must visit the content of the other view before the content of this
7694     * one. For example, if view B is set to be after view A, then a screen-reader
7695     * will traverse the entire content of A before traversing the entire content of B,
7696     * regardles of what traversal strategy it is using.
7697     * <p>
7698     * Views that do not have specified before/after relationships are traversed in order
7699     * determined by the screen-reader.
7700     * </p>
7701     * <p>
7702     * Setting that this view is after a view that is not important for accessibility
7703     * or if this view is not important for accessibility will have no effect as the
7704     * screen-reader is not aware of unimportant views.
7705     * </p>
7706     *
7707     * @param afterId The id of a view this one succedees in accessibility traversal.
7708     *
7709     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
7710     *
7711     * @see #setImportantForAccessibility(int)
7712     */
7713    @RemotableViewMethod
7714    public void setAccessibilityTraversalAfter(int afterId) {
7715        if (mAccessibilityTraversalAfterId == afterId) {
7716            return;
7717        }
7718        mAccessibilityTraversalAfterId = afterId;
7719        notifyViewAccessibilityStateChangedIfNeeded(
7720                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7721    }
7722
7723    /**
7724     * Gets the id of a view after which this one is visited in accessibility traversal.
7725     *
7726     * @return The id of a view this one succeedes in accessibility traversal if
7727     *         specified, otherwise {@link #NO_ID}.
7728     *
7729     * @see #setAccessibilityTraversalAfter(int)
7730     */
7731    public int getAccessibilityTraversalAfter() {
7732        return mAccessibilityTraversalAfterId;
7733    }
7734
7735    /**
7736     * Gets the id of a view for which this view serves as a label for
7737     * accessibility purposes.
7738     *
7739     * @return The labeled view id.
7740     */
7741    @ViewDebug.ExportedProperty(category = "accessibility")
7742    public int getLabelFor() {
7743        return mLabelForId;
7744    }
7745
7746    /**
7747     * Sets the id of a view for which this view serves as a label for
7748     * accessibility purposes.
7749     *
7750     * @param id The labeled view id.
7751     */
7752    @RemotableViewMethod
7753    public void setLabelFor(@IdRes int id) {
7754        if (mLabelForId == id) {
7755            return;
7756        }
7757        mLabelForId = id;
7758        if (mLabelForId != View.NO_ID
7759                && mID == View.NO_ID) {
7760            mID = generateViewId();
7761        }
7762        notifyViewAccessibilityStateChangedIfNeeded(
7763                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7764    }
7765
7766    /**
7767     * Invoked whenever this view loses focus, either by losing window focus or by losing
7768     * focus within its window. This method can be used to clear any state tied to the
7769     * focus. For instance, if a button is held pressed with the trackball and the window
7770     * loses focus, this method can be used to cancel the press.
7771     *
7772     * Subclasses of View overriding this method should always call super.onFocusLost().
7773     *
7774     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7775     * @see #onWindowFocusChanged(boolean)
7776     *
7777     * @hide pending API council approval
7778     */
7779    @CallSuper
7780    protected void onFocusLost() {
7781        resetPressedState();
7782    }
7783
7784    private void resetPressedState() {
7785        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7786            return;
7787        }
7788
7789        if (isPressed()) {
7790            setPressed(false);
7791
7792            if (!mHasPerformedLongPress) {
7793                removeLongPressCallback();
7794            }
7795        }
7796    }
7797
7798    /**
7799     * Returns true if this view has focus
7800     *
7801     * @return True if this view has focus, false otherwise.
7802     */
7803    @ViewDebug.ExportedProperty(category = "focus")
7804    public boolean isFocused() {
7805        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7806    }
7807
7808    /**
7809     * Find the view in the hierarchy rooted at this view that currently has
7810     * focus.
7811     *
7812     * @return The view that currently has focus, or null if no focused view can
7813     *         be found.
7814     */
7815    public View findFocus() {
7816        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7817    }
7818
7819    /**
7820     * Indicates whether this view is one of the set of scrollable containers in
7821     * its window.
7822     *
7823     * @return whether this view is one of the set of scrollable containers in
7824     * its window
7825     *
7826     * @attr ref android.R.styleable#View_isScrollContainer
7827     */
7828    public boolean isScrollContainer() {
7829        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7830    }
7831
7832    /**
7833     * Change whether this view is one of the set of scrollable containers in
7834     * its window.  This will be used to determine whether the window can
7835     * resize or must pan when a soft input area is open -- scrollable
7836     * containers allow the window to use resize mode since the container
7837     * will appropriately shrink.
7838     *
7839     * @attr ref android.R.styleable#View_isScrollContainer
7840     */
7841    public void setScrollContainer(boolean isScrollContainer) {
7842        if (isScrollContainer) {
7843            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7844                mAttachInfo.mScrollContainers.add(this);
7845                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7846            }
7847            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7848        } else {
7849            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7850                mAttachInfo.mScrollContainers.remove(this);
7851            }
7852            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7853        }
7854    }
7855
7856    /**
7857     * Returns the quality of the drawing cache.
7858     *
7859     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7860     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7861     *
7862     * @see #setDrawingCacheQuality(int)
7863     * @see #setDrawingCacheEnabled(boolean)
7864     * @see #isDrawingCacheEnabled()
7865     *
7866     * @attr ref android.R.styleable#View_drawingCacheQuality
7867     */
7868    @DrawingCacheQuality
7869    public int getDrawingCacheQuality() {
7870        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7871    }
7872
7873    /**
7874     * Set the drawing cache quality of this view. This value is used only when the
7875     * drawing cache is enabled
7876     *
7877     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7878     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7879     *
7880     * @see #getDrawingCacheQuality()
7881     * @see #setDrawingCacheEnabled(boolean)
7882     * @see #isDrawingCacheEnabled()
7883     *
7884     * @attr ref android.R.styleable#View_drawingCacheQuality
7885     */
7886    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7887        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7888    }
7889
7890    /**
7891     * Returns whether the screen should remain on, corresponding to the current
7892     * value of {@link #KEEP_SCREEN_ON}.
7893     *
7894     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7895     *
7896     * @see #setKeepScreenOn(boolean)
7897     *
7898     * @attr ref android.R.styleable#View_keepScreenOn
7899     */
7900    public boolean getKeepScreenOn() {
7901        return (mViewFlags & KEEP_SCREEN_ON) != 0;
7902    }
7903
7904    /**
7905     * Controls whether the screen should remain on, modifying the
7906     * value of {@link #KEEP_SCREEN_ON}.
7907     *
7908     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7909     *
7910     * @see #getKeepScreenOn()
7911     *
7912     * @attr ref android.R.styleable#View_keepScreenOn
7913     */
7914    public void setKeepScreenOn(boolean keepScreenOn) {
7915        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7916    }
7917
7918    /**
7919     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7920     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7921     *
7922     * @attr ref android.R.styleable#View_nextFocusLeft
7923     */
7924    public int getNextFocusLeftId() {
7925        return mNextFocusLeftId;
7926    }
7927
7928    /**
7929     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7930     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7931     * decide automatically.
7932     *
7933     * @attr ref android.R.styleable#View_nextFocusLeft
7934     */
7935    public void setNextFocusLeftId(int nextFocusLeftId) {
7936        mNextFocusLeftId = nextFocusLeftId;
7937    }
7938
7939    /**
7940     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7941     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7942     *
7943     * @attr ref android.R.styleable#View_nextFocusRight
7944     */
7945    public int getNextFocusRightId() {
7946        return mNextFocusRightId;
7947    }
7948
7949    /**
7950     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7951     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7952     * decide automatically.
7953     *
7954     * @attr ref android.R.styleable#View_nextFocusRight
7955     */
7956    public void setNextFocusRightId(int nextFocusRightId) {
7957        mNextFocusRightId = nextFocusRightId;
7958    }
7959
7960    /**
7961     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7962     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7963     *
7964     * @attr ref android.R.styleable#View_nextFocusUp
7965     */
7966    public int getNextFocusUpId() {
7967        return mNextFocusUpId;
7968    }
7969
7970    /**
7971     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7972     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7973     * decide automatically.
7974     *
7975     * @attr ref android.R.styleable#View_nextFocusUp
7976     */
7977    public void setNextFocusUpId(int nextFocusUpId) {
7978        mNextFocusUpId = nextFocusUpId;
7979    }
7980
7981    /**
7982     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7983     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7984     *
7985     * @attr ref android.R.styleable#View_nextFocusDown
7986     */
7987    public int getNextFocusDownId() {
7988        return mNextFocusDownId;
7989    }
7990
7991    /**
7992     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7993     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7994     * decide automatically.
7995     *
7996     * @attr ref android.R.styleable#View_nextFocusDown
7997     */
7998    public void setNextFocusDownId(int nextFocusDownId) {
7999        mNextFocusDownId = nextFocusDownId;
8000    }
8001
8002    /**
8003     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8004     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8005     *
8006     * @attr ref android.R.styleable#View_nextFocusForward
8007     */
8008    public int getNextFocusForwardId() {
8009        return mNextFocusForwardId;
8010    }
8011
8012    /**
8013     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8014     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8015     * decide automatically.
8016     *
8017     * @attr ref android.R.styleable#View_nextFocusForward
8018     */
8019    public void setNextFocusForwardId(int nextFocusForwardId) {
8020        mNextFocusForwardId = nextFocusForwardId;
8021    }
8022
8023    /**
8024     * Gets the id of the root of the next keyboard navigation cluster.
8025     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8026     * decide automatically.
8027     *
8028     * @attr ref android.R.styleable#View_nextClusterForward
8029     */
8030    public int getNextClusterForwardId() {
8031        return mNextClusterForwardId;
8032    }
8033
8034    /**
8035     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8036     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8037     * decide automatically.
8038     *
8039     * @attr ref android.R.styleable#View_nextClusterForward
8040     */
8041    public void setNextClusterForwardId(int nextClusterForwardId) {
8042        mNextClusterForwardId = nextClusterForwardId;
8043    }
8044
8045    /**
8046     * Returns the visibility of this view and all of its ancestors
8047     *
8048     * @return True if this view and all of its ancestors are {@link #VISIBLE}
8049     */
8050    public boolean isShown() {
8051        View current = this;
8052        //noinspection ConstantConditions
8053        do {
8054            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8055                return false;
8056            }
8057            ViewParent parent = current.mParent;
8058            if (parent == null) {
8059                return false; // We are not attached to the view root
8060            }
8061            if (!(parent instanceof View)) {
8062                return true;
8063            }
8064            current = (View) parent;
8065        } while (current != null);
8066
8067        return false;
8068    }
8069
8070    /**
8071     * Called by the view hierarchy when the content insets for a window have
8072     * changed, to allow it to adjust its content to fit within those windows.
8073     * The content insets tell you the space that the status bar, input method,
8074     * and other system windows infringe on the application's window.
8075     *
8076     * <p>You do not normally need to deal with this function, since the default
8077     * window decoration given to applications takes care of applying it to the
8078     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
8079     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
8080     * and your content can be placed under those system elements.  You can then
8081     * use this method within your view hierarchy if you have parts of your UI
8082     * which you would like to ensure are not being covered.
8083     *
8084     * <p>The default implementation of this method simply applies the content
8085     * insets to the view's padding, consuming that content (modifying the
8086     * insets to be 0), and returning true.  This behavior is off by default, but can
8087     * be enabled through {@link #setFitsSystemWindows(boolean)}.
8088     *
8089     * <p>This function's traversal down the hierarchy is depth-first.  The same content
8090     * insets object is propagated down the hierarchy, so any changes made to it will
8091     * be seen by all following views (including potentially ones above in
8092     * the hierarchy since this is a depth-first traversal).  The first view
8093     * that returns true will abort the entire traversal.
8094     *
8095     * <p>The default implementation works well for a situation where it is
8096     * used with a container that covers the entire window, allowing it to
8097     * apply the appropriate insets to its content on all edges.  If you need
8098     * a more complicated layout (such as two different views fitting system
8099     * windows, one on the top of the window, and one on the bottom),
8100     * you can override the method and handle the insets however you would like.
8101     * Note that the insets provided by the framework are always relative to the
8102     * far edges of the window, not accounting for the location of the called view
8103     * within that window.  (In fact when this method is called you do not yet know
8104     * where the layout will place the view, as it is done before layout happens.)
8105     *
8106     * <p>Note: unlike many View methods, there is no dispatch phase to this
8107     * call.  If you are overriding it in a ViewGroup and want to allow the
8108     * call to continue to your children, you must be sure to call the super
8109     * implementation.
8110     *
8111     * <p>Here is a sample layout that makes use of fitting system windows
8112     * to have controls for a video view placed inside of the window decorations
8113     * that it hides and shows.  This can be used with code like the second
8114     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
8115     *
8116     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
8117     *
8118     * @param insets Current content insets of the window.  Prior to
8119     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
8120     * the insets or else you and Android will be unhappy.
8121     *
8122     * @return {@code true} if this view applied the insets and it should not
8123     * continue propagating further down the hierarchy, {@code false} otherwise.
8124     * @see #getFitsSystemWindows()
8125     * @see #setFitsSystemWindows(boolean)
8126     * @see #setSystemUiVisibility(int)
8127     *
8128     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
8129     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
8130     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
8131     * to implement handling their own insets.
8132     */
8133    @Deprecated
8134    protected boolean fitSystemWindows(Rect insets) {
8135        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
8136            if (insets == null) {
8137                // Null insets by definition have already been consumed.
8138                // This call cannot apply insets since there are none to apply,
8139                // so return false.
8140                return false;
8141            }
8142            // If we're not in the process of dispatching the newer apply insets call,
8143            // that means we're not in the compatibility path. Dispatch into the newer
8144            // apply insets path and take things from there.
8145            try {
8146                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
8147                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
8148            } finally {
8149                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
8150            }
8151        } else {
8152            // We're being called from the newer apply insets path.
8153            // Perform the standard fallback behavior.
8154            return fitSystemWindowsInt(insets);
8155        }
8156    }
8157
8158    private boolean fitSystemWindowsInt(Rect insets) {
8159        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
8160            mUserPaddingStart = UNDEFINED_PADDING;
8161            mUserPaddingEnd = UNDEFINED_PADDING;
8162            Rect localInsets = sThreadLocal.get();
8163            if (localInsets == null) {
8164                localInsets = new Rect();
8165                sThreadLocal.set(localInsets);
8166            }
8167            boolean res = computeFitSystemWindows(insets, localInsets);
8168            mUserPaddingLeftInitial = localInsets.left;
8169            mUserPaddingRightInitial = localInsets.right;
8170            internalSetPadding(localInsets.left, localInsets.top,
8171                    localInsets.right, localInsets.bottom);
8172            return res;
8173        }
8174        return false;
8175    }
8176
8177    /**
8178     * Called when the view should apply {@link WindowInsets} according to its internal policy.
8179     *
8180     * <p>This method should be overridden by views that wish to apply a policy different from or
8181     * in addition to the default behavior. Clients that wish to force a view subtree
8182     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
8183     *
8184     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
8185     * it will be called during dispatch instead of this method. The listener may optionally
8186     * call this method from its own implementation if it wishes to apply the view's default
8187     * insets policy in addition to its own.</p>
8188     *
8189     * <p>Implementations of this method should either return the insets parameter unchanged
8190     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
8191     * that this view applied itself. This allows new inset types added in future platform
8192     * versions to pass through existing implementations unchanged without being erroneously
8193     * consumed.</p>
8194     *
8195     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
8196     * property is set then the view will consume the system window insets and apply them
8197     * as padding for the view.</p>
8198     *
8199     * @param insets Insets to apply
8200     * @return The supplied insets with any applied insets consumed
8201     */
8202    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
8203        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
8204            // We weren't called from within a direct call to fitSystemWindows,
8205            // call into it as a fallback in case we're in a class that overrides it
8206            // and has logic to perform.
8207            if (fitSystemWindows(insets.getSystemWindowInsets())) {
8208                return insets.consumeSystemWindowInsets();
8209            }
8210        } else {
8211            // We were called from within a direct call to fitSystemWindows.
8212            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
8213                return insets.consumeSystemWindowInsets();
8214            }
8215        }
8216        return insets;
8217    }
8218
8219    /**
8220     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
8221     * window insets to this view. The listener's
8222     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
8223     * method will be called instead of the view's
8224     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
8225     *
8226     * @param listener Listener to set
8227     *
8228     * @see #onApplyWindowInsets(WindowInsets)
8229     */
8230    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
8231        getListenerInfo().mOnApplyWindowInsetsListener = listener;
8232    }
8233
8234    /**
8235     * Request to apply the given window insets to this view or another view in its subtree.
8236     *
8237     * <p>This method should be called by clients wishing to apply insets corresponding to areas
8238     * obscured by window decorations or overlays. This can include the status and navigation bars,
8239     * action bars, input methods and more. New inset categories may be added in the future.
8240     * The method returns the insets provided minus any that were applied by this view or its
8241     * children.</p>
8242     *
8243     * <p>Clients wishing to provide custom behavior should override the
8244     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
8245     * {@link OnApplyWindowInsetsListener} via the
8246     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
8247     * method.</p>
8248     *
8249     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
8250     * </p>
8251     *
8252     * @param insets Insets to apply
8253     * @return The provided insets minus the insets that were consumed
8254     */
8255    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
8256        try {
8257            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
8258            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
8259                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
8260            } else {
8261                return onApplyWindowInsets(insets);
8262            }
8263        } finally {
8264            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
8265        }
8266    }
8267
8268    /**
8269     * Compute the view's coordinate within the surface.
8270     *
8271     * <p>Computes the coordinates of this view in its surface. The argument
8272     * must be an array of two integers. After the method returns, the array
8273     * contains the x and y location in that order.</p>
8274     * @hide
8275     * @param location an array of two integers in which to hold the coordinates
8276     */
8277    public void getLocationInSurface(@Size(2) int[] location) {
8278        getLocationInWindow(location);
8279        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
8280            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
8281            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
8282        }
8283    }
8284
8285    /**
8286     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
8287     * only available if the view is attached.
8288     *
8289     * @return WindowInsets from the top of the view hierarchy or null if View is detached
8290     */
8291    public WindowInsets getRootWindowInsets() {
8292        if (mAttachInfo != null) {
8293            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
8294        }
8295        return null;
8296    }
8297
8298    /**
8299     * @hide Compute the insets that should be consumed by this view and the ones
8300     * that should propagate to those under it.
8301     */
8302    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
8303        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8304                || mAttachInfo == null
8305                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
8306                        && !mAttachInfo.mOverscanRequested)) {
8307            outLocalInsets.set(inoutInsets);
8308            inoutInsets.set(0, 0, 0, 0);
8309            return true;
8310        } else {
8311            // The application wants to take care of fitting system window for
8312            // the content...  however we still need to take care of any overscan here.
8313            final Rect overscan = mAttachInfo.mOverscanInsets;
8314            outLocalInsets.set(overscan);
8315            inoutInsets.left -= overscan.left;
8316            inoutInsets.top -= overscan.top;
8317            inoutInsets.right -= overscan.right;
8318            inoutInsets.bottom -= overscan.bottom;
8319            return false;
8320        }
8321    }
8322
8323    /**
8324     * Compute insets that should be consumed by this view and the ones that should propagate
8325     * to those under it.
8326     *
8327     * @param in Insets currently being processed by this View, likely received as a parameter
8328     *           to {@link #onApplyWindowInsets(WindowInsets)}.
8329     * @param outLocalInsets A Rect that will receive the insets that should be consumed
8330     *                       by this view
8331     * @return Insets that should be passed along to views under this one
8332     */
8333    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
8334        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8335                || mAttachInfo == null
8336                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
8337            outLocalInsets.set(in.getSystemWindowInsets());
8338            return in.consumeSystemWindowInsets();
8339        } else {
8340            outLocalInsets.set(0, 0, 0, 0);
8341            return in;
8342        }
8343    }
8344
8345    /**
8346     * Sets whether or not this view should account for system screen decorations
8347     * such as the status bar and inset its content; that is, controlling whether
8348     * the default implementation of {@link #fitSystemWindows(Rect)} will be
8349     * executed.  See that method for more details.
8350     *
8351     * <p>Note that if you are providing your own implementation of
8352     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
8353     * flag to true -- your implementation will be overriding the default
8354     * implementation that checks this flag.
8355     *
8356     * @param fitSystemWindows If true, then the default implementation of
8357     * {@link #fitSystemWindows(Rect)} will be executed.
8358     *
8359     * @attr ref android.R.styleable#View_fitsSystemWindows
8360     * @see #getFitsSystemWindows()
8361     * @see #fitSystemWindows(Rect)
8362     * @see #setSystemUiVisibility(int)
8363     */
8364    public void setFitsSystemWindows(boolean fitSystemWindows) {
8365        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
8366    }
8367
8368    /**
8369     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
8370     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
8371     * will be executed.
8372     *
8373     * @return {@code true} if the default implementation of
8374     * {@link #fitSystemWindows(Rect)} will be executed.
8375     *
8376     * @attr ref android.R.styleable#View_fitsSystemWindows
8377     * @see #setFitsSystemWindows(boolean)
8378     * @see #fitSystemWindows(Rect)
8379     * @see #setSystemUiVisibility(int)
8380     */
8381    @ViewDebug.ExportedProperty
8382    public boolean getFitsSystemWindows() {
8383        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8384    }
8385
8386    /** @hide */
8387    public boolean fitsSystemWindows() {
8388        return getFitsSystemWindows();
8389    }
8390
8391    /**
8392     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8393     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8394     */
8395    @Deprecated
8396    public void requestFitSystemWindows() {
8397        if (mParent != null) {
8398            mParent.requestFitSystemWindows();
8399        }
8400    }
8401
8402    /**
8403     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8404     */
8405    public void requestApplyInsets() {
8406        requestFitSystemWindows();
8407    }
8408
8409    /**
8410     * For use by PhoneWindow to make its own system window fitting optional.
8411     * @hide
8412     */
8413    public void makeOptionalFitsSystemWindows() {
8414        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8415    }
8416
8417    /**
8418     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8419     * treat them as such.
8420     * @hide
8421     */
8422    public void getOutsets(Rect outOutsetRect) {
8423        if (mAttachInfo != null) {
8424            outOutsetRect.set(mAttachInfo.mOutsets);
8425        } else {
8426            outOutsetRect.setEmpty();
8427        }
8428    }
8429
8430    /**
8431     * Returns the visibility status for this view.
8432     *
8433     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8434     * @attr ref android.R.styleable#View_visibility
8435     */
8436    @ViewDebug.ExportedProperty(mapping = {
8437        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8438        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8439        @ViewDebug.IntToString(from = GONE,      to = "GONE")
8440    })
8441    @Visibility
8442    public int getVisibility() {
8443        return mViewFlags & VISIBILITY_MASK;
8444    }
8445
8446    /**
8447     * Set the visibility state of this view.
8448     *
8449     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8450     * @attr ref android.R.styleable#View_visibility
8451     */
8452    @RemotableViewMethod
8453    public void setVisibility(@Visibility int visibility) {
8454        setFlags(visibility, VISIBILITY_MASK);
8455    }
8456
8457    /**
8458     * Returns the enabled status for this view. The interpretation of the
8459     * enabled state varies by subclass.
8460     *
8461     * @return True if this view is enabled, false otherwise.
8462     */
8463    @ViewDebug.ExportedProperty
8464    public boolean isEnabled() {
8465        return (mViewFlags & ENABLED_MASK) == ENABLED;
8466    }
8467
8468    /**
8469     * Set the enabled state of this view. The interpretation of the enabled
8470     * state varies by subclass.
8471     *
8472     * @param enabled True if this view is enabled, false otherwise.
8473     */
8474    @RemotableViewMethod
8475    public void setEnabled(boolean enabled) {
8476        if (enabled == isEnabled()) return;
8477
8478        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
8479
8480        /*
8481         * The View most likely has to change its appearance, so refresh
8482         * the drawable state.
8483         */
8484        refreshDrawableState();
8485
8486        // Invalidate too, since the default behavior for views is to be
8487        // be drawn at 50% alpha rather than to change the drawable.
8488        invalidate(true);
8489
8490        if (!enabled) {
8491            cancelPendingInputEvents();
8492        }
8493    }
8494
8495    /**
8496     * Set whether this view can receive the focus.
8497     * <p>
8498     * Setting this to false will also ensure that this view is not focusable
8499     * in touch mode.
8500     *
8501     * @param focusable If true, this view can receive the focus.
8502     *
8503     * @see #setFocusableInTouchMode(boolean)
8504     * @see #setFocusable(int)
8505     * @attr ref android.R.styleable#View_focusable
8506     */
8507    public void setFocusable(boolean focusable) {
8508        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
8509    }
8510
8511    /**
8512     * Sets whether this view can receive focus.
8513     * <p>
8514     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
8515     * automatically based on the view's interactivity. This is the default.
8516     * <p>
8517     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
8518     * in touch mode.
8519     *
8520     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
8521     *                  or {@link #FOCUSABLE_AUTO}.
8522     * @see #setFocusableInTouchMode(boolean)
8523     * @attr ref android.R.styleable#View_focusable
8524     */
8525    public void setFocusable(@Focusable int focusable) {
8526        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
8527            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
8528        }
8529        setFlags(focusable, FOCUSABLE_MASK);
8530    }
8531
8532    /**
8533     * Set whether this view can receive focus while in touch mode.
8534     *
8535     * Setting this to true will also ensure that this view is focusable.
8536     *
8537     * @param focusableInTouchMode If true, this view can receive the focus while
8538     *   in touch mode.
8539     *
8540     * @see #setFocusable(boolean)
8541     * @attr ref android.R.styleable#View_focusableInTouchMode
8542     */
8543    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
8544        // Focusable in touch mode should always be set before the focusable flag
8545        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
8546        // which, in touch mode, will not successfully request focus on this view
8547        // because the focusable in touch mode flag is not set
8548        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
8549        if (focusableInTouchMode) {
8550            setFlags(FOCUSABLE, FOCUSABLE_MASK);
8551        }
8552    }
8553
8554    /**
8555     * Set whether this view should have sound effects enabled for events such as
8556     * clicking and touching.
8557     *
8558     * <p>You may wish to disable sound effects for a view if you already play sounds,
8559     * for instance, a dial key that plays dtmf tones.
8560     *
8561     * @param soundEffectsEnabled whether sound effects are enabled for this view.
8562     * @see #isSoundEffectsEnabled()
8563     * @see #playSoundEffect(int)
8564     * @attr ref android.R.styleable#View_soundEffectsEnabled
8565     */
8566    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
8567        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
8568    }
8569
8570    /**
8571     * @return whether this view should have sound effects enabled for events such as
8572     *     clicking and touching.
8573     *
8574     * @see #setSoundEffectsEnabled(boolean)
8575     * @see #playSoundEffect(int)
8576     * @attr ref android.R.styleable#View_soundEffectsEnabled
8577     */
8578    @ViewDebug.ExportedProperty
8579    public boolean isSoundEffectsEnabled() {
8580        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
8581    }
8582
8583    /**
8584     * Set whether this view should have haptic feedback for events such as
8585     * long presses.
8586     *
8587     * <p>You may wish to disable haptic feedback if your view already controls
8588     * its own haptic feedback.
8589     *
8590     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
8591     * @see #isHapticFeedbackEnabled()
8592     * @see #performHapticFeedback(int)
8593     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8594     */
8595    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
8596        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
8597    }
8598
8599    /**
8600     * @return whether this view should have haptic feedback enabled for events
8601     * long presses.
8602     *
8603     * @see #setHapticFeedbackEnabled(boolean)
8604     * @see #performHapticFeedback(int)
8605     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8606     */
8607    @ViewDebug.ExportedProperty
8608    public boolean isHapticFeedbackEnabled() {
8609        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
8610    }
8611
8612    /**
8613     * Returns the layout direction for this view.
8614     *
8615     * @return One of {@link #LAYOUT_DIRECTION_LTR},
8616     *   {@link #LAYOUT_DIRECTION_RTL},
8617     *   {@link #LAYOUT_DIRECTION_INHERIT} or
8618     *   {@link #LAYOUT_DIRECTION_LOCALE}.
8619     *
8620     * @attr ref android.R.styleable#View_layoutDirection
8621     *
8622     * @hide
8623     */
8624    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8625        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
8626        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
8627        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
8628        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
8629    })
8630    @LayoutDir
8631    public int getRawLayoutDirection() {
8632        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
8633    }
8634
8635    /**
8636     * Set the layout direction for this view. This will propagate a reset of layout direction
8637     * resolution to the view's children and resolve layout direction for this view.
8638     *
8639     * @param layoutDirection the layout direction to set. Should be one of:
8640     *
8641     * {@link #LAYOUT_DIRECTION_LTR},
8642     * {@link #LAYOUT_DIRECTION_RTL},
8643     * {@link #LAYOUT_DIRECTION_INHERIT},
8644     * {@link #LAYOUT_DIRECTION_LOCALE}.
8645     *
8646     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
8647     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
8648     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
8649     *
8650     * @attr ref android.R.styleable#View_layoutDirection
8651     */
8652    @RemotableViewMethod
8653    public void setLayoutDirection(@LayoutDir int layoutDirection) {
8654        if (getRawLayoutDirection() != layoutDirection) {
8655            // Reset the current layout direction and the resolved one
8656            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
8657            resetRtlProperties();
8658            // Set the new layout direction (filtered)
8659            mPrivateFlags2 |=
8660                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
8661            // We need to resolve all RTL properties as they all depend on layout direction
8662            resolveRtlPropertiesIfNeeded();
8663            requestLayout();
8664            invalidate(true);
8665        }
8666    }
8667
8668    /**
8669     * Returns the resolved layout direction for this view.
8670     *
8671     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
8672     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
8673     *
8674     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
8675     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
8676     *
8677     * @attr ref android.R.styleable#View_layoutDirection
8678     */
8679    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8680        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
8681        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
8682    })
8683    @ResolvedLayoutDir
8684    public int getLayoutDirection() {
8685        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
8686        if (targetSdkVersion < JELLY_BEAN_MR1) {
8687            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
8688            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
8689        }
8690        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
8691                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
8692    }
8693
8694    /**
8695     * Indicates whether or not this view's layout is right-to-left. This is resolved from
8696     * layout attribute and/or the inherited value from the parent
8697     *
8698     * @return true if the layout is right-to-left.
8699     *
8700     * @hide
8701     */
8702    @ViewDebug.ExportedProperty(category = "layout")
8703    public boolean isLayoutRtl() {
8704        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
8705    }
8706
8707    /**
8708     * Indicates whether the view is currently tracking transient state that the
8709     * app should not need to concern itself with saving and restoring, but that
8710     * the framework should take special note to preserve when possible.
8711     *
8712     * <p>A view with transient state cannot be trivially rebound from an external
8713     * data source, such as an adapter binding item views in a list. This may be
8714     * because the view is performing an animation, tracking user selection
8715     * of content, or similar.</p>
8716     *
8717     * @return true if the view has transient state
8718     */
8719    @ViewDebug.ExportedProperty(category = "layout")
8720    public boolean hasTransientState() {
8721        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
8722    }
8723
8724    /**
8725     * Set whether this view is currently tracking transient state that the
8726     * framework should attempt to preserve when possible. This flag is reference counted,
8727     * so every call to setHasTransientState(true) should be paired with a later call
8728     * to setHasTransientState(false).
8729     *
8730     * <p>A view with transient state cannot be trivially rebound from an external
8731     * data source, such as an adapter binding item views in a list. This may be
8732     * because the view is performing an animation, tracking user selection
8733     * of content, or similar.</p>
8734     *
8735     * @param hasTransientState true if this view has transient state
8736     */
8737    public void setHasTransientState(boolean hasTransientState) {
8738        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
8739                mTransientStateCount - 1;
8740        if (mTransientStateCount < 0) {
8741            mTransientStateCount = 0;
8742            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
8743                    "unmatched pair of setHasTransientState calls");
8744        } else if ((hasTransientState && mTransientStateCount == 1) ||
8745                (!hasTransientState && mTransientStateCount == 0)) {
8746            // update flag if we've just incremented up from 0 or decremented down to 0
8747            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
8748                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
8749            if (mParent != null) {
8750                try {
8751                    mParent.childHasTransientStateChanged(this, hasTransientState);
8752                } catch (AbstractMethodError e) {
8753                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8754                            " does not fully implement ViewParent", e);
8755                }
8756            }
8757        }
8758    }
8759
8760    /**
8761     * Returns true if this view is currently attached to a window.
8762     */
8763    public boolean isAttachedToWindow() {
8764        return mAttachInfo != null;
8765    }
8766
8767    /**
8768     * Returns true if this view has been through at least one layout since it
8769     * was last attached to or detached from a window.
8770     */
8771    public boolean isLaidOut() {
8772        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
8773    }
8774
8775    /**
8776     * If this view doesn't do any drawing on its own, set this flag to
8777     * allow further optimizations. By default, this flag is not set on
8778     * View, but could be set on some View subclasses such as ViewGroup.
8779     *
8780     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8781     * you should clear this flag.
8782     *
8783     * @param willNotDraw whether or not this View draw on its own
8784     */
8785    public void setWillNotDraw(boolean willNotDraw) {
8786        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8787    }
8788
8789    /**
8790     * Returns whether or not this View draws on its own.
8791     *
8792     * @return true if this view has nothing to draw, false otherwise
8793     */
8794    @ViewDebug.ExportedProperty(category = "drawing")
8795    public boolean willNotDraw() {
8796        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8797    }
8798
8799    /**
8800     * When a View's drawing cache is enabled, drawing is redirected to an
8801     * offscreen bitmap. Some views, like an ImageView, must be able to
8802     * bypass this mechanism if they already draw a single bitmap, to avoid
8803     * unnecessary usage of the memory.
8804     *
8805     * @param willNotCacheDrawing true if this view does not cache its
8806     *        drawing, false otherwise
8807     */
8808    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8809        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8810    }
8811
8812    /**
8813     * Returns whether or not this View can cache its drawing or not.
8814     *
8815     * @return true if this view does not cache its drawing, false otherwise
8816     */
8817    @ViewDebug.ExportedProperty(category = "drawing")
8818    public boolean willNotCacheDrawing() {
8819        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8820    }
8821
8822    /**
8823     * Indicates whether this view reacts to click events or not.
8824     *
8825     * @return true if the view is clickable, false otherwise
8826     *
8827     * @see #setClickable(boolean)
8828     * @attr ref android.R.styleable#View_clickable
8829     */
8830    @ViewDebug.ExportedProperty
8831    public boolean isClickable() {
8832        return (mViewFlags & CLICKABLE) == CLICKABLE;
8833    }
8834
8835    /**
8836     * Enables or disables click events for this view. When a view
8837     * is clickable it will change its state to "pressed" on every click.
8838     * Subclasses should set the view clickable to visually react to
8839     * user's clicks.
8840     *
8841     * @param clickable true to make the view clickable, false otherwise
8842     *
8843     * @see #isClickable()
8844     * @attr ref android.R.styleable#View_clickable
8845     */
8846    public void setClickable(boolean clickable) {
8847        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8848    }
8849
8850    /**
8851     * Indicates whether this view reacts to long click events or not.
8852     *
8853     * @return true if the view is long clickable, false otherwise
8854     *
8855     * @see #setLongClickable(boolean)
8856     * @attr ref android.R.styleable#View_longClickable
8857     */
8858    public boolean isLongClickable() {
8859        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8860    }
8861
8862    /**
8863     * Enables or disables long click events for this view. When a view is long
8864     * clickable it reacts to the user holding down the button for a longer
8865     * duration than a tap. This event can either launch the listener or a
8866     * context menu.
8867     *
8868     * @param longClickable true to make the view long clickable, false otherwise
8869     * @see #isLongClickable()
8870     * @attr ref android.R.styleable#View_longClickable
8871     */
8872    public void setLongClickable(boolean longClickable) {
8873        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8874    }
8875
8876    /**
8877     * Indicates whether this view reacts to context clicks or not.
8878     *
8879     * @return true if the view is context clickable, false otherwise
8880     * @see #setContextClickable(boolean)
8881     * @attr ref android.R.styleable#View_contextClickable
8882     */
8883    public boolean isContextClickable() {
8884        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8885    }
8886
8887    /**
8888     * Enables or disables context clicking for this view. This event can launch the listener.
8889     *
8890     * @param contextClickable true to make the view react to a context click, false otherwise
8891     * @see #isContextClickable()
8892     * @attr ref android.R.styleable#View_contextClickable
8893     */
8894    public void setContextClickable(boolean contextClickable) {
8895        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8896    }
8897
8898    /**
8899     * Sets the pressed state for this view and provides a touch coordinate for
8900     * animation hinting.
8901     *
8902     * @param pressed Pass true to set the View's internal state to "pressed",
8903     *            or false to reverts the View's internal state from a
8904     *            previously set "pressed" state.
8905     * @param x The x coordinate of the touch that caused the press
8906     * @param y The y coordinate of the touch that caused the press
8907     */
8908    private void setPressed(boolean pressed, float x, float y) {
8909        if (pressed) {
8910            drawableHotspotChanged(x, y);
8911        }
8912
8913        setPressed(pressed);
8914    }
8915
8916    /**
8917     * Sets the pressed state for this view.
8918     *
8919     * @see #isClickable()
8920     * @see #setClickable(boolean)
8921     *
8922     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8923     *        the View's internal state from a previously set "pressed" state.
8924     */
8925    public void setPressed(boolean pressed) {
8926        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8927
8928        if (pressed) {
8929            mPrivateFlags |= PFLAG_PRESSED;
8930        } else {
8931            mPrivateFlags &= ~PFLAG_PRESSED;
8932        }
8933
8934        if (needsRefresh) {
8935            refreshDrawableState();
8936        }
8937        dispatchSetPressed(pressed);
8938    }
8939
8940    /**
8941     * Dispatch setPressed to all of this View's children.
8942     *
8943     * @see #setPressed(boolean)
8944     *
8945     * @param pressed The new pressed state
8946     */
8947    protected void dispatchSetPressed(boolean pressed) {
8948    }
8949
8950    /**
8951     * Indicates whether the view is currently in pressed state. Unless
8952     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8953     * the pressed state.
8954     *
8955     * @see #setPressed(boolean)
8956     * @see #isClickable()
8957     * @see #setClickable(boolean)
8958     *
8959     * @return true if the view is currently pressed, false otherwise
8960     */
8961    @ViewDebug.ExportedProperty
8962    public boolean isPressed() {
8963        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8964    }
8965
8966    /**
8967     * @hide
8968     * Indicates whether this view will participate in data collection through
8969     * {@link ViewStructure}.  If true, it will not provide any data
8970     * for itself or its children.  If false, the normal data collection will be allowed.
8971     *
8972     * @return Returns false if assist data collection is not blocked, else true.
8973     *
8974     * @see #setAssistBlocked(boolean)
8975     * @attr ref android.R.styleable#View_assistBlocked
8976     */
8977    public boolean isAssistBlocked() {
8978        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8979    }
8980
8981    /**
8982     * @hide
8983     * Indicates whether this view will participate in data collection through
8984     * {@link ViewStructure} for auto-fill purposes.
8985     *
8986     * <p>If {@code true}, it will not provide any data for itself or its children.
8987     * <p>If {@code false}, the normal data collection will be allowed.
8988     *
8989     * @return Returns {@code false} if assist data collection for auto-fill is not blocked,
8990     * else {@code true}.
8991     *
8992     * TODO(b/33197203): update / remove javadoc tags below
8993     * @see #setAssistBlocked(boolean)
8994     * @attr ref android.R.styleable#View_assistBlocked
8995     */
8996    public boolean isAutoFillBlocked() {
8997        return false; // TODO(b/33197203): properly implement it
8998    }
8999
9000    /**
9001     * @hide
9002     * Controls whether assist data collection from this view and its children is enabled
9003     * (that is, whether {@link #onProvideStructure} and
9004     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9005     * allowing normal assist collection.  Setting this to false will disable assist collection.
9006     *
9007     * @param enabled Set to true to <em>disable</em> assist data collection, or false
9008     * (the default) to allow it.
9009     *
9010     * @see #isAssistBlocked()
9011     * @see #onProvideStructure
9012     * @see #onProvideVirtualStructure
9013     * @attr ref android.R.styleable#View_assistBlocked
9014     */
9015    public void setAssistBlocked(boolean enabled) {
9016        if (enabled) {
9017            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9018        } else {
9019            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9020        }
9021    }
9022
9023    /**
9024     * Indicates whether this view will save its state (that is,
9025     * whether its {@link #onSaveInstanceState} method will be called).
9026     *
9027     * @return Returns true if the view state saving is enabled, else false.
9028     *
9029     * @see #setSaveEnabled(boolean)
9030     * @attr ref android.R.styleable#View_saveEnabled
9031     */
9032    public boolean isSaveEnabled() {
9033        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9034    }
9035
9036    /**
9037     * Controls whether the saving of this view's state is
9038     * enabled (that is, whether its {@link #onSaveInstanceState} method
9039     * will be called).  Note that even if freezing is enabled, the
9040     * view still must have an id assigned to it (via {@link #setId(int)})
9041     * for its state to be saved.  This flag can only disable the
9042     * saving of this view; any child views may still have their state saved.
9043     *
9044     * @param enabled Set to false to <em>disable</em> state saving, or true
9045     * (the default) to allow it.
9046     *
9047     * @see #isSaveEnabled()
9048     * @see #setId(int)
9049     * @see #onSaveInstanceState()
9050     * @attr ref android.R.styleable#View_saveEnabled
9051     */
9052    public void setSaveEnabled(boolean enabled) {
9053        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
9054    }
9055
9056    /**
9057     * Gets whether the framework should discard touches when the view's
9058     * window is obscured by another visible window.
9059     * Refer to the {@link View} security documentation for more details.
9060     *
9061     * @return True if touch filtering is enabled.
9062     *
9063     * @see #setFilterTouchesWhenObscured(boolean)
9064     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9065     */
9066    @ViewDebug.ExportedProperty
9067    public boolean getFilterTouchesWhenObscured() {
9068        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
9069    }
9070
9071    /**
9072     * Sets whether the framework should discard touches when the view's
9073     * window is obscured by another visible window.
9074     * Refer to the {@link View} security documentation for more details.
9075     *
9076     * @param enabled True if touch filtering should be enabled.
9077     *
9078     * @see #getFilterTouchesWhenObscured
9079     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9080     */
9081    public void setFilterTouchesWhenObscured(boolean enabled) {
9082        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
9083                FILTER_TOUCHES_WHEN_OBSCURED);
9084    }
9085
9086    /**
9087     * Indicates whether the entire hierarchy under this view will save its
9088     * state when a state saving traversal occurs from its parent.  The default
9089     * is true; if false, these views will not be saved unless
9090     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9091     *
9092     * @return Returns true if the view state saving from parent is enabled, else false.
9093     *
9094     * @see #setSaveFromParentEnabled(boolean)
9095     */
9096    public boolean isSaveFromParentEnabled() {
9097        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
9098    }
9099
9100    /**
9101     * Controls whether the entire hierarchy under this view will save its
9102     * state when a state saving traversal occurs from its parent.  The default
9103     * is true; if false, these views will not be saved unless
9104     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9105     *
9106     * @param enabled Set to false to <em>disable</em> state saving, or true
9107     * (the default) to allow it.
9108     *
9109     * @see #isSaveFromParentEnabled()
9110     * @see #setId(int)
9111     * @see #onSaveInstanceState()
9112     */
9113    public void setSaveFromParentEnabled(boolean enabled) {
9114        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
9115    }
9116
9117
9118    /**
9119     * Returns whether this View is currently able to take focus.
9120     *
9121     * @return True if this view can take focus, or false otherwise.
9122     */
9123    @ViewDebug.ExportedProperty(category = "focus")
9124    public final boolean isFocusable() {
9125        return FOCUSABLE == (mViewFlags & FOCUSABLE);
9126    }
9127
9128    /**
9129     * Returns the focusable setting for this view.
9130     *
9131     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
9132     * @attr ref android.R.styleable#View_focusable
9133     */
9134    @ViewDebug.ExportedProperty(mapping = {
9135            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
9136            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
9137            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
9138            })
9139    @Focusable
9140    public int getFocusable() {
9141        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
9142    }
9143
9144    /**
9145     * When a view is focusable, it may not want to take focus when in touch mode.
9146     * For example, a button would like focus when the user is navigating via a D-pad
9147     * so that the user can click on it, but once the user starts touching the screen,
9148     * the button shouldn't take focus
9149     * @return Whether the view is focusable in touch mode.
9150     * @attr ref android.R.styleable#View_focusableInTouchMode
9151     */
9152    @ViewDebug.ExportedProperty
9153    public final boolean isFocusableInTouchMode() {
9154        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
9155    }
9156
9157    /**
9158     * Find the nearest view in the specified direction that can take focus.
9159     * This does not actually give focus to that view.
9160     *
9161     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9162     *
9163     * @return The nearest focusable in the specified direction, or null if none
9164     *         can be found.
9165     */
9166    public View focusSearch(@FocusRealDirection int direction) {
9167        if (mParent != null) {
9168            return mParent.focusSearch(this, direction);
9169        } else {
9170            return null;
9171        }
9172    }
9173
9174    /**
9175     * Returns whether this View is a root of a keyboard navigation cluster.
9176     *
9177     * @return True if this view is a root of a cluster, or false otherwise.
9178     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9179     */
9180    @ViewDebug.ExportedProperty(category = "keyboardNavigationCluster")
9181    public final boolean isKeyboardNavigationCluster() {
9182        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
9183    }
9184
9185    /**
9186     * Set whether this view is a root of a keyboard navigation cluster.
9187     *
9188     * @param isCluster If true, this view is a root of a cluster.
9189     *
9190     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9191     */
9192    public void setKeyboardNavigationCluster(boolean isCluster) {
9193        if (isCluster) {
9194            mPrivateFlags3 |= PFLAG3_CLUSTER;
9195        } else {
9196            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
9197        }
9198    }
9199
9200    /**
9201     * Returns whether this View should receive focus when the focus is restored for the view
9202     * hierarchy containing this view.
9203     * <p>
9204     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9205     * window or serves as a target of cluster navigation.
9206     *
9207     * @see #restoreDefaultFocus(int)
9208     *
9209     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
9210     * @attr ref android.R.styleable#View_focusedByDefault
9211     */
9212    @ViewDebug.ExportedProperty(category = "focusedByDefault")
9213    public final boolean isFocusedByDefault() {
9214        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
9215    }
9216
9217    /**
9218     * Sets whether this View should receive focus when the focus is restored for the view
9219     * hierarchy containing this view.
9220     * <p>
9221     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9222     * window or serves as a target of cluster navigation.
9223     *
9224     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
9225     *                           {@code false} otherwise.
9226     *
9227     * @see #restoreDefaultFocus(int)
9228     *
9229     * @attr ref android.R.styleable#View_focusedByDefault
9230     */
9231    public void setFocusedByDefault(boolean isFocusedByDefault) {
9232        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
9233            return;
9234        }
9235
9236        if (isFocusedByDefault) {
9237            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
9238        } else {
9239            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
9240        }
9241
9242        if (mParent instanceof ViewGroup) {
9243            if (isFocusedByDefault) {
9244                ((ViewGroup) mParent).setDefaultFocus(this);
9245            } else {
9246                ((ViewGroup) mParent).cleanDefaultFocus(this);
9247            }
9248        }
9249    }
9250
9251    /**
9252     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
9253     *
9254     * @return {@code true} if this view has default focus, {@code false} otherwise
9255     */
9256    boolean hasDefaultFocus() {
9257        return isFocusedByDefault();
9258    }
9259
9260    /**
9261     * Find the nearest keyboard navigation cluster in the specified direction.
9262     * This does not actually give focus to that cluster.
9263     *
9264     * @param currentCluster The starting point of the search. Null means the current cluster is not
9265     *                       found yet
9266     * @param direction Direction to look
9267     *
9268     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
9269     *         can be found
9270     */
9271    public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
9272        if (isKeyboardNavigationCluster()) {
9273            currentCluster = this;
9274        }
9275        if (isRootNamespace()) {
9276            // Root namespace means we should consider ourselves the top of the
9277            // tree for group searching; otherwise we could be group searching
9278            // into other tabs.  see LocalActivityManager and TabHost for more info.
9279            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
9280                    this, currentCluster, direction);
9281        } else if (mParent != null) {
9282            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
9283        }
9284        return null;
9285    }
9286
9287    /**
9288     * This method is the last chance for the focused view and its ancestors to
9289     * respond to an arrow key. This is called when the focused view did not
9290     * consume the key internally, nor could the view system find a new view in
9291     * the requested direction to give focus to.
9292     *
9293     * @param focused The currently focused view.
9294     * @param direction The direction focus wants to move. One of FOCUS_UP,
9295     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
9296     * @return True if the this view consumed this unhandled move.
9297     */
9298    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
9299        return false;
9300    }
9301
9302    /**
9303     * If a user manually specified the next view id for a particular direction,
9304     * use the root to look up the view.
9305     * @param root The root view of the hierarchy containing this view.
9306     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
9307     * or FOCUS_BACKWARD.
9308     * @return The user specified next view, or null if there is none.
9309     */
9310    View findUserSetNextFocus(View root, @FocusDirection int direction) {
9311        switch (direction) {
9312            case FOCUS_LEFT:
9313                if (mNextFocusLeftId == View.NO_ID) return null;
9314                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
9315            case FOCUS_RIGHT:
9316                if (mNextFocusRightId == View.NO_ID) return null;
9317                return findViewInsideOutShouldExist(root, mNextFocusRightId);
9318            case FOCUS_UP:
9319                if (mNextFocusUpId == View.NO_ID) return null;
9320                return findViewInsideOutShouldExist(root, mNextFocusUpId);
9321            case FOCUS_DOWN:
9322                if (mNextFocusDownId == View.NO_ID) return null;
9323                return findViewInsideOutShouldExist(root, mNextFocusDownId);
9324            case FOCUS_FORWARD:
9325                if (mNextFocusForwardId == View.NO_ID) return null;
9326                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
9327            case FOCUS_BACKWARD: {
9328                if (mID == View.NO_ID) return null;
9329                final int id = mID;
9330                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
9331                    @Override
9332                    public boolean apply(View t) {
9333                        return t.mNextFocusForwardId == id;
9334                    }
9335                });
9336            }
9337        }
9338        return null;
9339    }
9340
9341    private View findViewInsideOutShouldExist(View root, int id) {
9342        if (mMatchIdPredicate == null) {
9343            mMatchIdPredicate = new MatchIdPredicate();
9344        }
9345        mMatchIdPredicate.mId = id;
9346        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
9347        if (result == null) {
9348            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
9349        }
9350        return result;
9351    }
9352
9353    /**
9354     * Find and return all focusable views that are descendants of this view,
9355     * possibly including this view if it is focusable itself.
9356     *
9357     * @param direction The direction of the focus
9358     * @return A list of focusable views
9359     */
9360    public ArrayList<View> getFocusables(@FocusDirection int direction) {
9361        ArrayList<View> result = new ArrayList<View>(24);
9362        addFocusables(result, direction);
9363        return result;
9364    }
9365
9366    /**
9367     * Add any focusable views that are descendants of this view (possibly
9368     * including this view if it is focusable itself) to views.  If we are in touch mode,
9369     * only add views that are also focusable in touch mode.
9370     *
9371     * @param views Focusable views found so far
9372     * @param direction The direction of the focus
9373     */
9374    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
9375        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
9376    }
9377
9378    /**
9379     * Adds any focusable views that are descendants of this view (possibly
9380     * including this view if it is focusable itself) to views. This method
9381     * adds all focusable views regardless if we are in touch mode or
9382     * only views focusable in touch mode if we are in touch mode or
9383     * only views that can take accessibility focus if accessibility is enabled
9384     * depending on the focusable mode parameter.
9385     *
9386     * @param views Focusable views found so far or null if all we are interested is
9387     *        the number of focusables.
9388     * @param direction The direction of the focus.
9389     * @param focusableMode The type of focusables to be added.
9390     *
9391     * @see #FOCUSABLES_ALL
9392     * @see #FOCUSABLES_TOUCH_MODE
9393     */
9394    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
9395            @FocusableMode int focusableMode) {
9396        if (views == null) {
9397            return;
9398        }
9399        if (!isFocusable()) {
9400            return;
9401        }
9402        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
9403                && !isFocusableInTouchMode()) {
9404            return;
9405        }
9406        views.add(this);
9407    }
9408
9409    /**
9410     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
9411     * including this view if it is a cluster root itself) to views.
9412     *
9413     * @param views Keyboard navigation cluster roots found so far
9414     * @param direction Direction to look
9415     */
9416    public void addKeyboardNavigationClusters(
9417            @NonNull Collection<View> views,
9418            int direction) {
9419        if (!(isKeyboardNavigationCluster())) {
9420            return;
9421        }
9422        views.add(this);
9423    }
9424
9425    /**
9426     * Finds the Views that contain given text. The containment is case insensitive.
9427     * The search is performed by either the text that the View renders or the content
9428     * description that describes the view for accessibility purposes and the view does
9429     * not render or both. Clients can specify how the search is to be performed via
9430     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
9431     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
9432     *
9433     * @param outViews The output list of matching Views.
9434     * @param searched The text to match against.
9435     *
9436     * @see #FIND_VIEWS_WITH_TEXT
9437     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
9438     * @see #setContentDescription(CharSequence)
9439     */
9440    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
9441            @FindViewFlags int flags) {
9442        if (getAccessibilityNodeProvider() != null) {
9443            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
9444                outViews.add(this);
9445            }
9446        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
9447                && (searched != null && searched.length() > 0)
9448                && (mContentDescription != null && mContentDescription.length() > 0)) {
9449            String searchedLowerCase = searched.toString().toLowerCase();
9450            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
9451            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
9452                outViews.add(this);
9453            }
9454        }
9455    }
9456
9457    /**
9458     * Find and return all touchable views that are descendants of this view,
9459     * possibly including this view if it is touchable itself.
9460     *
9461     * @return A list of touchable views
9462     */
9463    public ArrayList<View> getTouchables() {
9464        ArrayList<View> result = new ArrayList<View>();
9465        addTouchables(result);
9466        return result;
9467    }
9468
9469    /**
9470     * Add any touchable views that are descendants of this view (possibly
9471     * including this view if it is touchable itself) to views.
9472     *
9473     * @param views Touchable views found so far
9474     */
9475    public void addTouchables(ArrayList<View> views) {
9476        final int viewFlags = mViewFlags;
9477
9478        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
9479                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
9480                && (viewFlags & ENABLED_MASK) == ENABLED) {
9481            views.add(this);
9482        }
9483    }
9484
9485    /**
9486     * Returns whether this View is accessibility focused.
9487     *
9488     * @return True if this View is accessibility focused.
9489     */
9490    public boolean isAccessibilityFocused() {
9491        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
9492    }
9493
9494    /**
9495     * Call this to try to give accessibility focus to this view.
9496     *
9497     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
9498     * returns false or the view is no visible or the view already has accessibility
9499     * focus.
9500     *
9501     * See also {@link #focusSearch(int)}, which is what you call to say that you
9502     * have focus, and you want your parent to look for the next one.
9503     *
9504     * @return Whether this view actually took accessibility focus.
9505     *
9506     * @hide
9507     */
9508    public boolean requestAccessibilityFocus() {
9509        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
9510        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
9511            return false;
9512        }
9513        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9514            return false;
9515        }
9516        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
9517            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
9518            ViewRootImpl viewRootImpl = getViewRootImpl();
9519            if (viewRootImpl != null) {
9520                viewRootImpl.setAccessibilityFocus(this, null);
9521            }
9522            invalidate();
9523            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
9524            return true;
9525        }
9526        return false;
9527    }
9528
9529    /**
9530     * Call this to try to clear accessibility focus of this view.
9531     *
9532     * See also {@link #focusSearch(int)}, which is what you call to say that you
9533     * have focus, and you want your parent to look for the next one.
9534     *
9535     * @hide
9536     */
9537    public void clearAccessibilityFocus() {
9538        clearAccessibilityFocusNoCallbacks(0);
9539
9540        // Clear the global reference of accessibility focus if this view or
9541        // any of its descendants had accessibility focus. This will NOT send
9542        // an event or update internal state if focus is cleared from a
9543        // descendant view, which may leave views in inconsistent states.
9544        final ViewRootImpl viewRootImpl = getViewRootImpl();
9545        if (viewRootImpl != null) {
9546            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
9547            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9548                viewRootImpl.setAccessibilityFocus(null, null);
9549            }
9550        }
9551    }
9552
9553    private void sendAccessibilityHoverEvent(int eventType) {
9554        // Since we are not delivering to a client accessibility events from not
9555        // important views (unless the clinet request that) we need to fire the
9556        // event from the deepest view exposed to the client. As a consequence if
9557        // the user crosses a not exposed view the client will see enter and exit
9558        // of the exposed predecessor followed by and enter and exit of that same
9559        // predecessor when entering and exiting the not exposed descendant. This
9560        // is fine since the client has a clear idea which view is hovered at the
9561        // price of a couple more events being sent. This is a simple and
9562        // working solution.
9563        View source = this;
9564        while (true) {
9565            if (source.includeForAccessibility()) {
9566                source.sendAccessibilityEvent(eventType);
9567                return;
9568            }
9569            ViewParent parent = source.getParent();
9570            if (parent instanceof View) {
9571                source = (View) parent;
9572            } else {
9573                return;
9574            }
9575        }
9576    }
9577
9578    /**
9579     * Clears accessibility focus without calling any callback methods
9580     * normally invoked in {@link #clearAccessibilityFocus()}. This method
9581     * is used separately from that one for clearing accessibility focus when
9582     * giving this focus to another view.
9583     *
9584     * @param action The action, if any, that led to focus being cleared. Set to
9585     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
9586     * the window.
9587     */
9588    void clearAccessibilityFocusNoCallbacks(int action) {
9589        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
9590            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
9591            invalidate();
9592            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9593                AccessibilityEvent event = AccessibilityEvent.obtain(
9594                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
9595                event.setAction(action);
9596                if (mAccessibilityDelegate != null) {
9597                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
9598                } else {
9599                    sendAccessibilityEventUnchecked(event);
9600                }
9601            }
9602        }
9603    }
9604
9605    /**
9606     * Call this to try to give focus to a specific view or to one of its
9607     * descendants.
9608     *
9609     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9610     * false), or if it is focusable and it is not focusable in touch mode
9611     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9612     *
9613     * See also {@link #focusSearch(int)}, which is what you call to say that you
9614     * have focus, and you want your parent to look for the next one.
9615     *
9616     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
9617     * {@link #FOCUS_DOWN} and <code>null</code>.
9618     *
9619     * @return Whether this view or one of its descendants actually took focus.
9620     */
9621    public final boolean requestFocus() {
9622        return requestFocus(View.FOCUS_DOWN);
9623    }
9624
9625    /**
9626     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
9627     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
9628     * Nested keyboard navigation clusters are excluded from the hierarchy.
9629     *
9630     * @param direction The direction of the focus
9631     * @return Whether this view or one of its descendants actually took focus
9632     */
9633    public boolean restoreDefaultFocus(@FocusDirection int direction) {
9634        return requestFocus(direction);
9635    }
9636
9637    /**
9638     * Call this to try to give focus to a specific view or to one of its
9639     * descendants and give it a hint about what direction focus is heading.
9640     *
9641     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9642     * false), or if it is focusable and it is not focusable in touch mode
9643     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9644     *
9645     * See also {@link #focusSearch(int)}, which is what you call to say that you
9646     * have focus, and you want your parent to look for the next one.
9647     *
9648     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
9649     * <code>null</code> set for the previously focused rectangle.
9650     *
9651     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9652     * @return Whether this view or one of its descendants actually took focus.
9653     */
9654    public final boolean requestFocus(int direction) {
9655        return requestFocus(direction, null);
9656    }
9657
9658    /**
9659     * Call this to try to give focus to a specific view or to one of its descendants
9660     * and give it hints about the direction and a specific rectangle that the focus
9661     * is coming from.  The rectangle can help give larger views a finer grained hint
9662     * about where focus is coming from, and therefore, where to show selection, or
9663     * forward focus change internally.
9664     *
9665     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9666     * false), or if it is focusable and it is not focusable in touch mode
9667     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9668     *
9669     * A View will not take focus if it is not visible.
9670     *
9671     * A View will not take focus if one of its parents has
9672     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
9673     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
9674     *
9675     * See also {@link #focusSearch(int)}, which is what you call to say that you
9676     * have focus, and you want your parent to look for the next one.
9677     *
9678     * You may wish to override this method if your custom {@link View} has an internal
9679     * {@link View} that it wishes to forward the request to.
9680     *
9681     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9682     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
9683     *        to give a finer grained hint about where focus is coming from.  May be null
9684     *        if there is no hint.
9685     * @return Whether this view or one of its descendants actually took focus.
9686     */
9687    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
9688        return requestFocusNoSearch(direction, previouslyFocusedRect);
9689    }
9690
9691    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
9692        // need to be focusable
9693        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
9694                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9695            return false;
9696        }
9697
9698        // need to be focusable in touch mode if in touch mode
9699        if (isInTouchMode() &&
9700            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
9701               return false;
9702        }
9703
9704        // need to not have any parents blocking us
9705        if (hasAncestorThatBlocksDescendantFocus()) {
9706            return false;
9707        }
9708
9709        handleFocusGainInternal(direction, previouslyFocusedRect);
9710        return true;
9711    }
9712
9713    /**
9714     * Call this to try to give focus to a specific view or to one of its descendants. This is a
9715     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
9716     * touch mode to request focus when they are touched.
9717     *
9718     * @return Whether this view or one of its descendants actually took focus.
9719     *
9720     * @see #isInTouchMode()
9721     *
9722     */
9723    public final boolean requestFocusFromTouch() {
9724        // Leave touch mode if we need to
9725        if (isInTouchMode()) {
9726            ViewRootImpl viewRoot = getViewRootImpl();
9727            if (viewRoot != null) {
9728                viewRoot.ensureTouchMode(false);
9729            }
9730        }
9731        return requestFocus(View.FOCUS_DOWN);
9732    }
9733
9734    /**
9735     * @return Whether any ancestor of this view blocks descendant focus.
9736     */
9737    private boolean hasAncestorThatBlocksDescendantFocus() {
9738        final boolean focusableInTouchMode = isFocusableInTouchMode();
9739        ViewParent ancestor = mParent;
9740        while (ancestor instanceof ViewGroup) {
9741            final ViewGroup vgAncestor = (ViewGroup) ancestor;
9742            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
9743                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
9744                return true;
9745            } else {
9746                ancestor = vgAncestor.getParent();
9747            }
9748        }
9749        return false;
9750    }
9751
9752    /**
9753     * Gets the mode for determining whether this View is important for accessibility.
9754     * A view is important for accessibility if it fires accessibility events and if it
9755     * is reported to accessibility services that query the screen.
9756     *
9757     * @return The mode for determining whether a view is important for accessibility, one
9758     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
9759     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
9760     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
9761     *
9762     * @attr ref android.R.styleable#View_importantForAccessibility
9763     *
9764     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9765     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9766     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9767     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9768     */
9769    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
9770            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
9771            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
9772            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
9773            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
9774                    to = "noHideDescendants")
9775        })
9776    public int getImportantForAccessibility() {
9777        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9778                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9779    }
9780
9781    /**
9782     * Sets the live region mode for this view. This indicates to accessibility
9783     * services whether they should automatically notify the user about changes
9784     * to the view's content description or text, or to the content descriptions
9785     * or text of the view's children (where applicable).
9786     * <p>
9787     * For example, in a login screen with a TextView that displays an "incorrect
9788     * password" notification, that view should be marked as a live region with
9789     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9790     * <p>
9791     * To disable change notifications for this view, use
9792     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
9793     * mode for most views.
9794     * <p>
9795     * To indicate that the user should be notified of changes, use
9796     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9797     * <p>
9798     * If the view's changes should interrupt ongoing speech and notify the user
9799     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
9800     *
9801     * @param mode The live region mode for this view, one of:
9802     *        <ul>
9803     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
9804     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
9805     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
9806     *        </ul>
9807     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9808     */
9809    public void setAccessibilityLiveRegion(int mode) {
9810        if (mode != getAccessibilityLiveRegion()) {
9811            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9812            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
9813                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9814            notifyViewAccessibilityStateChangedIfNeeded(
9815                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9816        }
9817    }
9818
9819    /**
9820     * Gets the live region mode for this View.
9821     *
9822     * @return The live region mode for the view.
9823     *
9824     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9825     *
9826     * @see #setAccessibilityLiveRegion(int)
9827     */
9828    public int getAccessibilityLiveRegion() {
9829        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
9830                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
9831    }
9832
9833    /**
9834     * Sets how to determine whether this view is important for accessibility
9835     * which is if it fires accessibility events and if it is reported to
9836     * accessibility services that query the screen.
9837     *
9838     * @param mode How to determine whether this view is important for accessibility.
9839     *
9840     * @attr ref android.R.styleable#View_importantForAccessibility
9841     *
9842     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9843     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9844     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9845     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9846     */
9847    public void setImportantForAccessibility(int mode) {
9848        final int oldMode = getImportantForAccessibility();
9849        if (mode != oldMode) {
9850            final boolean hideDescendants =
9851                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
9852
9853            // If this node or its descendants are no longer important, try to
9854            // clear accessibility focus.
9855            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
9856                final View focusHost = findAccessibilityFocusHost(hideDescendants);
9857                if (focusHost != null) {
9858                    focusHost.clearAccessibilityFocus();
9859                }
9860            }
9861
9862            // If we're moving between AUTO and another state, we might not need
9863            // to send a subtree changed notification. We'll store the computed
9864            // importance, since we'll need to check it later to make sure.
9865            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
9866                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
9867            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
9868            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9869            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
9870                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9871            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
9872                notifySubtreeAccessibilityStateChangedIfNeeded();
9873            } else {
9874                notifyViewAccessibilityStateChangedIfNeeded(
9875                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9876            }
9877        }
9878    }
9879
9880    /**
9881     * Returns the view within this view's hierarchy that is hosting
9882     * accessibility focus.
9883     *
9884     * @param searchDescendants whether to search for focus in descendant views
9885     * @return the view hosting accessibility focus, or {@code null}
9886     */
9887    private View findAccessibilityFocusHost(boolean searchDescendants) {
9888        if (isAccessibilityFocusedViewOrHost()) {
9889            return this;
9890        }
9891
9892        if (searchDescendants) {
9893            final ViewRootImpl viewRoot = getViewRootImpl();
9894            if (viewRoot != null) {
9895                final View focusHost = viewRoot.getAccessibilityFocusedHost();
9896                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9897                    return focusHost;
9898                }
9899            }
9900        }
9901
9902        return null;
9903    }
9904
9905    /**
9906     * Computes whether this view should be exposed for accessibility. In
9907     * general, views that are interactive or provide information are exposed
9908     * while views that serve only as containers are hidden.
9909     * <p>
9910     * If an ancestor of this view has importance
9911     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
9912     * returns <code>false</code>.
9913     * <p>
9914     * Otherwise, the value is computed according to the view's
9915     * {@link #getImportantForAccessibility()} value:
9916     * <ol>
9917     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
9918     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
9919     * </code>
9920     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
9921     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
9922     * view satisfies any of the following:
9923     * <ul>
9924     * <li>Is actionable, e.g. {@link #isClickable()},
9925     * {@link #isLongClickable()}, or {@link #isFocusable()}
9926     * <li>Has an {@link AccessibilityDelegate}
9927     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
9928     * {@link OnKeyListener}, etc.
9929     * <li>Is an accessibility live region, e.g.
9930     * {@link #getAccessibilityLiveRegion()} is not
9931     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
9932     * </ul>
9933     * </ol>
9934     *
9935     * @return Whether the view is exposed for accessibility.
9936     * @see #setImportantForAccessibility(int)
9937     * @see #getImportantForAccessibility()
9938     */
9939    public boolean isImportantForAccessibility() {
9940        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9941                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9942        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
9943                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9944            return false;
9945        }
9946
9947        // Check parent mode to ensure we're not hidden.
9948        ViewParent parent = mParent;
9949        while (parent instanceof View) {
9950            if (((View) parent).getImportantForAccessibility()
9951                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
9952                return false;
9953            }
9954            parent = parent.getParent();
9955        }
9956
9957        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
9958                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
9959                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
9960    }
9961
9962    /**
9963     * Gets the parent for accessibility purposes. Note that the parent for
9964     * accessibility is not necessary the immediate parent. It is the first
9965     * predecessor that is important for accessibility.
9966     *
9967     * @return The parent for accessibility purposes.
9968     */
9969    public ViewParent getParentForAccessibility() {
9970        if (mParent instanceof View) {
9971            View parentView = (View) mParent;
9972            if (parentView.includeForAccessibility()) {
9973                return mParent;
9974            } else {
9975                return mParent.getParentForAccessibility();
9976            }
9977        }
9978        return null;
9979    }
9980
9981    /**
9982     * Adds the children of this View relevant for accessibility to the given list
9983     * as output. Since some Views are not important for accessibility the added
9984     * child views are not necessarily direct children of this view, rather they are
9985     * the first level of descendants important for accessibility.
9986     *
9987     * @param outChildren The output list that will receive children for accessibility.
9988     */
9989    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
9990
9991    }
9992
9993    /**
9994     * Whether to regard this view for accessibility. A view is regarded for
9995     * accessibility if it is important for accessibility or the querying
9996     * accessibility service has explicitly requested that view not
9997     * important for accessibility are regarded.
9998     *
9999     * @return Whether to regard the view for accessibility.
10000     *
10001     * @hide
10002     */
10003    public boolean includeForAccessibility() {
10004        if (mAttachInfo != null) {
10005            return (mAttachInfo.mAccessibilityFetchFlags
10006                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
10007                    || isImportantForAccessibility();
10008        }
10009        return false;
10010    }
10011
10012    /**
10013     * Returns whether the View is considered actionable from
10014     * accessibility perspective. Such view are important for
10015     * accessibility.
10016     *
10017     * @return True if the view is actionable for accessibility.
10018     *
10019     * @hide
10020     */
10021    public boolean isActionableForAccessibility() {
10022        return (isClickable() || isLongClickable() || isFocusable());
10023    }
10024
10025    /**
10026     * Returns whether the View has registered callbacks which makes it
10027     * important for accessibility.
10028     *
10029     * @return True if the view is actionable for accessibility.
10030     */
10031    private boolean hasListenersForAccessibility() {
10032        ListenerInfo info = getListenerInfo();
10033        return mTouchDelegate != null || info.mOnKeyListener != null
10034                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
10035                || info.mOnHoverListener != null || info.mOnDragListener != null;
10036    }
10037
10038    /**
10039     * Notifies that the accessibility state of this view changed. The change
10040     * is local to this view and does not represent structural changes such
10041     * as children and parent. For example, the view became focusable. The
10042     * notification is at at most once every
10043     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10044     * to avoid unnecessary load to the system. Also once a view has a pending
10045     * notification this method is a NOP until the notification has been sent.
10046     *
10047     * @hide
10048     */
10049    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
10050        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10051            return;
10052        }
10053        if (mSendViewStateChangedAccessibilityEvent == null) {
10054            mSendViewStateChangedAccessibilityEvent =
10055                    new SendViewStateChangedAccessibilityEvent();
10056        }
10057        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
10058    }
10059
10060    /**
10061     * Notifies that the accessibility state of this view changed. The change
10062     * is *not* local to this view and does represent structural changes such
10063     * as children and parent. For example, the view size changed. The
10064     * notification is at at most once every
10065     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10066     * to avoid unnecessary load to the system. Also once a view has a pending
10067     * notification this method is a NOP until the notification has been sent.
10068     *
10069     * @hide
10070     */
10071    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
10072        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10073            return;
10074        }
10075        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
10076            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10077            if (mParent != null) {
10078                try {
10079                    mParent.notifySubtreeAccessibilityStateChanged(
10080                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
10081                } catch (AbstractMethodError e) {
10082                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
10083                            " does not fully implement ViewParent", e);
10084                }
10085            }
10086        }
10087    }
10088
10089    /**
10090     * Change the visibility of the View without triggering any other changes. This is
10091     * important for transitions, where visibility changes should not adjust focus or
10092     * trigger a new layout. This is only used when the visibility has already been changed
10093     * and we need a transient value during an animation. When the animation completes,
10094     * the original visibility value is always restored.
10095     *
10096     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
10097     * @hide
10098     */
10099    public void setTransitionVisibility(@Visibility int visibility) {
10100        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
10101    }
10102
10103    /**
10104     * Reset the flag indicating the accessibility state of the subtree rooted
10105     * at this view changed.
10106     */
10107    void resetSubtreeAccessibilityStateChanged() {
10108        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10109    }
10110
10111    /**
10112     * Report an accessibility action to this view's parents for delegated processing.
10113     *
10114     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
10115     * call this method to delegate an accessibility action to a supporting parent. If the parent
10116     * returns true from its
10117     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
10118     * method this method will return true to signify that the action was consumed.</p>
10119     *
10120     * <p>This method is useful for implementing nested scrolling child views. If
10121     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
10122     * a custom view implementation may invoke this method to allow a parent to consume the
10123     * scroll first. If this method returns true the custom view should skip its own scrolling
10124     * behavior.</p>
10125     *
10126     * @param action Accessibility action to delegate
10127     * @param arguments Optional action arguments
10128     * @return true if the action was consumed by a parent
10129     */
10130    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
10131        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
10132            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
10133                return true;
10134            }
10135        }
10136        return false;
10137    }
10138
10139    /**
10140     * Performs the specified accessibility action on the view. For
10141     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
10142     * <p>
10143     * If an {@link AccessibilityDelegate} has been specified via calling
10144     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10145     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
10146     * is responsible for handling this call.
10147     * </p>
10148     *
10149     * <p>The default implementation will delegate
10150     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
10151     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
10152     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
10153     *
10154     * @param action The action to perform.
10155     * @param arguments Optional action arguments.
10156     * @return Whether the action was performed.
10157     */
10158    public boolean performAccessibilityAction(int action, Bundle arguments) {
10159      if (mAccessibilityDelegate != null) {
10160          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
10161      } else {
10162          return performAccessibilityActionInternal(action, arguments);
10163      }
10164    }
10165
10166   /**
10167    * @see #performAccessibilityAction(int, Bundle)
10168    *
10169    * Note: Called from the default {@link AccessibilityDelegate}.
10170    *
10171    * @hide
10172    */
10173    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
10174        if (isNestedScrollingEnabled()
10175                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
10176                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
10177                || action == R.id.accessibilityActionScrollUp
10178                || action == R.id.accessibilityActionScrollLeft
10179                || action == R.id.accessibilityActionScrollDown
10180                || action == R.id.accessibilityActionScrollRight)) {
10181            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
10182                return true;
10183            }
10184        }
10185
10186        switch (action) {
10187            case AccessibilityNodeInfo.ACTION_CLICK: {
10188                if (isClickable()) {
10189                    performClick();
10190                    return true;
10191                }
10192            } break;
10193            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
10194                if (isLongClickable()) {
10195                    performLongClick();
10196                    return true;
10197                }
10198            } break;
10199            case AccessibilityNodeInfo.ACTION_FOCUS: {
10200                if (!hasFocus()) {
10201                    // Get out of touch mode since accessibility
10202                    // wants to move focus around.
10203                    getViewRootImpl().ensureTouchMode(false);
10204                    return requestFocus();
10205                }
10206            } break;
10207            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
10208                if (hasFocus()) {
10209                    clearFocus();
10210                    return !isFocused();
10211                }
10212            } break;
10213            case AccessibilityNodeInfo.ACTION_SELECT: {
10214                if (!isSelected()) {
10215                    setSelected(true);
10216                    return isSelected();
10217                }
10218            } break;
10219            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
10220                if (isSelected()) {
10221                    setSelected(false);
10222                    return !isSelected();
10223                }
10224            } break;
10225            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
10226                if (!isAccessibilityFocused()) {
10227                    return requestAccessibilityFocus();
10228                }
10229            } break;
10230            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
10231                if (isAccessibilityFocused()) {
10232                    clearAccessibilityFocus();
10233                    return true;
10234                }
10235            } break;
10236            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
10237                if (arguments != null) {
10238                    final int granularity = arguments.getInt(
10239                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10240                    final boolean extendSelection = arguments.getBoolean(
10241                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10242                    return traverseAtGranularity(granularity, true, extendSelection);
10243                }
10244            } break;
10245            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
10246                if (arguments != null) {
10247                    final int granularity = arguments.getInt(
10248                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10249                    final boolean extendSelection = arguments.getBoolean(
10250                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10251                    return traverseAtGranularity(granularity, false, extendSelection);
10252                }
10253            } break;
10254            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
10255                CharSequence text = getIterableTextForAccessibility();
10256                if (text == null) {
10257                    return false;
10258                }
10259                final int start = (arguments != null) ? arguments.getInt(
10260                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
10261                final int end = (arguments != null) ? arguments.getInt(
10262                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
10263                // Only cursor position can be specified (selection length == 0)
10264                if ((getAccessibilitySelectionStart() != start
10265                        || getAccessibilitySelectionEnd() != end)
10266                        && (start == end)) {
10267                    setAccessibilitySelection(start, end);
10268                    notifyViewAccessibilityStateChangedIfNeeded(
10269                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10270                    return true;
10271                }
10272            } break;
10273            case R.id.accessibilityActionShowOnScreen: {
10274                if (mAttachInfo != null) {
10275                    final Rect r = mAttachInfo.mTmpInvalRect;
10276                    getDrawingRect(r);
10277                    return requestRectangleOnScreen(r, true);
10278                }
10279            } break;
10280            case R.id.accessibilityActionContextClick: {
10281                if (isContextClickable()) {
10282                    performContextClick();
10283                    return true;
10284                }
10285            } break;
10286        }
10287        return false;
10288    }
10289
10290    private boolean traverseAtGranularity(int granularity, boolean forward,
10291            boolean extendSelection) {
10292        CharSequence text = getIterableTextForAccessibility();
10293        if (text == null || text.length() == 0) {
10294            return false;
10295        }
10296        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
10297        if (iterator == null) {
10298            return false;
10299        }
10300        int current = getAccessibilitySelectionEnd();
10301        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
10302            current = forward ? 0 : text.length();
10303        }
10304        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
10305        if (range == null) {
10306            return false;
10307        }
10308        final int segmentStart = range[0];
10309        final int segmentEnd = range[1];
10310        int selectionStart;
10311        int selectionEnd;
10312        if (extendSelection && isAccessibilitySelectionExtendable()) {
10313            selectionStart = getAccessibilitySelectionStart();
10314            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
10315                selectionStart = forward ? segmentStart : segmentEnd;
10316            }
10317            selectionEnd = forward ? segmentEnd : segmentStart;
10318        } else {
10319            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
10320        }
10321        setAccessibilitySelection(selectionStart, selectionEnd);
10322        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
10323                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
10324        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
10325        return true;
10326    }
10327
10328    /**
10329     * Gets the text reported for accessibility purposes.
10330     *
10331     * @return The accessibility text.
10332     *
10333     * @hide
10334     */
10335    public CharSequence getIterableTextForAccessibility() {
10336        return getContentDescription();
10337    }
10338
10339    /**
10340     * Gets whether accessibility selection can be extended.
10341     *
10342     * @return If selection is extensible.
10343     *
10344     * @hide
10345     */
10346    public boolean isAccessibilitySelectionExtendable() {
10347        return false;
10348    }
10349
10350    /**
10351     * @hide
10352     */
10353    public int getAccessibilitySelectionStart() {
10354        return mAccessibilityCursorPosition;
10355    }
10356
10357    /**
10358     * @hide
10359     */
10360    public int getAccessibilitySelectionEnd() {
10361        return getAccessibilitySelectionStart();
10362    }
10363
10364    /**
10365     * @hide
10366     */
10367    public void setAccessibilitySelection(int start, int end) {
10368        if (start ==  end && end == mAccessibilityCursorPosition) {
10369            return;
10370        }
10371        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
10372            mAccessibilityCursorPosition = start;
10373        } else {
10374            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
10375        }
10376        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
10377    }
10378
10379    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
10380            int fromIndex, int toIndex) {
10381        if (mParent == null) {
10382            return;
10383        }
10384        AccessibilityEvent event = AccessibilityEvent.obtain(
10385                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
10386        onInitializeAccessibilityEvent(event);
10387        onPopulateAccessibilityEvent(event);
10388        event.setFromIndex(fromIndex);
10389        event.setToIndex(toIndex);
10390        event.setAction(action);
10391        event.setMovementGranularity(granularity);
10392        mParent.requestSendAccessibilityEvent(this, event);
10393    }
10394
10395    /**
10396     * @hide
10397     */
10398    public TextSegmentIterator getIteratorForGranularity(int granularity) {
10399        switch (granularity) {
10400            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
10401                CharSequence text = getIterableTextForAccessibility();
10402                if (text != null && text.length() > 0) {
10403                    CharacterTextSegmentIterator iterator =
10404                        CharacterTextSegmentIterator.getInstance(
10405                                mContext.getResources().getConfiguration().locale);
10406                    iterator.initialize(text.toString());
10407                    return iterator;
10408                }
10409            } break;
10410            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
10411                CharSequence text = getIterableTextForAccessibility();
10412                if (text != null && text.length() > 0) {
10413                    WordTextSegmentIterator iterator =
10414                        WordTextSegmentIterator.getInstance(
10415                                mContext.getResources().getConfiguration().locale);
10416                    iterator.initialize(text.toString());
10417                    return iterator;
10418                }
10419            } break;
10420            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
10421                CharSequence text = getIterableTextForAccessibility();
10422                if (text != null && text.length() > 0) {
10423                    ParagraphTextSegmentIterator iterator =
10424                        ParagraphTextSegmentIterator.getInstance();
10425                    iterator.initialize(text.toString());
10426                    return iterator;
10427                }
10428            } break;
10429        }
10430        return null;
10431    }
10432
10433    /**
10434     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
10435     * and {@link #onFinishTemporaryDetach()}.
10436     *
10437     * <p>This method always returns {@code true} when called directly or indirectly from
10438     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
10439     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
10440     * <ul>
10441     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
10442     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
10443     * </ul>
10444     * </p>
10445     *
10446     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
10447     * and {@link #onFinishTemporaryDetach()}.
10448     */
10449    public final boolean isTemporarilyDetached() {
10450        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
10451    }
10452
10453    /**
10454     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
10455     * a container View.
10456     */
10457    @CallSuper
10458    public void dispatchStartTemporaryDetach() {
10459        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
10460        onStartTemporaryDetach();
10461    }
10462
10463    /**
10464     * This is called when a container is going to temporarily detach a child, with
10465     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
10466     * It will either be followed by {@link #onFinishTemporaryDetach()} or
10467     * {@link #onDetachedFromWindow()} when the container is done.
10468     */
10469    public void onStartTemporaryDetach() {
10470        removeUnsetPressCallback();
10471        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
10472    }
10473
10474    /**
10475     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
10476     * a container View.
10477     */
10478    @CallSuper
10479    public void dispatchFinishTemporaryDetach() {
10480        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
10481        onFinishTemporaryDetach();
10482        if (hasWindowFocus() && hasFocus()) {
10483            InputMethodManager.getInstance().focusIn(this);
10484        }
10485    }
10486
10487    /**
10488     * Called after {@link #onStartTemporaryDetach} when the container is done
10489     * changing the view.
10490     */
10491    public void onFinishTemporaryDetach() {
10492    }
10493
10494    /**
10495     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
10496     * for this view's window.  Returns null if the view is not currently attached
10497     * to the window.  Normally you will not need to use this directly, but
10498     * just use the standard high-level event callbacks like
10499     * {@link #onKeyDown(int, KeyEvent)}.
10500     */
10501    public KeyEvent.DispatcherState getKeyDispatcherState() {
10502        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
10503    }
10504
10505    /**
10506     * Dispatch a key event before it is processed by any input method
10507     * associated with the view hierarchy.  This can be used to intercept
10508     * key events in special situations before the IME consumes them; a
10509     * typical example would be handling the BACK key to update the application's
10510     * UI instead of allowing the IME to see it and close itself.
10511     *
10512     * @param event The key event to be dispatched.
10513     * @return True if the event was handled, false otherwise.
10514     */
10515    public boolean dispatchKeyEventPreIme(KeyEvent event) {
10516        return onKeyPreIme(event.getKeyCode(), event);
10517    }
10518
10519    /**
10520     * Dispatch a key event to the next view on the focus path. This path runs
10521     * from the top of the view tree down to the currently focused view. If this
10522     * view has focus, it will dispatch to itself. Otherwise it will dispatch
10523     * the next node down the focus path. This method also fires any key
10524     * listeners.
10525     *
10526     * @param event The key event to be dispatched.
10527     * @return True if the event was handled, false otherwise.
10528     */
10529    public boolean dispatchKeyEvent(KeyEvent event) {
10530        if (mInputEventConsistencyVerifier != null) {
10531            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
10532        }
10533
10534        // Give any attached key listener a first crack at the event.
10535        //noinspection SimplifiableIfStatement
10536        ListenerInfo li = mListenerInfo;
10537        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
10538                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
10539            return true;
10540        }
10541
10542        if (event.dispatch(this, mAttachInfo != null
10543                ? mAttachInfo.mKeyDispatchState : null, this)) {
10544            return true;
10545        }
10546
10547        if (mInputEventConsistencyVerifier != null) {
10548            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10549        }
10550        return false;
10551    }
10552
10553    /**
10554     * Dispatches a key shortcut event.
10555     *
10556     * @param event The key event to be dispatched.
10557     * @return True if the event was handled by the view, false otherwise.
10558     */
10559    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
10560        return onKeyShortcut(event.getKeyCode(), event);
10561    }
10562
10563    /**
10564     * Pass the touch screen motion event down to the target view, or this
10565     * view if it is the target.
10566     *
10567     * @param event The motion event to be dispatched.
10568     * @return True if the event was handled by the view, false otherwise.
10569     */
10570    public boolean dispatchTouchEvent(MotionEvent event) {
10571        // If the event should be handled by accessibility focus first.
10572        if (event.isTargetAccessibilityFocus()) {
10573            // We don't have focus or no virtual descendant has it, do not handle the event.
10574            if (!isAccessibilityFocusedViewOrHost()) {
10575                return false;
10576            }
10577            // We have focus and got the event, then use normal event dispatch.
10578            event.setTargetAccessibilityFocus(false);
10579        }
10580
10581        boolean result = false;
10582
10583        if (mInputEventConsistencyVerifier != null) {
10584            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
10585        }
10586
10587        final int actionMasked = event.getActionMasked();
10588        if (actionMasked == MotionEvent.ACTION_DOWN) {
10589            // Defensive cleanup for new gesture
10590            stopNestedScroll();
10591        }
10592
10593        if (onFilterTouchEventForSecurity(event)) {
10594            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
10595                result = true;
10596            }
10597            //noinspection SimplifiableIfStatement
10598            ListenerInfo li = mListenerInfo;
10599            if (li != null && li.mOnTouchListener != null
10600                    && (mViewFlags & ENABLED_MASK) == ENABLED
10601                    && li.mOnTouchListener.onTouch(this, event)) {
10602                result = true;
10603            }
10604
10605            if (!result && onTouchEvent(event)) {
10606                result = true;
10607            }
10608        }
10609
10610        if (!result && mInputEventConsistencyVerifier != null) {
10611            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10612        }
10613
10614        // Clean up after nested scrolls if this is the end of a gesture;
10615        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
10616        // of the gesture.
10617        if (actionMasked == MotionEvent.ACTION_UP ||
10618                actionMasked == MotionEvent.ACTION_CANCEL ||
10619                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
10620            stopNestedScroll();
10621        }
10622
10623        return result;
10624    }
10625
10626    boolean isAccessibilityFocusedViewOrHost() {
10627        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
10628                .getAccessibilityFocusedHost() == this);
10629    }
10630
10631    /**
10632     * Filter the touch event to apply security policies.
10633     *
10634     * @param event The motion event to be filtered.
10635     * @return True if the event should be dispatched, false if the event should be dropped.
10636     *
10637     * @see #getFilterTouchesWhenObscured
10638     */
10639    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
10640        //noinspection RedundantIfStatement
10641        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
10642                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
10643            // Window is obscured, drop this touch.
10644            return false;
10645        }
10646        return true;
10647    }
10648
10649    /**
10650     * Pass a trackball motion event down to the focused view.
10651     *
10652     * @param event The motion event to be dispatched.
10653     * @return True if the event was handled by the view, false otherwise.
10654     */
10655    public boolean dispatchTrackballEvent(MotionEvent event) {
10656        if (mInputEventConsistencyVerifier != null) {
10657            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
10658        }
10659
10660        return onTrackballEvent(event);
10661    }
10662
10663    /**
10664     * Dispatch a generic motion event.
10665     * <p>
10666     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10667     * are delivered to the view under the pointer.  All other generic motion events are
10668     * delivered to the focused view.  Hover events are handled specially and are delivered
10669     * to {@link #onHoverEvent(MotionEvent)}.
10670     * </p>
10671     *
10672     * @param event The motion event to be dispatched.
10673     * @return True if the event was handled by the view, false otherwise.
10674     */
10675    public boolean dispatchGenericMotionEvent(MotionEvent event) {
10676        if (mInputEventConsistencyVerifier != null) {
10677            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
10678        }
10679
10680        final int source = event.getSource();
10681        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
10682            final int action = event.getAction();
10683            if (action == MotionEvent.ACTION_HOVER_ENTER
10684                    || action == MotionEvent.ACTION_HOVER_MOVE
10685                    || action == MotionEvent.ACTION_HOVER_EXIT) {
10686                if (dispatchHoverEvent(event)) {
10687                    return true;
10688                }
10689            } else if (dispatchGenericPointerEvent(event)) {
10690                return true;
10691            }
10692        } else if (dispatchGenericFocusedEvent(event)) {
10693            return true;
10694        }
10695
10696        if (dispatchGenericMotionEventInternal(event)) {
10697            return true;
10698        }
10699
10700        if (mInputEventConsistencyVerifier != null) {
10701            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10702        }
10703        return false;
10704    }
10705
10706    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
10707        //noinspection SimplifiableIfStatement
10708        ListenerInfo li = mListenerInfo;
10709        if (li != null && li.mOnGenericMotionListener != null
10710                && (mViewFlags & ENABLED_MASK) == ENABLED
10711                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
10712            return true;
10713        }
10714
10715        if (onGenericMotionEvent(event)) {
10716            return true;
10717        }
10718
10719        final int actionButton = event.getActionButton();
10720        switch (event.getActionMasked()) {
10721            case MotionEvent.ACTION_BUTTON_PRESS:
10722                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
10723                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10724                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10725                    if (performContextClick(event.getX(), event.getY())) {
10726                        mInContextButtonPress = true;
10727                        setPressed(true, event.getX(), event.getY());
10728                        removeTapCallback();
10729                        removeLongPressCallback();
10730                        return true;
10731                    }
10732                }
10733                break;
10734
10735            case MotionEvent.ACTION_BUTTON_RELEASE:
10736                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10737                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10738                    mInContextButtonPress = false;
10739                    mIgnoreNextUpEvent = true;
10740                }
10741                break;
10742        }
10743
10744        if (mInputEventConsistencyVerifier != null) {
10745            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10746        }
10747        return false;
10748    }
10749
10750    /**
10751     * Dispatch a hover event.
10752     * <p>
10753     * Do not call this method directly.
10754     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10755     * </p>
10756     *
10757     * @param event The motion event to be dispatched.
10758     * @return True if the event was handled by the view, false otherwise.
10759     */
10760    protected boolean dispatchHoverEvent(MotionEvent event) {
10761        ListenerInfo li = mListenerInfo;
10762        //noinspection SimplifiableIfStatement
10763        if (li != null && li.mOnHoverListener != null
10764                && (mViewFlags & ENABLED_MASK) == ENABLED
10765                && li.mOnHoverListener.onHover(this, event)) {
10766            return true;
10767        }
10768
10769        return onHoverEvent(event);
10770    }
10771
10772    /**
10773     * Returns true if the view has a child to which it has recently sent
10774     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
10775     * it does not have a hovered child, then it must be the innermost hovered view.
10776     * @hide
10777     */
10778    protected boolean hasHoveredChild() {
10779        return false;
10780    }
10781
10782    /**
10783     * Dispatch a generic motion event to the view under the first pointer.
10784     * <p>
10785     * Do not call this method directly.
10786     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10787     * </p>
10788     *
10789     * @param event The motion event to be dispatched.
10790     * @return True if the event was handled by the view, false otherwise.
10791     */
10792    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
10793        return false;
10794    }
10795
10796    /**
10797     * Dispatch a generic motion event to the currently focused view.
10798     * <p>
10799     * Do not call this method directly.
10800     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10801     * </p>
10802     *
10803     * @param event The motion event to be dispatched.
10804     * @return True if the event was handled by the view, false otherwise.
10805     */
10806    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
10807        return false;
10808    }
10809
10810    /**
10811     * Dispatch a pointer event.
10812     * <p>
10813     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
10814     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
10815     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
10816     * and should not be expected to handle other pointing device features.
10817     * </p>
10818     *
10819     * @param event The motion event to be dispatched.
10820     * @return True if the event was handled by the view, false otherwise.
10821     * @hide
10822     */
10823    public final boolean dispatchPointerEvent(MotionEvent event) {
10824        if (event.isTouchEvent()) {
10825            return dispatchTouchEvent(event);
10826        } else {
10827            return dispatchGenericMotionEvent(event);
10828        }
10829    }
10830
10831    /**
10832     * Called when the window containing this view gains or loses window focus.
10833     * ViewGroups should override to route to their children.
10834     *
10835     * @param hasFocus True if the window containing this view now has focus,
10836     *        false otherwise.
10837     */
10838    public void dispatchWindowFocusChanged(boolean hasFocus) {
10839        onWindowFocusChanged(hasFocus);
10840    }
10841
10842    /**
10843     * Called when the window containing this view gains or loses focus.  Note
10844     * that this is separate from view focus: to receive key events, both
10845     * your view and its window must have focus.  If a window is displayed
10846     * on top of yours that takes input focus, then your own window will lose
10847     * focus but the view focus will remain unchanged.
10848     *
10849     * @param hasWindowFocus True if the window containing this view now has
10850     *        focus, false otherwise.
10851     */
10852    public void onWindowFocusChanged(boolean hasWindowFocus) {
10853        InputMethodManager imm = InputMethodManager.peekInstance();
10854        if (!hasWindowFocus) {
10855            if (isPressed()) {
10856                setPressed(false);
10857            }
10858            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
10859            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10860                imm.focusOut(this);
10861            }
10862            removeLongPressCallback();
10863            removeTapCallback();
10864            onFocusLost();
10865        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10866            imm.focusIn(this);
10867        }
10868        refreshDrawableState();
10869    }
10870
10871    /**
10872     * Returns true if this view is in a window that currently has window focus.
10873     * Note that this is not the same as the view itself having focus.
10874     *
10875     * @return True if this view is in a window that currently has window focus.
10876     */
10877    public boolean hasWindowFocus() {
10878        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
10879    }
10880
10881    /**
10882     * Dispatch a view visibility change down the view hierarchy.
10883     * ViewGroups should override to route to their children.
10884     * @param changedView The view whose visibility changed. Could be 'this' or
10885     * an ancestor view.
10886     * @param visibility The new visibility of changedView: {@link #VISIBLE},
10887     * {@link #INVISIBLE} or {@link #GONE}.
10888     */
10889    protected void dispatchVisibilityChanged(@NonNull View changedView,
10890            @Visibility int visibility) {
10891        onVisibilityChanged(changedView, visibility);
10892    }
10893
10894    /**
10895     * Called when the visibility of the view or an ancestor of the view has
10896     * changed.
10897     *
10898     * @param changedView The view whose visibility changed. May be
10899     *                    {@code this} or an ancestor view.
10900     * @param visibility The new visibility, one of {@link #VISIBLE},
10901     *                   {@link #INVISIBLE} or {@link #GONE}.
10902     */
10903    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
10904    }
10905
10906    /**
10907     * Dispatch a hint about whether this view is displayed. For instance, when
10908     * a View moves out of the screen, it might receives a display hint indicating
10909     * the view is not displayed. Applications should not <em>rely</em> on this hint
10910     * as there is no guarantee that they will receive one.
10911     *
10912     * @param hint A hint about whether or not this view is displayed:
10913     * {@link #VISIBLE} or {@link #INVISIBLE}.
10914     */
10915    public void dispatchDisplayHint(@Visibility int hint) {
10916        onDisplayHint(hint);
10917    }
10918
10919    /**
10920     * Gives this view a hint about whether is displayed or not. For instance, when
10921     * a View moves out of the screen, it might receives a display hint indicating
10922     * the view is not displayed. Applications should not <em>rely</em> on this hint
10923     * as there is no guarantee that they will receive one.
10924     *
10925     * @param hint A hint about whether or not this view is displayed:
10926     * {@link #VISIBLE} or {@link #INVISIBLE}.
10927     */
10928    protected void onDisplayHint(@Visibility int hint) {
10929    }
10930
10931    /**
10932     * Dispatch a window visibility change down the view hierarchy.
10933     * ViewGroups should override to route to their children.
10934     *
10935     * @param visibility The new visibility of the window.
10936     *
10937     * @see #onWindowVisibilityChanged(int)
10938     */
10939    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
10940        onWindowVisibilityChanged(visibility);
10941    }
10942
10943    /**
10944     * Called when the window containing has change its visibility
10945     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
10946     * that this tells you whether or not your window is being made visible
10947     * to the window manager; this does <em>not</em> tell you whether or not
10948     * your window is obscured by other windows on the screen, even if it
10949     * is itself visible.
10950     *
10951     * @param visibility The new visibility of the window.
10952     */
10953    protected void onWindowVisibilityChanged(@Visibility int visibility) {
10954        if (visibility == VISIBLE) {
10955            initialAwakenScrollBars();
10956        }
10957    }
10958
10959    /**
10960     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
10961     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
10962     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
10963     *
10964     * @param isVisible true if this view's visibility to the user is uninterrupted by its
10965     *                  ancestors or by window visibility
10966     * @return true if this view is visible to the user, not counting clipping or overlapping
10967     */
10968    boolean dispatchVisibilityAggregated(boolean isVisible) {
10969        final boolean thisVisible = getVisibility() == VISIBLE;
10970        // If we're not visible but something is telling us we are, ignore it.
10971        if (thisVisible || !isVisible) {
10972            onVisibilityAggregated(isVisible);
10973        }
10974        return thisVisible && isVisible;
10975    }
10976
10977    /**
10978     * Called when the user-visibility of this View is potentially affected by a change
10979     * to this view itself, an ancestor view or the window this view is attached to.
10980     *
10981     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
10982     *                  and this view's window is also visible
10983     */
10984    @CallSuper
10985    public void onVisibilityAggregated(boolean isVisible) {
10986        if (isVisible && mAttachInfo != null) {
10987            initialAwakenScrollBars();
10988        }
10989
10990        final Drawable dr = mBackground;
10991        if (dr != null && isVisible != dr.isVisible()) {
10992            dr.setVisible(isVisible, false);
10993        }
10994        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
10995        if (fg != null && isVisible != fg.isVisible()) {
10996            fg.setVisible(isVisible, false);
10997        }
10998    }
10999
11000    /**
11001     * Returns the current visibility of the window this view is attached to
11002     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
11003     *
11004     * @return Returns the current visibility of the view's window.
11005     */
11006    @Visibility
11007    public int getWindowVisibility() {
11008        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
11009    }
11010
11011    /**
11012     * Retrieve the overall visible display size in which the window this view is
11013     * attached to has been positioned in.  This takes into account screen
11014     * decorations above the window, for both cases where the window itself
11015     * is being position inside of them or the window is being placed under
11016     * then and covered insets are used for the window to position its content
11017     * inside.  In effect, this tells you the available area where content can
11018     * be placed and remain visible to users.
11019     *
11020     * <p>This function requires an IPC back to the window manager to retrieve
11021     * the requested information, so should not be used in performance critical
11022     * code like drawing.
11023     *
11024     * @param outRect Filled in with the visible display frame.  If the view
11025     * is not attached to a window, this is simply the raw display size.
11026     */
11027    public void getWindowVisibleDisplayFrame(Rect outRect) {
11028        if (mAttachInfo != null) {
11029            try {
11030                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11031            } catch (RemoteException e) {
11032                return;
11033            }
11034            // XXX This is really broken, and probably all needs to be done
11035            // in the window manager, and we need to know more about whether
11036            // we want the area behind or in front of the IME.
11037            final Rect insets = mAttachInfo.mVisibleInsets;
11038            outRect.left += insets.left;
11039            outRect.top += insets.top;
11040            outRect.right -= insets.right;
11041            outRect.bottom -= insets.bottom;
11042            return;
11043        }
11044        // The view is not attached to a display so we don't have a context.
11045        // Make a best guess about the display size.
11046        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11047        d.getRectSize(outRect);
11048    }
11049
11050    /**
11051     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
11052     * is currently in without any insets.
11053     *
11054     * @hide
11055     */
11056    public void getWindowDisplayFrame(Rect outRect) {
11057        if (mAttachInfo != null) {
11058            try {
11059                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11060            } catch (RemoteException e) {
11061                return;
11062            }
11063            return;
11064        }
11065        // The view is not attached to a display so we don't have a context.
11066        // Make a best guess about the display size.
11067        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11068        d.getRectSize(outRect);
11069    }
11070
11071    /**
11072     * Dispatch a notification about a resource configuration change down
11073     * the view hierarchy.
11074     * ViewGroups should override to route to their children.
11075     *
11076     * @param newConfig The new resource configuration.
11077     *
11078     * @see #onConfigurationChanged(android.content.res.Configuration)
11079     */
11080    public void dispatchConfigurationChanged(Configuration newConfig) {
11081        onConfigurationChanged(newConfig);
11082    }
11083
11084    /**
11085     * Called when the current configuration of the resources being used
11086     * by the application have changed.  You can use this to decide when
11087     * to reload resources that can changed based on orientation and other
11088     * configuration characteristics.  You only need to use this if you are
11089     * not relying on the normal {@link android.app.Activity} mechanism of
11090     * recreating the activity instance upon a configuration change.
11091     *
11092     * @param newConfig The new resource configuration.
11093     */
11094    protected void onConfigurationChanged(Configuration newConfig) {
11095    }
11096
11097    /**
11098     * Private function to aggregate all per-view attributes in to the view
11099     * root.
11100     */
11101    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11102        performCollectViewAttributes(attachInfo, visibility);
11103    }
11104
11105    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11106        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
11107            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
11108                attachInfo.mKeepScreenOn = true;
11109            }
11110            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
11111            ListenerInfo li = mListenerInfo;
11112            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
11113                attachInfo.mHasSystemUiListeners = true;
11114            }
11115        }
11116    }
11117
11118    void needGlobalAttributesUpdate(boolean force) {
11119        final AttachInfo ai = mAttachInfo;
11120        if (ai != null && !ai.mRecomputeGlobalAttributes) {
11121            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
11122                    || ai.mHasSystemUiListeners) {
11123                ai.mRecomputeGlobalAttributes = true;
11124            }
11125        }
11126    }
11127
11128    /**
11129     * Returns whether the device is currently in touch mode.  Touch mode is entered
11130     * once the user begins interacting with the device by touch, and affects various
11131     * things like whether focus is always visible to the user.
11132     *
11133     * @return Whether the device is in touch mode.
11134     */
11135    @ViewDebug.ExportedProperty
11136    public boolean isInTouchMode() {
11137        if (mAttachInfo != null) {
11138            return mAttachInfo.mInTouchMode;
11139        } else {
11140            return ViewRootImpl.isInTouchMode();
11141        }
11142    }
11143
11144    /**
11145     * Returns the context the view is running in, through which it can
11146     * access the current theme, resources, etc.
11147     *
11148     * @return The view's Context.
11149     */
11150    @ViewDebug.CapturedViewProperty
11151    public final Context getContext() {
11152        return mContext;
11153    }
11154
11155    /**
11156     * Handle a key event before it is processed by any input method
11157     * associated with the view hierarchy.  This can be used to intercept
11158     * key events in special situations before the IME consumes them; a
11159     * typical example would be handling the BACK key to update the application's
11160     * UI instead of allowing the IME to see it and close itself.
11161     *
11162     * @param keyCode The value in event.getKeyCode().
11163     * @param event Description of the key event.
11164     * @return If you handled the event, return true. If you want to allow the
11165     *         event to be handled by the next receiver, return false.
11166     */
11167    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
11168        return false;
11169    }
11170
11171    /**
11172     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
11173     * KeyEvent.Callback.onKeyDown()}: perform press of the view
11174     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
11175     * is released, if the view is enabled and clickable.
11176     * <p>
11177     * Key presses in software keyboards will generally NOT trigger this
11178     * listener, although some may elect to do so in some situations. Do not
11179     * rely on this to catch software key presses.
11180     *
11181     * @param keyCode a key code that represents the button pressed, from
11182     *                {@link android.view.KeyEvent}
11183     * @param event the KeyEvent object that defines the button action
11184     */
11185    public boolean onKeyDown(int keyCode, KeyEvent event) {
11186        if (KeyEvent.isConfirmKey(keyCode)) {
11187            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11188                return true;
11189            }
11190
11191            if (event.getRepeatCount() == 0) {
11192                // Long clickable items don't necessarily have to be clickable.
11193                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
11194                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
11195                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
11196                    // For the purposes of menu anchoring and drawable hotspots,
11197                    // key events are considered to be at the center of the view.
11198                    final float x = getWidth() / 2f;
11199                    final float y = getHeight() / 2f;
11200                    if (clickable) {
11201                        setPressed(true, x, y);
11202                    }
11203                    checkForLongClick(0, x, y);
11204                    return true;
11205                }
11206            }
11207        }
11208
11209        return false;
11210    }
11211
11212    /**
11213     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
11214     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
11215     * the event).
11216     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11217     * although some may elect to do so in some situations. Do not rely on this to
11218     * catch software key presses.
11219     */
11220    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
11221        return false;
11222    }
11223
11224    /**
11225     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
11226     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
11227     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
11228     * or {@link KeyEvent#KEYCODE_SPACE} is released.
11229     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11230     * although some may elect to do so in some situations. Do not rely on this to
11231     * catch software key presses.
11232     *
11233     * @param keyCode A key code that represents the button pressed, from
11234     *                {@link android.view.KeyEvent}.
11235     * @param event   The KeyEvent object that defines the button action.
11236     */
11237    public boolean onKeyUp(int keyCode, KeyEvent event) {
11238        if (KeyEvent.isConfirmKey(keyCode)) {
11239            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11240                return true;
11241            }
11242            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
11243                setPressed(false);
11244
11245                if (!mHasPerformedLongPress) {
11246                    // This is a tap, so remove the longpress check
11247                    removeLongPressCallback();
11248                    return performClick();
11249                }
11250            }
11251        }
11252        return false;
11253    }
11254
11255    /**
11256     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
11257     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
11258     * the event).
11259     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11260     * although some may elect to do so in some situations. Do not rely on this to
11261     * catch software key presses.
11262     *
11263     * @param keyCode     A key code that represents the button pressed, from
11264     *                    {@link android.view.KeyEvent}.
11265     * @param repeatCount The number of times the action was made.
11266     * @param event       The KeyEvent object that defines the button action.
11267     */
11268    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
11269        return false;
11270    }
11271
11272    /**
11273     * Called on the focused view when a key shortcut event is not handled.
11274     * Override this method to implement local key shortcuts for the View.
11275     * Key shortcuts can also be implemented by setting the
11276     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
11277     *
11278     * @param keyCode The value in event.getKeyCode().
11279     * @param event Description of the key event.
11280     * @return If you handled the event, return true. If you want to allow the
11281     *         event to be handled by the next receiver, return false.
11282     */
11283    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
11284        return false;
11285    }
11286
11287    /**
11288     * Check whether the called view is a text editor, in which case it
11289     * would make sense to automatically display a soft input window for
11290     * it.  Subclasses should override this if they implement
11291     * {@link #onCreateInputConnection(EditorInfo)} to return true if
11292     * a call on that method would return a non-null InputConnection, and
11293     * they are really a first-class editor that the user would normally
11294     * start typing on when the go into a window containing your view.
11295     *
11296     * <p>The default implementation always returns false.  This does
11297     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
11298     * will not be called or the user can not otherwise perform edits on your
11299     * view; it is just a hint to the system that this is not the primary
11300     * purpose of this view.
11301     *
11302     * @return Returns true if this view is a text editor, else false.
11303     */
11304    public boolean onCheckIsTextEditor() {
11305        return false;
11306    }
11307
11308    /**
11309     * Create a new InputConnection for an InputMethod to interact
11310     * with the view.  The default implementation returns null, since it doesn't
11311     * support input methods.  You can override this to implement such support.
11312     * This is only needed for views that take focus and text input.
11313     *
11314     * <p>When implementing this, you probably also want to implement
11315     * {@link #onCheckIsTextEditor()} to indicate you will return a
11316     * non-null InputConnection.</p>
11317     *
11318     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
11319     * object correctly and in its entirety, so that the connected IME can rely
11320     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
11321     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
11322     * must be filled in with the correct cursor position for IMEs to work correctly
11323     * with your application.</p>
11324     *
11325     * @param outAttrs Fill in with attribute information about the connection.
11326     */
11327    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
11328        return null;
11329    }
11330
11331    /**
11332     * Called by the {@link android.view.inputmethod.InputMethodManager}
11333     * when a view who is not the current
11334     * input connection target is trying to make a call on the manager.  The
11335     * default implementation returns false; you can override this to return
11336     * true for certain views if you are performing InputConnection proxying
11337     * to them.
11338     * @param view The View that is making the InputMethodManager call.
11339     * @return Return true to allow the call, false to reject.
11340     */
11341    public boolean checkInputConnectionProxy(View view) {
11342        return false;
11343    }
11344
11345    /**
11346     * Show the context menu for this view. It is not safe to hold on to the
11347     * menu after returning from this method.
11348     *
11349     * You should normally not overload this method. Overload
11350     * {@link #onCreateContextMenu(ContextMenu)} or define an
11351     * {@link OnCreateContextMenuListener} to add items to the context menu.
11352     *
11353     * @param menu The context menu to populate
11354     */
11355    public void createContextMenu(ContextMenu menu) {
11356        ContextMenuInfo menuInfo = getContextMenuInfo();
11357
11358        // Sets the current menu info so all items added to menu will have
11359        // my extra info set.
11360        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
11361
11362        onCreateContextMenu(menu);
11363        ListenerInfo li = mListenerInfo;
11364        if (li != null && li.mOnCreateContextMenuListener != null) {
11365            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
11366        }
11367
11368        // Clear the extra information so subsequent items that aren't mine don't
11369        // have my extra info.
11370        ((MenuBuilder)menu).setCurrentMenuInfo(null);
11371
11372        if (mParent != null) {
11373            mParent.createContextMenu(menu);
11374        }
11375    }
11376
11377    /**
11378     * Views should implement this if they have extra information to associate
11379     * with the context menu. The return result is supplied as a parameter to
11380     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
11381     * callback.
11382     *
11383     * @return Extra information about the item for which the context menu
11384     *         should be shown. This information will vary across different
11385     *         subclasses of View.
11386     */
11387    protected ContextMenuInfo getContextMenuInfo() {
11388        return null;
11389    }
11390
11391    /**
11392     * Views should implement this if the view itself is going to add items to
11393     * the context menu.
11394     *
11395     * @param menu the context menu to populate
11396     */
11397    protected void onCreateContextMenu(ContextMenu menu) {
11398    }
11399
11400    /**
11401     * Implement this method to handle trackball motion events.  The
11402     * <em>relative</em> movement of the trackball since the last event
11403     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
11404     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
11405     * that a movement of 1 corresponds to the user pressing one DPAD key (so
11406     * they will often be fractional values, representing the more fine-grained
11407     * movement information available from a trackball).
11408     *
11409     * @param event The motion event.
11410     * @return True if the event was handled, false otherwise.
11411     */
11412    public boolean onTrackballEvent(MotionEvent event) {
11413        return false;
11414    }
11415
11416    /**
11417     * Implement this method to handle generic motion events.
11418     * <p>
11419     * Generic motion events describe joystick movements, mouse hovers, track pad
11420     * touches, scroll wheel movements and other input events.  The
11421     * {@link MotionEvent#getSource() source} of the motion event specifies
11422     * the class of input that was received.  Implementations of this method
11423     * must examine the bits in the source before processing the event.
11424     * The following code example shows how this is done.
11425     * </p><p>
11426     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11427     * are delivered to the view under the pointer.  All other generic motion events are
11428     * delivered to the focused view.
11429     * </p>
11430     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
11431     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
11432     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
11433     *             // process the joystick movement...
11434     *             return true;
11435     *         }
11436     *     }
11437     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
11438     *         switch (event.getAction()) {
11439     *             case MotionEvent.ACTION_HOVER_MOVE:
11440     *                 // process the mouse hover movement...
11441     *                 return true;
11442     *             case MotionEvent.ACTION_SCROLL:
11443     *                 // process the scroll wheel movement...
11444     *                 return true;
11445     *         }
11446     *     }
11447     *     return super.onGenericMotionEvent(event);
11448     * }</pre>
11449     *
11450     * @param event The generic motion event being processed.
11451     * @return True if the event was handled, false otherwise.
11452     */
11453    public boolean onGenericMotionEvent(MotionEvent event) {
11454        return false;
11455    }
11456
11457    /**
11458     * Implement this method to handle hover events.
11459     * <p>
11460     * This method is called whenever a pointer is hovering into, over, or out of the
11461     * bounds of a view and the view is not currently being touched.
11462     * Hover events are represented as pointer events with action
11463     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
11464     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
11465     * </p>
11466     * <ul>
11467     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
11468     * when the pointer enters the bounds of the view.</li>
11469     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
11470     * when the pointer has already entered the bounds of the view and has moved.</li>
11471     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
11472     * when the pointer has exited the bounds of the view or when the pointer is
11473     * about to go down due to a button click, tap, or similar user action that
11474     * causes the view to be touched.</li>
11475     * </ul>
11476     * <p>
11477     * The view should implement this method to return true to indicate that it is
11478     * handling the hover event, such as by changing its drawable state.
11479     * </p><p>
11480     * The default implementation calls {@link #setHovered} to update the hovered state
11481     * of the view when a hover enter or hover exit event is received, if the view
11482     * is enabled and is clickable.  The default implementation also sends hover
11483     * accessibility events.
11484     * </p>
11485     *
11486     * @param event The motion event that describes the hover.
11487     * @return True if the view handled the hover event.
11488     *
11489     * @see #isHovered
11490     * @see #setHovered
11491     * @see #onHoverChanged
11492     */
11493    public boolean onHoverEvent(MotionEvent event) {
11494        // The root view may receive hover (or touch) events that are outside the bounds of
11495        // the window.  This code ensures that we only send accessibility events for
11496        // hovers that are actually within the bounds of the root view.
11497        final int action = event.getActionMasked();
11498        if (!mSendingHoverAccessibilityEvents) {
11499            if ((action == MotionEvent.ACTION_HOVER_ENTER
11500                    || action == MotionEvent.ACTION_HOVER_MOVE)
11501                    && !hasHoveredChild()
11502                    && pointInView(event.getX(), event.getY())) {
11503                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
11504                mSendingHoverAccessibilityEvents = true;
11505            }
11506        } else {
11507            if (action == MotionEvent.ACTION_HOVER_EXIT
11508                    || (action == MotionEvent.ACTION_MOVE
11509                            && !pointInView(event.getX(), event.getY()))) {
11510                mSendingHoverAccessibilityEvents = false;
11511                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
11512            }
11513        }
11514
11515        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
11516                && event.isFromSource(InputDevice.SOURCE_MOUSE)
11517                && isOnScrollbar(event.getX(), event.getY())) {
11518            awakenScrollBars();
11519        }
11520        if (isHoverable()) {
11521            switch (action) {
11522                case MotionEvent.ACTION_HOVER_ENTER:
11523                    setHovered(true);
11524                    break;
11525                case MotionEvent.ACTION_HOVER_EXIT:
11526                    setHovered(false);
11527                    break;
11528            }
11529
11530            // Dispatch the event to onGenericMotionEvent before returning true.
11531            // This is to provide compatibility with existing applications that
11532            // handled HOVER_MOVE events in onGenericMotionEvent and that would
11533            // break because of the new default handling for hoverable views
11534            // in onHoverEvent.
11535            // Note that onGenericMotionEvent will be called by default when
11536            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
11537            dispatchGenericMotionEventInternal(event);
11538            // The event was already handled by calling setHovered(), so always
11539            // return true.
11540            return true;
11541        }
11542
11543        return false;
11544    }
11545
11546    /**
11547     * Returns true if the view should handle {@link #onHoverEvent}
11548     * by calling {@link #setHovered} to change its hovered state.
11549     *
11550     * @return True if the view is hoverable.
11551     */
11552    private boolean isHoverable() {
11553        final int viewFlags = mViewFlags;
11554        if ((viewFlags & ENABLED_MASK) == DISABLED) {
11555            return false;
11556        }
11557
11558        return (viewFlags & CLICKABLE) == CLICKABLE
11559                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
11560                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
11561    }
11562
11563    /**
11564     * Returns true if the view is currently hovered.
11565     *
11566     * @return True if the view is currently hovered.
11567     *
11568     * @see #setHovered
11569     * @see #onHoverChanged
11570     */
11571    @ViewDebug.ExportedProperty
11572    public boolean isHovered() {
11573        return (mPrivateFlags & PFLAG_HOVERED) != 0;
11574    }
11575
11576    /**
11577     * Sets whether the view is currently hovered.
11578     * <p>
11579     * Calling this method also changes the drawable state of the view.  This
11580     * enables the view to react to hover by using different drawable resources
11581     * to change its appearance.
11582     * </p><p>
11583     * The {@link #onHoverChanged} method is called when the hovered state changes.
11584     * </p>
11585     *
11586     * @param hovered True if the view is hovered.
11587     *
11588     * @see #isHovered
11589     * @see #onHoverChanged
11590     */
11591    public void setHovered(boolean hovered) {
11592        if (hovered) {
11593            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
11594                mPrivateFlags |= PFLAG_HOVERED;
11595                refreshDrawableState();
11596                onHoverChanged(true);
11597            }
11598        } else {
11599            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
11600                mPrivateFlags &= ~PFLAG_HOVERED;
11601                refreshDrawableState();
11602                onHoverChanged(false);
11603            }
11604        }
11605    }
11606
11607    /**
11608     * Implement this method to handle hover state changes.
11609     * <p>
11610     * This method is called whenever the hover state changes as a result of a
11611     * call to {@link #setHovered}.
11612     * </p>
11613     *
11614     * @param hovered The current hover state, as returned by {@link #isHovered}.
11615     *
11616     * @see #isHovered
11617     * @see #setHovered
11618     */
11619    public void onHoverChanged(boolean hovered) {
11620    }
11621
11622    /**
11623     * Handles scroll bar dragging by mouse input.
11624     *
11625     * @hide
11626     * @param event The motion event.
11627     *
11628     * @return true if the event was handled as a scroll bar dragging, false otherwise.
11629     */
11630    protected boolean handleScrollBarDragging(MotionEvent event) {
11631        if (mScrollCache == null) {
11632            return false;
11633        }
11634        final float x = event.getX();
11635        final float y = event.getY();
11636        final int action = event.getAction();
11637        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
11638                && action != MotionEvent.ACTION_DOWN)
11639                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
11640                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
11641            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11642            return false;
11643        }
11644
11645        switch (action) {
11646            case MotionEvent.ACTION_MOVE:
11647                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
11648                    return false;
11649                }
11650                if (mScrollCache.mScrollBarDraggingState
11651                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
11652                    final Rect bounds = mScrollCache.mScrollBarBounds;
11653                    getVerticalScrollBarBounds(bounds);
11654                    final int range = computeVerticalScrollRange();
11655                    final int offset = computeVerticalScrollOffset();
11656                    final int extent = computeVerticalScrollExtent();
11657
11658                    final int thumbLength = ScrollBarUtils.getThumbLength(
11659                            bounds.height(), bounds.width(), extent, range);
11660                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11661                            bounds.height(), thumbLength, extent, range, offset);
11662
11663                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
11664                    final float maxThumbOffset = bounds.height() - thumbLength;
11665                    final float newThumbOffset =
11666                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11667                    final int height = getHeight();
11668                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11669                            && height > 0 && extent > 0) {
11670                        final int newY = Math.round((range - extent)
11671                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
11672                        if (newY != getScrollY()) {
11673                            mScrollCache.mScrollBarDraggingPos = y;
11674                            setScrollY(newY);
11675                        }
11676                    }
11677                    return true;
11678                }
11679                if (mScrollCache.mScrollBarDraggingState
11680                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
11681                    final Rect bounds = mScrollCache.mScrollBarBounds;
11682                    getHorizontalScrollBarBounds(bounds);
11683                    final int range = computeHorizontalScrollRange();
11684                    final int offset = computeHorizontalScrollOffset();
11685                    final int extent = computeHorizontalScrollExtent();
11686
11687                    final int thumbLength = ScrollBarUtils.getThumbLength(
11688                            bounds.width(), bounds.height(), extent, range);
11689                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11690                            bounds.width(), thumbLength, extent, range, offset);
11691
11692                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
11693                    final float maxThumbOffset = bounds.width() - thumbLength;
11694                    final float newThumbOffset =
11695                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11696                    final int width = getWidth();
11697                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11698                            && width > 0 && extent > 0) {
11699                        final int newX = Math.round((range - extent)
11700                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
11701                        if (newX != getScrollX()) {
11702                            mScrollCache.mScrollBarDraggingPos = x;
11703                            setScrollX(newX);
11704                        }
11705                    }
11706                    return true;
11707                }
11708            case MotionEvent.ACTION_DOWN:
11709                if (mScrollCache.state == ScrollabilityCache.OFF) {
11710                    return false;
11711                }
11712                if (isOnVerticalScrollbarThumb(x, y)) {
11713                    mScrollCache.mScrollBarDraggingState =
11714                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
11715                    mScrollCache.mScrollBarDraggingPos = y;
11716                    return true;
11717                }
11718                if (isOnHorizontalScrollbarThumb(x, y)) {
11719                    mScrollCache.mScrollBarDraggingState =
11720                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
11721                    mScrollCache.mScrollBarDraggingPos = x;
11722                    return true;
11723                }
11724        }
11725        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11726        return false;
11727    }
11728
11729    /**
11730     * Implement this method to handle touch screen motion events.
11731     * <p>
11732     * If this method is used to detect click actions, it is recommended that
11733     * the actions be performed by implementing and calling
11734     * {@link #performClick()}. This will ensure consistent system behavior,
11735     * including:
11736     * <ul>
11737     * <li>obeying click sound preferences
11738     * <li>dispatching OnClickListener calls
11739     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
11740     * accessibility features are enabled
11741     * </ul>
11742     *
11743     * @param event The motion event.
11744     * @return True if the event was handled, false otherwise.
11745     */
11746    public boolean onTouchEvent(MotionEvent event) {
11747        final float x = event.getX();
11748        final float y = event.getY();
11749        final int viewFlags = mViewFlags;
11750        final int action = event.getAction();
11751
11752        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
11753                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
11754                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
11755
11756        if ((viewFlags & ENABLED_MASK) == DISABLED) {
11757            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
11758                setPressed(false);
11759            }
11760            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11761            // A disabled view that is clickable still consumes the touch
11762            // events, it just doesn't respond to them.
11763            return clickable;
11764        }
11765        if (mTouchDelegate != null) {
11766            if (mTouchDelegate.onTouchEvent(event)) {
11767                return true;
11768            }
11769        }
11770
11771        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
11772            switch (action) {
11773                case MotionEvent.ACTION_UP:
11774                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11775                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
11776                        handleTooltipUp();
11777                    }
11778                    if (!clickable) {
11779                        removeTapCallback();
11780                        removeLongPressCallback();
11781                        mInContextButtonPress = false;
11782                        mHasPerformedLongPress = false;
11783                        mIgnoreNextUpEvent = false;
11784                        break;
11785                    }
11786                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
11787                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
11788                        // take focus if we don't have it already and we should in
11789                        // touch mode.
11790                        boolean focusTaken = false;
11791                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
11792                            focusTaken = requestFocus();
11793                        }
11794
11795                        if (prepressed) {
11796                            // The button is being released before we actually
11797                            // showed it as pressed.  Make it show the pressed
11798                            // state now (before scheduling the click) to ensure
11799                            // the user sees it.
11800                            setPressed(true, x, y);
11801                        }
11802
11803                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
11804                            // This is a tap, so remove the longpress check
11805                            removeLongPressCallback();
11806
11807                            // Only perform take click actions if we were in the pressed state
11808                            if (!focusTaken) {
11809                                // Use a Runnable and post this rather than calling
11810                                // performClick directly. This lets other visual state
11811                                // of the view update before click actions start.
11812                                if (mPerformClick == null) {
11813                                    mPerformClick = new PerformClick();
11814                                }
11815                                if (!post(mPerformClick)) {
11816                                    performClick();
11817                                }
11818                            }
11819                        }
11820
11821                        if (mUnsetPressedState == null) {
11822                            mUnsetPressedState = new UnsetPressedState();
11823                        }
11824
11825                        if (prepressed) {
11826                            postDelayed(mUnsetPressedState,
11827                                    ViewConfiguration.getPressedStateDuration());
11828                        } else if (!post(mUnsetPressedState)) {
11829                            // If the post failed, unpress right now
11830                            mUnsetPressedState.run();
11831                        }
11832
11833                        removeTapCallback();
11834                    }
11835                    mIgnoreNextUpEvent = false;
11836                    break;
11837
11838                case MotionEvent.ACTION_DOWN:
11839                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
11840                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
11841                    }
11842                    mHasPerformedLongPress = false;
11843
11844                    if (!clickable) {
11845                        checkForLongClick(0, x, y);
11846                        break;
11847                    }
11848
11849                    if (performButtonActionOnTouchDown(event)) {
11850                        break;
11851                    }
11852
11853                    // Walk up the hierarchy to determine if we're inside a scrolling container.
11854                    boolean isInScrollingContainer = isInScrollingContainer();
11855
11856                    // For views inside a scrolling container, delay the pressed feedback for
11857                    // a short period in case this is a scroll.
11858                    if (isInScrollingContainer) {
11859                        mPrivateFlags |= PFLAG_PREPRESSED;
11860                        if (mPendingCheckForTap == null) {
11861                            mPendingCheckForTap = new CheckForTap();
11862                        }
11863                        mPendingCheckForTap.x = event.getX();
11864                        mPendingCheckForTap.y = event.getY();
11865                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
11866                    } else {
11867                        // Not inside a scrolling container, so show the feedback right away
11868                        setPressed(true, x, y);
11869                        checkForLongClick(0, x, y);
11870                    }
11871                    break;
11872
11873                case MotionEvent.ACTION_CANCEL:
11874                    if (clickable) {
11875                        setPressed(false);
11876                    }
11877                    removeTapCallback();
11878                    removeLongPressCallback();
11879                    mInContextButtonPress = false;
11880                    mHasPerformedLongPress = false;
11881                    mIgnoreNextUpEvent = false;
11882                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11883                    break;
11884
11885                case MotionEvent.ACTION_MOVE:
11886                    if (clickable) {
11887                        drawableHotspotChanged(x, y);
11888                    }
11889
11890                    // Be lenient about moving outside of buttons
11891                    if (!pointInView(x, y, mTouchSlop)) {
11892                        // Outside button
11893                        // Remove any future long press/tap checks
11894                        removeTapCallback();
11895                        removeLongPressCallback();
11896                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
11897                            setPressed(false);
11898                        }
11899                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11900                    }
11901                    break;
11902            }
11903
11904            return true;
11905        }
11906
11907        return false;
11908    }
11909
11910    /**
11911     * @hide
11912     */
11913    public boolean isInScrollingContainer() {
11914        ViewParent p = getParent();
11915        while (p != null && p instanceof ViewGroup) {
11916            if (((ViewGroup) p).shouldDelayChildPressedState()) {
11917                return true;
11918            }
11919            p = p.getParent();
11920        }
11921        return false;
11922    }
11923
11924    /**
11925     * Remove the longpress detection timer.
11926     */
11927    private void removeLongPressCallback() {
11928        if (mPendingCheckForLongPress != null) {
11929            removeCallbacks(mPendingCheckForLongPress);
11930        }
11931    }
11932
11933    /**
11934     * Remove the pending click action
11935     */
11936    private void removePerformClickCallback() {
11937        if (mPerformClick != null) {
11938            removeCallbacks(mPerformClick);
11939        }
11940    }
11941
11942    /**
11943     * Remove the prepress detection timer.
11944     */
11945    private void removeUnsetPressCallback() {
11946        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
11947            setPressed(false);
11948            removeCallbacks(mUnsetPressedState);
11949        }
11950    }
11951
11952    /**
11953     * Remove the tap detection timer.
11954     */
11955    private void removeTapCallback() {
11956        if (mPendingCheckForTap != null) {
11957            mPrivateFlags &= ~PFLAG_PREPRESSED;
11958            removeCallbacks(mPendingCheckForTap);
11959        }
11960    }
11961
11962    /**
11963     * Cancels a pending long press.  Your subclass can use this if you
11964     * want the context menu to come up if the user presses and holds
11965     * at the same place, but you don't want it to come up if they press
11966     * and then move around enough to cause scrolling.
11967     */
11968    public void cancelLongPress() {
11969        removeLongPressCallback();
11970
11971        /*
11972         * The prepressed state handled by the tap callback is a display
11973         * construct, but the tap callback will post a long press callback
11974         * less its own timeout. Remove it here.
11975         */
11976        removeTapCallback();
11977    }
11978
11979    /**
11980     * Remove the pending callback for sending a
11981     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
11982     */
11983    private void removeSendViewScrolledAccessibilityEventCallback() {
11984        if (mSendViewScrolledAccessibilityEvent != null) {
11985            removeCallbacks(mSendViewScrolledAccessibilityEvent);
11986            mSendViewScrolledAccessibilityEvent.mIsPending = false;
11987        }
11988    }
11989
11990    /**
11991     * Sets the TouchDelegate for this View.
11992     */
11993    public void setTouchDelegate(TouchDelegate delegate) {
11994        mTouchDelegate = delegate;
11995    }
11996
11997    /**
11998     * Gets the TouchDelegate for this View.
11999     */
12000    public TouchDelegate getTouchDelegate() {
12001        return mTouchDelegate;
12002    }
12003
12004    /**
12005     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
12006     *
12007     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
12008     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
12009     * available. This method should only be called for touch events.
12010     *
12011     * <p class="note">This api is not intended for most applications. Buffered dispatch
12012     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
12013     * streams will not improve your input latency. Side effects include: increased latency,
12014     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
12015     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
12016     * you.</p>
12017     */
12018    public final void requestUnbufferedDispatch(MotionEvent event) {
12019        final int action = event.getAction();
12020        if (mAttachInfo == null
12021                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
12022                || !event.isTouchEvent()) {
12023            return;
12024        }
12025        mAttachInfo.mUnbufferedDispatchRequested = true;
12026    }
12027
12028    /**
12029     * Set flags controlling behavior of this view.
12030     *
12031     * @param flags Constant indicating the value which should be set
12032     * @param mask Constant indicating the bit range that should be changed
12033     */
12034    void setFlags(int flags, int mask) {
12035        final boolean accessibilityEnabled =
12036                AccessibilityManager.getInstance(mContext).isEnabled();
12037        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
12038
12039        int old = mViewFlags;
12040        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
12041
12042        int changed = mViewFlags ^ old;
12043        if (changed == 0) {
12044            return;
12045        }
12046        int privateFlags = mPrivateFlags;
12047
12048        // If focusable is auto, update the FOCUSABLE bit.
12049        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
12050                && (changed & (FOCUSABLE_MASK | CLICKABLE | FOCUSABLE_IN_TOUCH_MODE)) != 0) {
12051            int newFocus = NOT_FOCUSABLE;
12052            if ((mViewFlags & (CLICKABLE | FOCUSABLE_IN_TOUCH_MODE)) != 0) {
12053                newFocus = FOCUSABLE;
12054            } else {
12055                mViewFlags = (mViewFlags & ~FOCUSABLE_IN_TOUCH_MODE);
12056            }
12057            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
12058            int focusChanged = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
12059            changed = (changed & ~FOCUSABLE) | focusChanged;
12060        }
12061
12062        /* Check if the FOCUSABLE bit has changed */
12063        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
12064            if (((old & FOCUSABLE) == FOCUSABLE)
12065                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
12066                /* Give up focus if we are no longer focusable */
12067                clearFocus();
12068            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
12069                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
12070                /*
12071                 * Tell the view system that we are now available to take focus
12072                 * if no one else already has it.
12073                 */
12074                if (mParent != null) mParent.focusableViewAvailable(this);
12075            }
12076        }
12077
12078        final int newVisibility = flags & VISIBILITY_MASK;
12079        if (newVisibility == VISIBLE) {
12080            if ((changed & VISIBILITY_MASK) != 0) {
12081                /*
12082                 * If this view is becoming visible, invalidate it in case it changed while
12083                 * it was not visible. Marking it drawn ensures that the invalidation will
12084                 * go through.
12085                 */
12086                mPrivateFlags |= PFLAG_DRAWN;
12087                invalidate(true);
12088
12089                needGlobalAttributesUpdate(true);
12090
12091                // a view becoming visible is worth notifying the parent
12092                // about in case nothing has focus.  even if this specific view
12093                // isn't focusable, it may contain something that is, so let
12094                // the root view try to give this focus if nothing else does.
12095                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
12096                    mParent.focusableViewAvailable(this);
12097                }
12098            }
12099        }
12100
12101        /* Check if the GONE bit has changed */
12102        if ((changed & GONE) != 0) {
12103            needGlobalAttributesUpdate(false);
12104            requestLayout();
12105
12106            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
12107                if (hasFocus()) clearFocus();
12108                clearAccessibilityFocus();
12109                destroyDrawingCache();
12110                if (mParent instanceof View) {
12111                    // GONE views noop invalidation, so invalidate the parent
12112                    ((View) mParent).invalidate(true);
12113                }
12114                // Mark the view drawn to ensure that it gets invalidated properly the next
12115                // time it is visible and gets invalidated
12116                mPrivateFlags |= PFLAG_DRAWN;
12117            }
12118            if (mAttachInfo != null) {
12119                mAttachInfo.mViewVisibilityChanged = true;
12120            }
12121        }
12122
12123        /* Check if the VISIBLE bit has changed */
12124        if ((changed & INVISIBLE) != 0) {
12125            needGlobalAttributesUpdate(false);
12126            /*
12127             * If this view is becoming invisible, set the DRAWN flag so that
12128             * the next invalidate() will not be skipped.
12129             */
12130            mPrivateFlags |= PFLAG_DRAWN;
12131
12132            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
12133                // root view becoming invisible shouldn't clear focus and accessibility focus
12134                if (getRootView() != this) {
12135                    if (hasFocus()) clearFocus();
12136                    clearAccessibilityFocus();
12137                }
12138            }
12139            if (mAttachInfo != null) {
12140                mAttachInfo.mViewVisibilityChanged = true;
12141            }
12142        }
12143
12144        if ((changed & VISIBILITY_MASK) != 0) {
12145            // If the view is invisible, cleanup its display list to free up resources
12146            if (newVisibility != VISIBLE && mAttachInfo != null) {
12147                cleanupDraw();
12148            }
12149
12150            if (mParent instanceof ViewGroup) {
12151                ((ViewGroup) mParent).onChildVisibilityChanged(this,
12152                        (changed & VISIBILITY_MASK), newVisibility);
12153                ((View) mParent).invalidate(true);
12154            } else if (mParent != null) {
12155                mParent.invalidateChild(this, null);
12156            }
12157
12158            if (mAttachInfo != null) {
12159                dispatchVisibilityChanged(this, newVisibility);
12160
12161                // Aggregated visibility changes are dispatched to attached views
12162                // in visible windows where the parent is currently shown/drawn
12163                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
12164                // discounting clipping or overlapping. This makes it a good place
12165                // to change animation states.
12166                if (mParent != null && getWindowVisibility() == VISIBLE &&
12167                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
12168                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
12169                }
12170                notifySubtreeAccessibilityStateChangedIfNeeded();
12171            }
12172        }
12173
12174        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
12175            destroyDrawingCache();
12176        }
12177
12178        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
12179            destroyDrawingCache();
12180            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12181            invalidateParentCaches();
12182        }
12183
12184        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
12185            destroyDrawingCache();
12186            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12187        }
12188
12189        if ((changed & DRAW_MASK) != 0) {
12190            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
12191                if (mBackground != null
12192                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
12193                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12194                } else {
12195                    mPrivateFlags |= PFLAG_SKIP_DRAW;
12196                }
12197            } else {
12198                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12199            }
12200            requestLayout();
12201            invalidate(true);
12202        }
12203
12204        if ((changed & KEEP_SCREEN_ON) != 0) {
12205            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
12206                mParent.recomputeViewAttributes(this);
12207            }
12208        }
12209
12210        if (accessibilityEnabled) {
12211            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
12212                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
12213                    || (changed & CONTEXT_CLICKABLE) != 0) {
12214                if (oldIncludeForAccessibility != includeForAccessibility()) {
12215                    notifySubtreeAccessibilityStateChangedIfNeeded();
12216                } else {
12217                    notifyViewAccessibilityStateChangedIfNeeded(
12218                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12219                }
12220            } else if ((changed & ENABLED_MASK) != 0) {
12221                notifyViewAccessibilityStateChangedIfNeeded(
12222                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12223            }
12224        }
12225    }
12226
12227    /**
12228     * Change the view's z order in the tree, so it's on top of other sibling
12229     * views. This ordering change may affect layout, if the parent container
12230     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
12231     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
12232     * method should be followed by calls to {@link #requestLayout()} and
12233     * {@link View#invalidate()} on the view's parent to force the parent to redraw
12234     * with the new child ordering.
12235     *
12236     * @see ViewGroup#bringChildToFront(View)
12237     */
12238    public void bringToFront() {
12239        if (mParent != null) {
12240            mParent.bringChildToFront(this);
12241        }
12242    }
12243
12244    /**
12245     * This is called in response to an internal scroll in this view (i.e., the
12246     * view scrolled its own contents). This is typically as a result of
12247     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
12248     * called.
12249     *
12250     * @param l Current horizontal scroll origin.
12251     * @param t Current vertical scroll origin.
12252     * @param oldl Previous horizontal scroll origin.
12253     * @param oldt Previous vertical scroll origin.
12254     */
12255    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
12256        notifySubtreeAccessibilityStateChangedIfNeeded();
12257
12258        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
12259            postSendViewScrolledAccessibilityEventCallback();
12260        }
12261
12262        mBackgroundSizeChanged = true;
12263        if (mForegroundInfo != null) {
12264            mForegroundInfo.mBoundsChanged = true;
12265        }
12266
12267        final AttachInfo ai = mAttachInfo;
12268        if (ai != null) {
12269            ai.mViewScrollChanged = true;
12270        }
12271
12272        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
12273            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
12274        }
12275    }
12276
12277    /**
12278     * Interface definition for a callback to be invoked when the scroll
12279     * X or Y positions of a view change.
12280     * <p>
12281     * <b>Note:</b> Some views handle scrolling independently from View and may
12282     * have their own separate listeners for scroll-type events. For example,
12283     * {@link android.widget.ListView ListView} allows clients to register an
12284     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
12285     * to listen for changes in list scroll position.
12286     *
12287     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
12288     */
12289    public interface OnScrollChangeListener {
12290        /**
12291         * Called when the scroll position of a view changes.
12292         *
12293         * @param v The view whose scroll position has changed.
12294         * @param scrollX Current horizontal scroll origin.
12295         * @param scrollY Current vertical scroll origin.
12296         * @param oldScrollX Previous horizontal scroll origin.
12297         * @param oldScrollY Previous vertical scroll origin.
12298         */
12299        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
12300    }
12301
12302    /**
12303     * Interface definition for a callback to be invoked when the layout bounds of a view
12304     * changes due to layout processing.
12305     */
12306    public interface OnLayoutChangeListener {
12307        /**
12308         * Called when the layout bounds of a view changes due to layout processing.
12309         *
12310         * @param v The view whose bounds have changed.
12311         * @param left The new value of the view's left property.
12312         * @param top The new value of the view's top property.
12313         * @param right The new value of the view's right property.
12314         * @param bottom The new value of the view's bottom property.
12315         * @param oldLeft The previous value of the view's left property.
12316         * @param oldTop The previous value of the view's top property.
12317         * @param oldRight The previous value of the view's right property.
12318         * @param oldBottom The previous value of the view's bottom property.
12319         */
12320        void onLayoutChange(View v, int left, int top, int right, int bottom,
12321            int oldLeft, int oldTop, int oldRight, int oldBottom);
12322    }
12323
12324    /**
12325     * This is called during layout when the size of this view has changed. If
12326     * you were just added to the view hierarchy, you're called with the old
12327     * values of 0.
12328     *
12329     * @param w Current width of this view.
12330     * @param h Current height of this view.
12331     * @param oldw Old width of this view.
12332     * @param oldh Old height of this view.
12333     */
12334    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
12335    }
12336
12337    /**
12338     * Called by draw to draw the child views. This may be overridden
12339     * by derived classes to gain control just before its children are drawn
12340     * (but after its own view has been drawn).
12341     * @param canvas the canvas on which to draw the view
12342     */
12343    protected void dispatchDraw(Canvas canvas) {
12344
12345    }
12346
12347    /**
12348     * Gets the parent of this view. Note that the parent is a
12349     * ViewParent and not necessarily a View.
12350     *
12351     * @return Parent of this view.
12352     */
12353    public final ViewParent getParent() {
12354        return mParent;
12355    }
12356
12357    /**
12358     * Set the horizontal scrolled position of your view. This will cause a call to
12359     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12360     * invalidated.
12361     * @param value the x position to scroll to
12362     */
12363    public void setScrollX(int value) {
12364        scrollTo(value, mScrollY);
12365    }
12366
12367    /**
12368     * Set the vertical scrolled position of your view. This will cause a call to
12369     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12370     * invalidated.
12371     * @param value the y position to scroll to
12372     */
12373    public void setScrollY(int value) {
12374        scrollTo(mScrollX, value);
12375    }
12376
12377    /**
12378     * Return the scrolled left position of this view. This is the left edge of
12379     * the displayed part of your view. You do not need to draw any pixels
12380     * farther left, since those are outside of the frame of your view on
12381     * screen.
12382     *
12383     * @return The left edge of the displayed part of your view, in pixels.
12384     */
12385    public final int getScrollX() {
12386        return mScrollX;
12387    }
12388
12389    /**
12390     * Return the scrolled top position of this view. This is the top edge of
12391     * the displayed part of your view. You do not need to draw any pixels above
12392     * it, since those are outside of the frame of your view on screen.
12393     *
12394     * @return The top edge of the displayed part of your view, in pixels.
12395     */
12396    public final int getScrollY() {
12397        return mScrollY;
12398    }
12399
12400    /**
12401     * Return the width of the your view.
12402     *
12403     * @return The width of your view, in pixels.
12404     */
12405    @ViewDebug.ExportedProperty(category = "layout")
12406    public final int getWidth() {
12407        return mRight - mLeft;
12408    }
12409
12410    /**
12411     * Return the height of your view.
12412     *
12413     * @return The height of your view, in pixels.
12414     */
12415    @ViewDebug.ExportedProperty(category = "layout")
12416    public final int getHeight() {
12417        return mBottom - mTop;
12418    }
12419
12420    /**
12421     * Return the visible drawing bounds of your view. Fills in the output
12422     * rectangle with the values from getScrollX(), getScrollY(),
12423     * getWidth(), and getHeight(). These bounds do not account for any
12424     * transformation properties currently set on the view, such as
12425     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
12426     *
12427     * @param outRect The (scrolled) drawing bounds of the view.
12428     */
12429    public void getDrawingRect(Rect outRect) {
12430        outRect.left = mScrollX;
12431        outRect.top = mScrollY;
12432        outRect.right = mScrollX + (mRight - mLeft);
12433        outRect.bottom = mScrollY + (mBottom - mTop);
12434    }
12435
12436    /**
12437     * Like {@link #getMeasuredWidthAndState()}, but only returns the
12438     * raw width component (that is the result is masked by
12439     * {@link #MEASURED_SIZE_MASK}).
12440     *
12441     * @return The raw measured width of this view.
12442     */
12443    public final int getMeasuredWidth() {
12444        return mMeasuredWidth & MEASURED_SIZE_MASK;
12445    }
12446
12447    /**
12448     * Return the full width measurement information for this view as computed
12449     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
12450     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
12451     * This should be used during measurement and layout calculations only. Use
12452     * {@link #getWidth()} to see how wide a view is after layout.
12453     *
12454     * @return The measured width of this view as a bit mask.
12455     */
12456    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
12457            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
12458                    name = "MEASURED_STATE_TOO_SMALL"),
12459    })
12460    public final int getMeasuredWidthAndState() {
12461        return mMeasuredWidth;
12462    }
12463
12464    /**
12465     * Like {@link #getMeasuredHeightAndState()}, but only returns the
12466     * raw height component (that is the result is masked by
12467     * {@link #MEASURED_SIZE_MASK}).
12468     *
12469     * @return The raw measured height of this view.
12470     */
12471    public final int getMeasuredHeight() {
12472        return mMeasuredHeight & MEASURED_SIZE_MASK;
12473    }
12474
12475    /**
12476     * Return the full height measurement information for this view as computed
12477     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
12478     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
12479     * This should be used during measurement and layout calculations only. Use
12480     * {@link #getHeight()} to see how wide a view is after layout.
12481     *
12482     * @return The measured height of this view as a bit mask.
12483     */
12484    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
12485            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
12486                    name = "MEASURED_STATE_TOO_SMALL"),
12487    })
12488    public final int getMeasuredHeightAndState() {
12489        return mMeasuredHeight;
12490    }
12491
12492    /**
12493     * Return only the state bits of {@link #getMeasuredWidthAndState()}
12494     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
12495     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
12496     * and the height component is at the shifted bits
12497     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
12498     */
12499    public final int getMeasuredState() {
12500        return (mMeasuredWidth&MEASURED_STATE_MASK)
12501                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
12502                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
12503    }
12504
12505    /**
12506     * The transform matrix of this view, which is calculated based on the current
12507     * rotation, scale, and pivot properties.
12508     *
12509     * @see #getRotation()
12510     * @see #getScaleX()
12511     * @see #getScaleY()
12512     * @see #getPivotX()
12513     * @see #getPivotY()
12514     * @return The current transform matrix for the view
12515     */
12516    public Matrix getMatrix() {
12517        ensureTransformationInfo();
12518        final Matrix matrix = mTransformationInfo.mMatrix;
12519        mRenderNode.getMatrix(matrix);
12520        return matrix;
12521    }
12522
12523    /**
12524     * Returns true if the transform matrix is the identity matrix.
12525     * Recomputes the matrix if necessary.
12526     *
12527     * @return True if the transform matrix is the identity matrix, false otherwise.
12528     */
12529    final boolean hasIdentityMatrix() {
12530        return mRenderNode.hasIdentityMatrix();
12531    }
12532
12533    void ensureTransformationInfo() {
12534        if (mTransformationInfo == null) {
12535            mTransformationInfo = new TransformationInfo();
12536        }
12537    }
12538
12539    /**
12540     * Utility method to retrieve the inverse of the current mMatrix property.
12541     * We cache the matrix to avoid recalculating it when transform properties
12542     * have not changed.
12543     *
12544     * @return The inverse of the current matrix of this view.
12545     * @hide
12546     */
12547    public final Matrix getInverseMatrix() {
12548        ensureTransformationInfo();
12549        if (mTransformationInfo.mInverseMatrix == null) {
12550            mTransformationInfo.mInverseMatrix = new Matrix();
12551        }
12552        final Matrix matrix = mTransformationInfo.mInverseMatrix;
12553        mRenderNode.getInverseMatrix(matrix);
12554        return matrix;
12555    }
12556
12557    /**
12558     * Gets the distance along the Z axis from the camera to this view.
12559     *
12560     * @see #setCameraDistance(float)
12561     *
12562     * @return The distance along the Z axis.
12563     */
12564    public float getCameraDistance() {
12565        final float dpi = mResources.getDisplayMetrics().densityDpi;
12566        return -(mRenderNode.getCameraDistance() * dpi);
12567    }
12568
12569    /**
12570     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
12571     * views are drawn) from the camera to this view. The camera's distance
12572     * affects 3D transformations, for instance rotations around the X and Y
12573     * axis. If the rotationX or rotationY properties are changed and this view is
12574     * large (more than half the size of the screen), it is recommended to always
12575     * use a camera distance that's greater than the height (X axis rotation) or
12576     * the width (Y axis rotation) of this view.</p>
12577     *
12578     * <p>The distance of the camera from the view plane can have an affect on the
12579     * perspective distortion of the view when it is rotated around the x or y axis.
12580     * For example, a large distance will result in a large viewing angle, and there
12581     * will not be much perspective distortion of the view as it rotates. A short
12582     * distance may cause much more perspective distortion upon rotation, and can
12583     * also result in some drawing artifacts if the rotated view ends up partially
12584     * behind the camera (which is why the recommendation is to use a distance at
12585     * least as far as the size of the view, if the view is to be rotated.)</p>
12586     *
12587     * <p>The distance is expressed in "depth pixels." The default distance depends
12588     * on the screen density. For instance, on a medium density display, the
12589     * default distance is 1280. On a high density display, the default distance
12590     * is 1920.</p>
12591     *
12592     * <p>If you want to specify a distance that leads to visually consistent
12593     * results across various densities, use the following formula:</p>
12594     * <pre>
12595     * float scale = context.getResources().getDisplayMetrics().density;
12596     * view.setCameraDistance(distance * scale);
12597     * </pre>
12598     *
12599     * <p>The density scale factor of a high density display is 1.5,
12600     * and 1920 = 1280 * 1.5.</p>
12601     *
12602     * @param distance The distance in "depth pixels", if negative the opposite
12603     *        value is used
12604     *
12605     * @see #setRotationX(float)
12606     * @see #setRotationY(float)
12607     */
12608    public void setCameraDistance(float distance) {
12609        final float dpi = mResources.getDisplayMetrics().densityDpi;
12610
12611        invalidateViewProperty(true, false);
12612        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
12613        invalidateViewProperty(false, false);
12614
12615        invalidateParentIfNeededAndWasQuickRejected();
12616    }
12617
12618    /**
12619     * The degrees that the view is rotated around the pivot point.
12620     *
12621     * @see #setRotation(float)
12622     * @see #getPivotX()
12623     * @see #getPivotY()
12624     *
12625     * @return The degrees of rotation.
12626     */
12627    @ViewDebug.ExportedProperty(category = "drawing")
12628    public float getRotation() {
12629        return mRenderNode.getRotation();
12630    }
12631
12632    /**
12633     * Sets the degrees that the view is rotated around the pivot point. Increasing values
12634     * result in clockwise rotation.
12635     *
12636     * @param rotation The degrees of rotation.
12637     *
12638     * @see #getRotation()
12639     * @see #getPivotX()
12640     * @see #getPivotY()
12641     * @see #setRotationX(float)
12642     * @see #setRotationY(float)
12643     *
12644     * @attr ref android.R.styleable#View_rotation
12645     */
12646    public void setRotation(float rotation) {
12647        if (rotation != getRotation()) {
12648            // Double-invalidation is necessary to capture view's old and new areas
12649            invalidateViewProperty(true, false);
12650            mRenderNode.setRotation(rotation);
12651            invalidateViewProperty(false, true);
12652
12653            invalidateParentIfNeededAndWasQuickRejected();
12654            notifySubtreeAccessibilityStateChangedIfNeeded();
12655        }
12656    }
12657
12658    /**
12659     * The degrees that the view is rotated around the vertical axis through the pivot point.
12660     *
12661     * @see #getPivotX()
12662     * @see #getPivotY()
12663     * @see #setRotationY(float)
12664     *
12665     * @return The degrees of Y rotation.
12666     */
12667    @ViewDebug.ExportedProperty(category = "drawing")
12668    public float getRotationY() {
12669        return mRenderNode.getRotationY();
12670    }
12671
12672    /**
12673     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
12674     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
12675     * down the y axis.
12676     *
12677     * When rotating large views, it is recommended to adjust the camera distance
12678     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12679     *
12680     * @param rotationY The degrees of Y rotation.
12681     *
12682     * @see #getRotationY()
12683     * @see #getPivotX()
12684     * @see #getPivotY()
12685     * @see #setRotation(float)
12686     * @see #setRotationX(float)
12687     * @see #setCameraDistance(float)
12688     *
12689     * @attr ref android.R.styleable#View_rotationY
12690     */
12691    public void setRotationY(float rotationY) {
12692        if (rotationY != getRotationY()) {
12693            invalidateViewProperty(true, false);
12694            mRenderNode.setRotationY(rotationY);
12695            invalidateViewProperty(false, true);
12696
12697            invalidateParentIfNeededAndWasQuickRejected();
12698            notifySubtreeAccessibilityStateChangedIfNeeded();
12699        }
12700    }
12701
12702    /**
12703     * The degrees that the view is rotated around the horizontal axis through the pivot point.
12704     *
12705     * @see #getPivotX()
12706     * @see #getPivotY()
12707     * @see #setRotationX(float)
12708     *
12709     * @return The degrees of X rotation.
12710     */
12711    @ViewDebug.ExportedProperty(category = "drawing")
12712    public float getRotationX() {
12713        return mRenderNode.getRotationX();
12714    }
12715
12716    /**
12717     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
12718     * Increasing values result in clockwise rotation from the viewpoint of looking down the
12719     * x axis.
12720     *
12721     * When rotating large views, it is recommended to adjust the camera distance
12722     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12723     *
12724     * @param rotationX The degrees of X rotation.
12725     *
12726     * @see #getRotationX()
12727     * @see #getPivotX()
12728     * @see #getPivotY()
12729     * @see #setRotation(float)
12730     * @see #setRotationY(float)
12731     * @see #setCameraDistance(float)
12732     *
12733     * @attr ref android.R.styleable#View_rotationX
12734     */
12735    public void setRotationX(float rotationX) {
12736        if (rotationX != getRotationX()) {
12737            invalidateViewProperty(true, false);
12738            mRenderNode.setRotationX(rotationX);
12739            invalidateViewProperty(false, true);
12740
12741            invalidateParentIfNeededAndWasQuickRejected();
12742            notifySubtreeAccessibilityStateChangedIfNeeded();
12743        }
12744    }
12745
12746    /**
12747     * The amount that the view is scaled in x around the pivot point, as a proportion of
12748     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
12749     *
12750     * <p>By default, this is 1.0f.
12751     *
12752     * @see #getPivotX()
12753     * @see #getPivotY()
12754     * @return The scaling factor.
12755     */
12756    @ViewDebug.ExportedProperty(category = "drawing")
12757    public float getScaleX() {
12758        return mRenderNode.getScaleX();
12759    }
12760
12761    /**
12762     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
12763     * the view's unscaled width. A value of 1 means that no scaling is applied.
12764     *
12765     * @param scaleX The scaling factor.
12766     * @see #getPivotX()
12767     * @see #getPivotY()
12768     *
12769     * @attr ref android.R.styleable#View_scaleX
12770     */
12771    public void setScaleX(float scaleX) {
12772        if (scaleX != getScaleX()) {
12773            invalidateViewProperty(true, false);
12774            mRenderNode.setScaleX(scaleX);
12775            invalidateViewProperty(false, true);
12776
12777            invalidateParentIfNeededAndWasQuickRejected();
12778            notifySubtreeAccessibilityStateChangedIfNeeded();
12779        }
12780    }
12781
12782    /**
12783     * The amount that the view is scaled in y around the pivot point, as a proportion of
12784     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
12785     *
12786     * <p>By default, this is 1.0f.
12787     *
12788     * @see #getPivotX()
12789     * @see #getPivotY()
12790     * @return The scaling factor.
12791     */
12792    @ViewDebug.ExportedProperty(category = "drawing")
12793    public float getScaleY() {
12794        return mRenderNode.getScaleY();
12795    }
12796
12797    /**
12798     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
12799     * the view's unscaled width. A value of 1 means that no scaling is applied.
12800     *
12801     * @param scaleY The scaling factor.
12802     * @see #getPivotX()
12803     * @see #getPivotY()
12804     *
12805     * @attr ref android.R.styleable#View_scaleY
12806     */
12807    public void setScaleY(float scaleY) {
12808        if (scaleY != getScaleY()) {
12809            invalidateViewProperty(true, false);
12810            mRenderNode.setScaleY(scaleY);
12811            invalidateViewProperty(false, true);
12812
12813            invalidateParentIfNeededAndWasQuickRejected();
12814            notifySubtreeAccessibilityStateChangedIfNeeded();
12815        }
12816    }
12817
12818    /**
12819     * The x location of the point around which the view is {@link #setRotation(float) rotated}
12820     * and {@link #setScaleX(float) scaled}.
12821     *
12822     * @see #getRotation()
12823     * @see #getScaleX()
12824     * @see #getScaleY()
12825     * @see #getPivotY()
12826     * @return The x location of the pivot point.
12827     *
12828     * @attr ref android.R.styleable#View_transformPivotX
12829     */
12830    @ViewDebug.ExportedProperty(category = "drawing")
12831    public float getPivotX() {
12832        return mRenderNode.getPivotX();
12833    }
12834
12835    /**
12836     * Sets the x location of the point around which the view is
12837     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
12838     * By default, the pivot point is centered on the object.
12839     * Setting this property disables this behavior and causes the view to use only the
12840     * explicitly set pivotX and pivotY values.
12841     *
12842     * @param pivotX The x location of the pivot point.
12843     * @see #getRotation()
12844     * @see #getScaleX()
12845     * @see #getScaleY()
12846     * @see #getPivotY()
12847     *
12848     * @attr ref android.R.styleable#View_transformPivotX
12849     */
12850    public void setPivotX(float pivotX) {
12851        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
12852            invalidateViewProperty(true, false);
12853            mRenderNode.setPivotX(pivotX);
12854            invalidateViewProperty(false, true);
12855
12856            invalidateParentIfNeededAndWasQuickRejected();
12857        }
12858    }
12859
12860    /**
12861     * The y location of the point around which the view is {@link #setRotation(float) rotated}
12862     * and {@link #setScaleY(float) scaled}.
12863     *
12864     * @see #getRotation()
12865     * @see #getScaleX()
12866     * @see #getScaleY()
12867     * @see #getPivotY()
12868     * @return The y location of the pivot point.
12869     *
12870     * @attr ref android.R.styleable#View_transformPivotY
12871     */
12872    @ViewDebug.ExportedProperty(category = "drawing")
12873    public float getPivotY() {
12874        return mRenderNode.getPivotY();
12875    }
12876
12877    /**
12878     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
12879     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
12880     * Setting this property disables this behavior and causes the view to use only the
12881     * explicitly set pivotX and pivotY values.
12882     *
12883     * @param pivotY The y location of the pivot point.
12884     * @see #getRotation()
12885     * @see #getScaleX()
12886     * @see #getScaleY()
12887     * @see #getPivotY()
12888     *
12889     * @attr ref android.R.styleable#View_transformPivotY
12890     */
12891    public void setPivotY(float pivotY) {
12892        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
12893            invalidateViewProperty(true, false);
12894            mRenderNode.setPivotY(pivotY);
12895            invalidateViewProperty(false, true);
12896
12897            invalidateParentIfNeededAndWasQuickRejected();
12898        }
12899    }
12900
12901    /**
12902     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
12903     * completely transparent and 1 means the view is completely opaque.
12904     *
12905     * <p>By default this is 1.0f.
12906     * @return The opacity of the view.
12907     */
12908    @ViewDebug.ExportedProperty(category = "drawing")
12909    public float getAlpha() {
12910        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
12911    }
12912
12913    /**
12914     * Sets the behavior for overlapping rendering for this view (see {@link
12915     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
12916     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
12917     * providing the value which is then used internally. That is, when {@link
12918     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
12919     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
12920     * instead.
12921     *
12922     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
12923     * instead of that returned by {@link #hasOverlappingRendering()}.
12924     *
12925     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
12926     */
12927    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
12928        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
12929        if (hasOverlappingRendering) {
12930            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12931        } else {
12932            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
12933        }
12934    }
12935
12936    /**
12937     * Returns the value for overlapping rendering that is used internally. This is either
12938     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
12939     * the return value of {@link #hasOverlappingRendering()}, otherwise.
12940     *
12941     * @return The value for overlapping rendering being used internally.
12942     */
12943    public final boolean getHasOverlappingRendering() {
12944        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
12945                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
12946                hasOverlappingRendering();
12947    }
12948
12949    /**
12950     * Returns whether this View has content which overlaps.
12951     *
12952     * <p>This function, intended to be overridden by specific View types, is an optimization when
12953     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
12954     * an offscreen buffer and then composited into place, which can be expensive. If the view has
12955     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
12956     * directly. An example of overlapping rendering is a TextView with a background image, such as
12957     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
12958     * ImageView with only the foreground image. The default implementation returns true; subclasses
12959     * should override if they have cases which can be optimized.</p>
12960     *
12961     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
12962     * necessitates that a View return true if it uses the methods internally without passing the
12963     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
12964     *
12965     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
12966     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
12967     *
12968     * @return true if the content in this view might overlap, false otherwise.
12969     */
12970    @ViewDebug.ExportedProperty(category = "drawing")
12971    public boolean hasOverlappingRendering() {
12972        return true;
12973    }
12974
12975    /**
12976     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
12977     * completely transparent and 1 means the view is completely opaque.
12978     *
12979     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
12980     * can have significant performance implications, especially for large views. It is best to use
12981     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
12982     *
12983     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
12984     * strongly recommended for performance reasons to either override
12985     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
12986     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
12987     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
12988     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
12989     * of rendering cost, even for simple or small views. Starting with
12990     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
12991     * applied to the view at the rendering level.</p>
12992     *
12993     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
12994     * responsible for applying the opacity itself.</p>
12995     *
12996     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
12997     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
12998     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
12999     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
13000     *
13001     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
13002     * value will clip a View to its bounds, unless the View returns <code>false</code> from
13003     * {@link #hasOverlappingRendering}.</p>
13004     *
13005     * @param alpha The opacity of the view.
13006     *
13007     * @see #hasOverlappingRendering()
13008     * @see #setLayerType(int, android.graphics.Paint)
13009     *
13010     * @attr ref android.R.styleable#View_alpha
13011     */
13012    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
13013        ensureTransformationInfo();
13014        if (mTransformationInfo.mAlpha != alpha) {
13015            // Report visibility changes, which can affect children, to accessibility
13016            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
13017                notifySubtreeAccessibilityStateChangedIfNeeded();
13018            }
13019            mTransformationInfo.mAlpha = alpha;
13020            if (onSetAlpha((int) (alpha * 255))) {
13021                mPrivateFlags |= PFLAG_ALPHA_SET;
13022                // subclass is handling alpha - don't optimize rendering cache invalidation
13023                invalidateParentCaches();
13024                invalidate(true);
13025            } else {
13026                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13027                invalidateViewProperty(true, false);
13028                mRenderNode.setAlpha(getFinalAlpha());
13029            }
13030        }
13031    }
13032
13033    /**
13034     * Faster version of setAlpha() which performs the same steps except there are
13035     * no calls to invalidate(). The caller of this function should perform proper invalidation
13036     * on the parent and this object. The return value indicates whether the subclass handles
13037     * alpha (the return value for onSetAlpha()).
13038     *
13039     * @param alpha The new value for the alpha property
13040     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
13041     *         the new value for the alpha property is different from the old value
13042     */
13043    boolean setAlphaNoInvalidation(float alpha) {
13044        ensureTransformationInfo();
13045        if (mTransformationInfo.mAlpha != alpha) {
13046            mTransformationInfo.mAlpha = alpha;
13047            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
13048            if (subclassHandlesAlpha) {
13049                mPrivateFlags |= PFLAG_ALPHA_SET;
13050                return true;
13051            } else {
13052                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13053                mRenderNode.setAlpha(getFinalAlpha());
13054            }
13055        }
13056        return false;
13057    }
13058
13059    /**
13060     * This property is hidden and intended only for use by the Fade transition, which
13061     * animates it to produce a visual translucency that does not side-effect (or get
13062     * affected by) the real alpha property. This value is composited with the other
13063     * alpha value (and the AlphaAnimation value, when that is present) to produce
13064     * a final visual translucency result, which is what is passed into the DisplayList.
13065     *
13066     * @hide
13067     */
13068    public void setTransitionAlpha(float alpha) {
13069        ensureTransformationInfo();
13070        if (mTransformationInfo.mTransitionAlpha != alpha) {
13071            mTransformationInfo.mTransitionAlpha = alpha;
13072            mPrivateFlags &= ~PFLAG_ALPHA_SET;
13073            invalidateViewProperty(true, false);
13074            mRenderNode.setAlpha(getFinalAlpha());
13075        }
13076    }
13077
13078    /**
13079     * Calculates the visual alpha of this view, which is a combination of the actual
13080     * alpha value and the transitionAlpha value (if set).
13081     */
13082    private float getFinalAlpha() {
13083        if (mTransformationInfo != null) {
13084            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
13085        }
13086        return 1;
13087    }
13088
13089    /**
13090     * This property is hidden and intended only for use by the Fade transition, which
13091     * animates it to produce a visual translucency that does not side-effect (or get
13092     * affected by) the real alpha property. This value is composited with the other
13093     * alpha value (and the AlphaAnimation value, when that is present) to produce
13094     * a final visual translucency result, which is what is passed into the DisplayList.
13095     *
13096     * @hide
13097     */
13098    @ViewDebug.ExportedProperty(category = "drawing")
13099    public float getTransitionAlpha() {
13100        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
13101    }
13102
13103    /**
13104     * Top position of this view relative to its parent.
13105     *
13106     * @return The top of this view, in pixels.
13107     */
13108    @ViewDebug.CapturedViewProperty
13109    public final int getTop() {
13110        return mTop;
13111    }
13112
13113    /**
13114     * Sets the top position of this view relative to its parent. This method is meant to be called
13115     * by the layout system and should not generally be called otherwise, because the property
13116     * may be changed at any time by the layout.
13117     *
13118     * @param top The top of this view, in pixels.
13119     */
13120    public final void setTop(int top) {
13121        if (top != mTop) {
13122            final boolean matrixIsIdentity = hasIdentityMatrix();
13123            if (matrixIsIdentity) {
13124                if (mAttachInfo != null) {
13125                    int minTop;
13126                    int yLoc;
13127                    if (top < mTop) {
13128                        minTop = top;
13129                        yLoc = top - mTop;
13130                    } else {
13131                        minTop = mTop;
13132                        yLoc = 0;
13133                    }
13134                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
13135                }
13136            } else {
13137                // Double-invalidation is necessary to capture view's old and new areas
13138                invalidate(true);
13139            }
13140
13141            int width = mRight - mLeft;
13142            int oldHeight = mBottom - mTop;
13143
13144            mTop = top;
13145            mRenderNode.setTop(mTop);
13146
13147            sizeChange(width, mBottom - mTop, width, oldHeight);
13148
13149            if (!matrixIsIdentity) {
13150                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13151                invalidate(true);
13152            }
13153            mBackgroundSizeChanged = true;
13154            if (mForegroundInfo != null) {
13155                mForegroundInfo.mBoundsChanged = true;
13156            }
13157            invalidateParentIfNeeded();
13158            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13159                // View was rejected last time it was drawn by its parent; this may have changed
13160                invalidateParentIfNeeded();
13161            }
13162        }
13163    }
13164
13165    /**
13166     * Bottom position of this view relative to its parent.
13167     *
13168     * @return The bottom of this view, in pixels.
13169     */
13170    @ViewDebug.CapturedViewProperty
13171    public final int getBottom() {
13172        return mBottom;
13173    }
13174
13175    /**
13176     * True if this view has changed since the last time being drawn.
13177     *
13178     * @return The dirty state of this view.
13179     */
13180    public boolean isDirty() {
13181        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
13182    }
13183
13184    /**
13185     * Sets the bottom position of this view relative to its parent. This method is meant to be
13186     * called by the layout system and should not generally be called otherwise, because the
13187     * property may be changed at any time by the layout.
13188     *
13189     * @param bottom The bottom of this view, in pixels.
13190     */
13191    public final void setBottom(int bottom) {
13192        if (bottom != mBottom) {
13193            final boolean matrixIsIdentity = hasIdentityMatrix();
13194            if (matrixIsIdentity) {
13195                if (mAttachInfo != null) {
13196                    int maxBottom;
13197                    if (bottom < mBottom) {
13198                        maxBottom = mBottom;
13199                    } else {
13200                        maxBottom = bottom;
13201                    }
13202                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
13203                }
13204            } else {
13205                // Double-invalidation is necessary to capture view's old and new areas
13206                invalidate(true);
13207            }
13208
13209            int width = mRight - mLeft;
13210            int oldHeight = mBottom - mTop;
13211
13212            mBottom = bottom;
13213            mRenderNode.setBottom(mBottom);
13214
13215            sizeChange(width, mBottom - mTop, width, oldHeight);
13216
13217            if (!matrixIsIdentity) {
13218                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13219                invalidate(true);
13220            }
13221            mBackgroundSizeChanged = true;
13222            if (mForegroundInfo != null) {
13223                mForegroundInfo.mBoundsChanged = true;
13224            }
13225            invalidateParentIfNeeded();
13226            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13227                // View was rejected last time it was drawn by its parent; this may have changed
13228                invalidateParentIfNeeded();
13229            }
13230        }
13231    }
13232
13233    /**
13234     * Left position of this view relative to its parent.
13235     *
13236     * @return The left edge of this view, in pixels.
13237     */
13238    @ViewDebug.CapturedViewProperty
13239    public final int getLeft() {
13240        return mLeft;
13241    }
13242
13243    /**
13244     * Sets the left position of this view relative to its parent. This method is meant to be called
13245     * by the layout system and should not generally be called otherwise, because the property
13246     * may be changed at any time by the layout.
13247     *
13248     * @param left The left of this view, in pixels.
13249     */
13250    public final void setLeft(int left) {
13251        if (left != mLeft) {
13252            final boolean matrixIsIdentity = hasIdentityMatrix();
13253            if (matrixIsIdentity) {
13254                if (mAttachInfo != null) {
13255                    int minLeft;
13256                    int xLoc;
13257                    if (left < mLeft) {
13258                        minLeft = left;
13259                        xLoc = left - mLeft;
13260                    } else {
13261                        minLeft = mLeft;
13262                        xLoc = 0;
13263                    }
13264                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
13265                }
13266            } else {
13267                // Double-invalidation is necessary to capture view's old and new areas
13268                invalidate(true);
13269            }
13270
13271            int oldWidth = mRight - mLeft;
13272            int height = mBottom - mTop;
13273
13274            mLeft = left;
13275            mRenderNode.setLeft(left);
13276
13277            sizeChange(mRight - mLeft, height, oldWidth, height);
13278
13279            if (!matrixIsIdentity) {
13280                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13281                invalidate(true);
13282            }
13283            mBackgroundSizeChanged = true;
13284            if (mForegroundInfo != null) {
13285                mForegroundInfo.mBoundsChanged = true;
13286            }
13287            invalidateParentIfNeeded();
13288            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13289                // View was rejected last time it was drawn by its parent; this may have changed
13290                invalidateParentIfNeeded();
13291            }
13292        }
13293    }
13294
13295    /**
13296     * Right position of this view relative to its parent.
13297     *
13298     * @return The right edge of this view, in pixels.
13299     */
13300    @ViewDebug.CapturedViewProperty
13301    public final int getRight() {
13302        return mRight;
13303    }
13304
13305    /**
13306     * Sets the right position of this view relative to its parent. This method is meant to be called
13307     * by the layout system and should not generally be called otherwise, because the property
13308     * may be changed at any time by the layout.
13309     *
13310     * @param right The right of this view, in pixels.
13311     */
13312    public final void setRight(int right) {
13313        if (right != mRight) {
13314            final boolean matrixIsIdentity = hasIdentityMatrix();
13315            if (matrixIsIdentity) {
13316                if (mAttachInfo != null) {
13317                    int maxRight;
13318                    if (right < mRight) {
13319                        maxRight = mRight;
13320                    } else {
13321                        maxRight = right;
13322                    }
13323                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
13324                }
13325            } else {
13326                // Double-invalidation is necessary to capture view's old and new areas
13327                invalidate(true);
13328            }
13329
13330            int oldWidth = mRight - mLeft;
13331            int height = mBottom - mTop;
13332
13333            mRight = right;
13334            mRenderNode.setRight(mRight);
13335
13336            sizeChange(mRight - mLeft, height, oldWidth, height);
13337
13338            if (!matrixIsIdentity) {
13339                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13340                invalidate(true);
13341            }
13342            mBackgroundSizeChanged = true;
13343            if (mForegroundInfo != null) {
13344                mForegroundInfo.mBoundsChanged = true;
13345            }
13346            invalidateParentIfNeeded();
13347            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13348                // View was rejected last time it was drawn by its parent; this may have changed
13349                invalidateParentIfNeeded();
13350            }
13351        }
13352    }
13353
13354    /**
13355     * The visual x position of this view, in pixels. This is equivalent to the
13356     * {@link #setTranslationX(float) translationX} property plus the current
13357     * {@link #getLeft() left} property.
13358     *
13359     * @return The visual x position of this view, in pixels.
13360     */
13361    @ViewDebug.ExportedProperty(category = "drawing")
13362    public float getX() {
13363        return mLeft + getTranslationX();
13364    }
13365
13366    /**
13367     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
13368     * {@link #setTranslationX(float) translationX} property to be the difference between
13369     * the x value passed in and the current {@link #getLeft() left} property.
13370     *
13371     * @param x The visual x position of this view, in pixels.
13372     */
13373    public void setX(float x) {
13374        setTranslationX(x - mLeft);
13375    }
13376
13377    /**
13378     * The visual y position of this view, in pixels. This is equivalent to the
13379     * {@link #setTranslationY(float) translationY} property plus the current
13380     * {@link #getTop() top} property.
13381     *
13382     * @return The visual y position of this view, in pixels.
13383     */
13384    @ViewDebug.ExportedProperty(category = "drawing")
13385    public float getY() {
13386        return mTop + getTranslationY();
13387    }
13388
13389    /**
13390     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
13391     * {@link #setTranslationY(float) translationY} property to be the difference between
13392     * the y value passed in and the current {@link #getTop() top} property.
13393     *
13394     * @param y The visual y position of this view, in pixels.
13395     */
13396    public void setY(float y) {
13397        setTranslationY(y - mTop);
13398    }
13399
13400    /**
13401     * The visual z position of this view, in pixels. This is equivalent to the
13402     * {@link #setTranslationZ(float) translationZ} property plus the current
13403     * {@link #getElevation() elevation} property.
13404     *
13405     * @return The visual z position of this view, in pixels.
13406     */
13407    @ViewDebug.ExportedProperty(category = "drawing")
13408    public float getZ() {
13409        return getElevation() + getTranslationZ();
13410    }
13411
13412    /**
13413     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
13414     * {@link #setTranslationZ(float) translationZ} property to be the difference between
13415     * the x value passed in and the current {@link #getElevation() elevation} property.
13416     *
13417     * @param z The visual z position of this view, in pixels.
13418     */
13419    public void setZ(float z) {
13420        setTranslationZ(z - getElevation());
13421    }
13422
13423    /**
13424     * The base elevation of this view relative to its parent, in pixels.
13425     *
13426     * @return The base depth position of the view, in pixels.
13427     */
13428    @ViewDebug.ExportedProperty(category = "drawing")
13429    public float getElevation() {
13430        return mRenderNode.getElevation();
13431    }
13432
13433    /**
13434     * Sets the base elevation of this view, in pixels.
13435     *
13436     * @attr ref android.R.styleable#View_elevation
13437     */
13438    public void setElevation(float elevation) {
13439        if (elevation != getElevation()) {
13440            invalidateViewProperty(true, false);
13441            mRenderNode.setElevation(elevation);
13442            invalidateViewProperty(false, true);
13443
13444            invalidateParentIfNeededAndWasQuickRejected();
13445        }
13446    }
13447
13448    /**
13449     * The horizontal location of this view relative to its {@link #getLeft() left} position.
13450     * This position is post-layout, in addition to wherever the object's
13451     * layout placed it.
13452     *
13453     * @return The horizontal position of this view relative to its left position, in pixels.
13454     */
13455    @ViewDebug.ExportedProperty(category = "drawing")
13456    public float getTranslationX() {
13457        return mRenderNode.getTranslationX();
13458    }
13459
13460    /**
13461     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
13462     * This effectively positions the object post-layout, in addition to wherever the object's
13463     * layout placed it.
13464     *
13465     * @param translationX The horizontal position of this view relative to its left position,
13466     * in pixels.
13467     *
13468     * @attr ref android.R.styleable#View_translationX
13469     */
13470    public void setTranslationX(float translationX) {
13471        if (translationX != getTranslationX()) {
13472            invalidateViewProperty(true, false);
13473            mRenderNode.setTranslationX(translationX);
13474            invalidateViewProperty(false, true);
13475
13476            invalidateParentIfNeededAndWasQuickRejected();
13477            notifySubtreeAccessibilityStateChangedIfNeeded();
13478        }
13479    }
13480
13481    /**
13482     * The vertical location of this view relative to its {@link #getTop() top} position.
13483     * This position is post-layout, in addition to wherever the object's
13484     * layout placed it.
13485     *
13486     * @return The vertical position of this view relative to its top position,
13487     * in pixels.
13488     */
13489    @ViewDebug.ExportedProperty(category = "drawing")
13490    public float getTranslationY() {
13491        return mRenderNode.getTranslationY();
13492    }
13493
13494    /**
13495     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
13496     * This effectively positions the object post-layout, in addition to wherever the object's
13497     * layout placed it.
13498     *
13499     * @param translationY The vertical position of this view relative to its top position,
13500     * in pixels.
13501     *
13502     * @attr ref android.R.styleable#View_translationY
13503     */
13504    public void setTranslationY(float translationY) {
13505        if (translationY != getTranslationY()) {
13506            invalidateViewProperty(true, false);
13507            mRenderNode.setTranslationY(translationY);
13508            invalidateViewProperty(false, true);
13509
13510            invalidateParentIfNeededAndWasQuickRejected();
13511            notifySubtreeAccessibilityStateChangedIfNeeded();
13512        }
13513    }
13514
13515    /**
13516     * The depth location of this view relative to its {@link #getElevation() elevation}.
13517     *
13518     * @return The depth of this view relative to its elevation.
13519     */
13520    @ViewDebug.ExportedProperty(category = "drawing")
13521    public float getTranslationZ() {
13522        return mRenderNode.getTranslationZ();
13523    }
13524
13525    /**
13526     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
13527     *
13528     * @attr ref android.R.styleable#View_translationZ
13529     */
13530    public void setTranslationZ(float translationZ) {
13531        if (translationZ != getTranslationZ()) {
13532            invalidateViewProperty(true, false);
13533            mRenderNode.setTranslationZ(translationZ);
13534            invalidateViewProperty(false, true);
13535
13536            invalidateParentIfNeededAndWasQuickRejected();
13537        }
13538    }
13539
13540    /** @hide */
13541    public void setAnimationMatrix(Matrix matrix) {
13542        invalidateViewProperty(true, false);
13543        mRenderNode.setAnimationMatrix(matrix);
13544        invalidateViewProperty(false, true);
13545
13546        invalidateParentIfNeededAndWasQuickRejected();
13547    }
13548
13549    /**
13550     * Returns the current StateListAnimator if exists.
13551     *
13552     * @return StateListAnimator or null if it does not exists
13553     * @see    #setStateListAnimator(android.animation.StateListAnimator)
13554     */
13555    public StateListAnimator getStateListAnimator() {
13556        return mStateListAnimator;
13557    }
13558
13559    /**
13560     * Attaches the provided StateListAnimator to this View.
13561     * <p>
13562     * Any previously attached StateListAnimator will be detached.
13563     *
13564     * @param stateListAnimator The StateListAnimator to update the view
13565     * @see {@link android.animation.StateListAnimator}
13566     */
13567    public void setStateListAnimator(StateListAnimator stateListAnimator) {
13568        if (mStateListAnimator == stateListAnimator) {
13569            return;
13570        }
13571        if (mStateListAnimator != null) {
13572            mStateListAnimator.setTarget(null);
13573        }
13574        mStateListAnimator = stateListAnimator;
13575        if (stateListAnimator != null) {
13576            stateListAnimator.setTarget(this);
13577            if (isAttachedToWindow()) {
13578                stateListAnimator.setState(getDrawableState());
13579            }
13580        }
13581    }
13582
13583    /**
13584     * Returns whether the Outline should be used to clip the contents of the View.
13585     * <p>
13586     * Note that this flag will only be respected if the View's Outline returns true from
13587     * {@link Outline#canClip()}.
13588     *
13589     * @see #setOutlineProvider(ViewOutlineProvider)
13590     * @see #setClipToOutline(boolean)
13591     */
13592    public final boolean getClipToOutline() {
13593        return mRenderNode.getClipToOutline();
13594    }
13595
13596    /**
13597     * Sets whether the View's Outline should be used to clip the contents of the View.
13598     * <p>
13599     * Only a single non-rectangular clip can be applied on a View at any time.
13600     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
13601     * circular reveal} animation take priority over Outline clipping, and
13602     * child Outline clipping takes priority over Outline clipping done by a
13603     * parent.
13604     * <p>
13605     * Note that this flag will only be respected if the View's Outline returns true from
13606     * {@link Outline#canClip()}.
13607     *
13608     * @see #setOutlineProvider(ViewOutlineProvider)
13609     * @see #getClipToOutline()
13610     */
13611    public void setClipToOutline(boolean clipToOutline) {
13612        damageInParent();
13613        if (getClipToOutline() != clipToOutline) {
13614            mRenderNode.setClipToOutline(clipToOutline);
13615        }
13616    }
13617
13618    // correspond to the enum values of View_outlineProvider
13619    private static final int PROVIDER_BACKGROUND = 0;
13620    private static final int PROVIDER_NONE = 1;
13621    private static final int PROVIDER_BOUNDS = 2;
13622    private static final int PROVIDER_PADDED_BOUNDS = 3;
13623    private void setOutlineProviderFromAttribute(int providerInt) {
13624        switch (providerInt) {
13625            case PROVIDER_BACKGROUND:
13626                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
13627                break;
13628            case PROVIDER_NONE:
13629                setOutlineProvider(null);
13630                break;
13631            case PROVIDER_BOUNDS:
13632                setOutlineProvider(ViewOutlineProvider.BOUNDS);
13633                break;
13634            case PROVIDER_PADDED_BOUNDS:
13635                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
13636                break;
13637        }
13638    }
13639
13640    /**
13641     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
13642     * the shape of the shadow it casts, and enables outline clipping.
13643     * <p>
13644     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
13645     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
13646     * outline provider with this method allows this behavior to be overridden.
13647     * <p>
13648     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
13649     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
13650     * <p>
13651     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
13652     *
13653     * @see #setClipToOutline(boolean)
13654     * @see #getClipToOutline()
13655     * @see #getOutlineProvider()
13656     */
13657    public void setOutlineProvider(ViewOutlineProvider provider) {
13658        mOutlineProvider = provider;
13659        invalidateOutline();
13660    }
13661
13662    /**
13663     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
13664     * that defines the shape of the shadow it casts, and enables outline clipping.
13665     *
13666     * @see #setOutlineProvider(ViewOutlineProvider)
13667     */
13668    public ViewOutlineProvider getOutlineProvider() {
13669        return mOutlineProvider;
13670    }
13671
13672    /**
13673     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
13674     *
13675     * @see #setOutlineProvider(ViewOutlineProvider)
13676     */
13677    public void invalidateOutline() {
13678        rebuildOutline();
13679
13680        notifySubtreeAccessibilityStateChangedIfNeeded();
13681        invalidateViewProperty(false, false);
13682    }
13683
13684    /**
13685     * Internal version of {@link #invalidateOutline()} which invalidates the
13686     * outline without invalidating the view itself. This is intended to be called from
13687     * within methods in the View class itself which are the result of the view being
13688     * invalidated already. For example, when we are drawing the background of a View,
13689     * we invalidate the outline in case it changed in the meantime, but we do not
13690     * need to invalidate the view because we're already drawing the background as part
13691     * of drawing the view in response to an earlier invalidation of the view.
13692     */
13693    private void rebuildOutline() {
13694        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
13695        if (mAttachInfo == null) return;
13696
13697        if (mOutlineProvider == null) {
13698            // no provider, remove outline
13699            mRenderNode.setOutline(null);
13700        } else {
13701            final Outline outline = mAttachInfo.mTmpOutline;
13702            outline.setEmpty();
13703            outline.setAlpha(1.0f);
13704
13705            mOutlineProvider.getOutline(this, outline);
13706            mRenderNode.setOutline(outline);
13707        }
13708    }
13709
13710    /**
13711     * HierarchyViewer only
13712     *
13713     * @hide
13714     */
13715    @ViewDebug.ExportedProperty(category = "drawing")
13716    public boolean hasShadow() {
13717        return mRenderNode.hasShadow();
13718    }
13719
13720
13721    /** @hide */
13722    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
13723        mRenderNode.setRevealClip(shouldClip, x, y, radius);
13724        invalidateViewProperty(false, false);
13725    }
13726
13727    /**
13728     * Hit rectangle in parent's coordinates
13729     *
13730     * @param outRect The hit rectangle of the view.
13731     */
13732    public void getHitRect(Rect outRect) {
13733        if (hasIdentityMatrix() || mAttachInfo == null) {
13734            outRect.set(mLeft, mTop, mRight, mBottom);
13735        } else {
13736            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
13737            tmpRect.set(0, 0, getWidth(), getHeight());
13738            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
13739            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
13740                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
13741        }
13742    }
13743
13744    /**
13745     * Determines whether the given point, in local coordinates is inside the view.
13746     */
13747    /*package*/ final boolean pointInView(float localX, float localY) {
13748        return pointInView(localX, localY, 0);
13749    }
13750
13751    /**
13752     * Utility method to determine whether the given point, in local coordinates,
13753     * is inside the view, where the area of the view is expanded by the slop factor.
13754     * This method is called while processing touch-move events to determine if the event
13755     * is still within the view.
13756     *
13757     * @hide
13758     */
13759    public boolean pointInView(float localX, float localY, float slop) {
13760        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
13761                localY < ((mBottom - mTop) + slop);
13762    }
13763
13764    /**
13765     * When a view has focus and the user navigates away from it, the next view is searched for
13766     * starting from the rectangle filled in by this method.
13767     *
13768     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
13769     * of the view.  However, if your view maintains some idea of internal selection,
13770     * such as a cursor, or a selected row or column, you should override this method and
13771     * fill in a more specific rectangle.
13772     *
13773     * @param r The rectangle to fill in, in this view's coordinates.
13774     */
13775    public void getFocusedRect(Rect r) {
13776        getDrawingRect(r);
13777    }
13778
13779    /**
13780     * If some part of this view is not clipped by any of its parents, then
13781     * return that area in r in global (root) coordinates. To convert r to local
13782     * coordinates (without taking possible View rotations into account), offset
13783     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
13784     * If the view is completely clipped or translated out, return false.
13785     *
13786     * @param r If true is returned, r holds the global coordinates of the
13787     *        visible portion of this view.
13788     * @param globalOffset If true is returned, globalOffset holds the dx,dy
13789     *        between this view and its root. globalOffet may be null.
13790     * @return true if r is non-empty (i.e. part of the view is visible at the
13791     *         root level.
13792     */
13793    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
13794        int width = mRight - mLeft;
13795        int height = mBottom - mTop;
13796        if (width > 0 && height > 0) {
13797            r.set(0, 0, width, height);
13798            if (globalOffset != null) {
13799                globalOffset.set(-mScrollX, -mScrollY);
13800            }
13801            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
13802        }
13803        return false;
13804    }
13805
13806    public final boolean getGlobalVisibleRect(Rect r) {
13807        return getGlobalVisibleRect(r, null);
13808    }
13809
13810    public final boolean getLocalVisibleRect(Rect r) {
13811        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
13812        if (getGlobalVisibleRect(r, offset)) {
13813            r.offset(-offset.x, -offset.y); // make r local
13814            return true;
13815        }
13816        return false;
13817    }
13818
13819    /**
13820     * Offset this view's vertical location by the specified number of pixels.
13821     *
13822     * @param offset the number of pixels to offset the view by
13823     */
13824    public void offsetTopAndBottom(int offset) {
13825        if (offset != 0) {
13826            final boolean matrixIsIdentity = hasIdentityMatrix();
13827            if (matrixIsIdentity) {
13828                if (isHardwareAccelerated()) {
13829                    invalidateViewProperty(false, false);
13830                } else {
13831                    final ViewParent p = mParent;
13832                    if (p != null && mAttachInfo != null) {
13833                        final Rect r = mAttachInfo.mTmpInvalRect;
13834                        int minTop;
13835                        int maxBottom;
13836                        int yLoc;
13837                        if (offset < 0) {
13838                            minTop = mTop + offset;
13839                            maxBottom = mBottom;
13840                            yLoc = offset;
13841                        } else {
13842                            minTop = mTop;
13843                            maxBottom = mBottom + offset;
13844                            yLoc = 0;
13845                        }
13846                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
13847                        p.invalidateChild(this, r);
13848                    }
13849                }
13850            } else {
13851                invalidateViewProperty(false, false);
13852            }
13853
13854            mTop += offset;
13855            mBottom += offset;
13856            mRenderNode.offsetTopAndBottom(offset);
13857            if (isHardwareAccelerated()) {
13858                invalidateViewProperty(false, false);
13859                invalidateParentIfNeededAndWasQuickRejected();
13860            } else {
13861                if (!matrixIsIdentity) {
13862                    invalidateViewProperty(false, true);
13863                }
13864                invalidateParentIfNeeded();
13865            }
13866            notifySubtreeAccessibilityStateChangedIfNeeded();
13867        }
13868    }
13869
13870    /**
13871     * Offset this view's horizontal location by the specified amount of pixels.
13872     *
13873     * @param offset the number of pixels to offset the view by
13874     */
13875    public void offsetLeftAndRight(int offset) {
13876        if (offset != 0) {
13877            final boolean matrixIsIdentity = hasIdentityMatrix();
13878            if (matrixIsIdentity) {
13879                if (isHardwareAccelerated()) {
13880                    invalidateViewProperty(false, false);
13881                } else {
13882                    final ViewParent p = mParent;
13883                    if (p != null && mAttachInfo != null) {
13884                        final Rect r = mAttachInfo.mTmpInvalRect;
13885                        int minLeft;
13886                        int maxRight;
13887                        if (offset < 0) {
13888                            minLeft = mLeft + offset;
13889                            maxRight = mRight;
13890                        } else {
13891                            minLeft = mLeft;
13892                            maxRight = mRight + offset;
13893                        }
13894                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
13895                        p.invalidateChild(this, r);
13896                    }
13897                }
13898            } else {
13899                invalidateViewProperty(false, false);
13900            }
13901
13902            mLeft += offset;
13903            mRight += offset;
13904            mRenderNode.offsetLeftAndRight(offset);
13905            if (isHardwareAccelerated()) {
13906                invalidateViewProperty(false, false);
13907                invalidateParentIfNeededAndWasQuickRejected();
13908            } else {
13909                if (!matrixIsIdentity) {
13910                    invalidateViewProperty(false, true);
13911                }
13912                invalidateParentIfNeeded();
13913            }
13914            notifySubtreeAccessibilityStateChangedIfNeeded();
13915        }
13916    }
13917
13918    /**
13919     * Get the LayoutParams associated with this view. All views should have
13920     * layout parameters. These supply parameters to the <i>parent</i> of this
13921     * view specifying how it should be arranged. There are many subclasses of
13922     * ViewGroup.LayoutParams, and these correspond to the different subclasses
13923     * of ViewGroup that are responsible for arranging their children.
13924     *
13925     * This method may return null if this View is not attached to a parent
13926     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
13927     * was not invoked successfully. When a View is attached to a parent
13928     * ViewGroup, this method must not return null.
13929     *
13930     * @return The LayoutParams associated with this view, or null if no
13931     *         parameters have been set yet
13932     */
13933    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
13934    public ViewGroup.LayoutParams getLayoutParams() {
13935        return mLayoutParams;
13936    }
13937
13938    /**
13939     * Set the layout parameters associated with this view. These supply
13940     * parameters to the <i>parent</i> of this view specifying how it should be
13941     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
13942     * correspond to the different subclasses of ViewGroup that are responsible
13943     * for arranging their children.
13944     *
13945     * @param params The layout parameters for this view, cannot be null
13946     */
13947    public void setLayoutParams(ViewGroup.LayoutParams params) {
13948        if (params == null) {
13949            throw new NullPointerException("Layout parameters cannot be null");
13950        }
13951        mLayoutParams = params;
13952        resolveLayoutParams();
13953        if (mParent instanceof ViewGroup) {
13954            ((ViewGroup) mParent).onSetLayoutParams(this, params);
13955        }
13956        requestLayout();
13957    }
13958
13959    /**
13960     * Resolve the layout parameters depending on the resolved layout direction
13961     *
13962     * @hide
13963     */
13964    public void resolveLayoutParams() {
13965        if (mLayoutParams != null) {
13966            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
13967        }
13968    }
13969
13970    /**
13971     * Set the scrolled position of your view. This will cause a call to
13972     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13973     * invalidated.
13974     * @param x the x position to scroll to
13975     * @param y the y position to scroll to
13976     */
13977    public void scrollTo(int x, int y) {
13978        if (mScrollX != x || mScrollY != y) {
13979            int oldX = mScrollX;
13980            int oldY = mScrollY;
13981            mScrollX = x;
13982            mScrollY = y;
13983            invalidateParentCaches();
13984            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
13985            if (!awakenScrollBars()) {
13986                postInvalidateOnAnimation();
13987            }
13988        }
13989    }
13990
13991    /**
13992     * Move the scrolled position of your view. This will cause a call to
13993     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13994     * invalidated.
13995     * @param x the amount of pixels to scroll by horizontally
13996     * @param y the amount of pixels to scroll by vertically
13997     */
13998    public void scrollBy(int x, int y) {
13999        scrollTo(mScrollX + x, mScrollY + y);
14000    }
14001
14002    /**
14003     * <p>Trigger the scrollbars to draw. When invoked this method starts an
14004     * animation to fade the scrollbars out after a default delay. If a subclass
14005     * provides animated scrolling, the start delay should equal the duration
14006     * of the scrolling animation.</p>
14007     *
14008     * <p>The animation starts only if at least one of the scrollbars is
14009     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
14010     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14011     * this method returns true, and false otherwise. If the animation is
14012     * started, this method calls {@link #invalidate()}; in that case the
14013     * caller should not call {@link #invalidate()}.</p>
14014     *
14015     * <p>This method should be invoked every time a subclass directly updates
14016     * the scroll parameters.</p>
14017     *
14018     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
14019     * and {@link #scrollTo(int, int)}.</p>
14020     *
14021     * @return true if the animation is played, false otherwise
14022     *
14023     * @see #awakenScrollBars(int)
14024     * @see #scrollBy(int, int)
14025     * @see #scrollTo(int, int)
14026     * @see #isHorizontalScrollBarEnabled()
14027     * @see #isVerticalScrollBarEnabled()
14028     * @see #setHorizontalScrollBarEnabled(boolean)
14029     * @see #setVerticalScrollBarEnabled(boolean)
14030     */
14031    protected boolean awakenScrollBars() {
14032        return mScrollCache != null &&
14033                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
14034    }
14035
14036    /**
14037     * Trigger the scrollbars to draw.
14038     * This method differs from awakenScrollBars() only in its default duration.
14039     * initialAwakenScrollBars() will show the scroll bars for longer than
14040     * usual to give the user more of a chance to notice them.
14041     *
14042     * @return true if the animation is played, false otherwise.
14043     */
14044    private boolean initialAwakenScrollBars() {
14045        return mScrollCache != null &&
14046                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
14047    }
14048
14049    /**
14050     * <p>
14051     * Trigger the scrollbars to draw. When invoked this method starts an
14052     * animation to fade the scrollbars out after a fixed delay. If a subclass
14053     * provides animated scrolling, the start delay should equal the duration of
14054     * the scrolling animation.
14055     * </p>
14056     *
14057     * <p>
14058     * The animation starts only if at least one of the scrollbars is enabled,
14059     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14060     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14061     * this method returns true, and false otherwise. If the animation is
14062     * started, this method calls {@link #invalidate()}; in that case the caller
14063     * should not call {@link #invalidate()}.
14064     * </p>
14065     *
14066     * <p>
14067     * This method should be invoked every time a subclass directly updates the
14068     * scroll parameters.
14069     * </p>
14070     *
14071     * @param startDelay the delay, in milliseconds, after which the animation
14072     *        should start; when the delay is 0, the animation starts
14073     *        immediately
14074     * @return true if the animation is played, false otherwise
14075     *
14076     * @see #scrollBy(int, int)
14077     * @see #scrollTo(int, int)
14078     * @see #isHorizontalScrollBarEnabled()
14079     * @see #isVerticalScrollBarEnabled()
14080     * @see #setHorizontalScrollBarEnabled(boolean)
14081     * @see #setVerticalScrollBarEnabled(boolean)
14082     */
14083    protected boolean awakenScrollBars(int startDelay) {
14084        return awakenScrollBars(startDelay, true);
14085    }
14086
14087    /**
14088     * <p>
14089     * Trigger the scrollbars to draw. When invoked this method starts an
14090     * animation to fade the scrollbars out after a fixed delay. If a subclass
14091     * provides animated scrolling, the start delay should equal the duration of
14092     * the scrolling animation.
14093     * </p>
14094     *
14095     * <p>
14096     * The animation starts only if at least one of the scrollbars is enabled,
14097     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14098     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14099     * this method returns true, and false otherwise. If the animation is
14100     * started, this method calls {@link #invalidate()} if the invalidate parameter
14101     * is set to true; in that case the caller
14102     * should not call {@link #invalidate()}.
14103     * </p>
14104     *
14105     * <p>
14106     * This method should be invoked every time a subclass directly updates the
14107     * scroll parameters.
14108     * </p>
14109     *
14110     * @param startDelay the delay, in milliseconds, after which the animation
14111     *        should start; when the delay is 0, the animation starts
14112     *        immediately
14113     *
14114     * @param invalidate Whether this method should call invalidate
14115     *
14116     * @return true if the animation is played, false otherwise
14117     *
14118     * @see #scrollBy(int, int)
14119     * @see #scrollTo(int, int)
14120     * @see #isHorizontalScrollBarEnabled()
14121     * @see #isVerticalScrollBarEnabled()
14122     * @see #setHorizontalScrollBarEnabled(boolean)
14123     * @see #setVerticalScrollBarEnabled(boolean)
14124     */
14125    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
14126        final ScrollabilityCache scrollCache = mScrollCache;
14127
14128        if (scrollCache == null || !scrollCache.fadeScrollBars) {
14129            return false;
14130        }
14131
14132        if (scrollCache.scrollBar == null) {
14133            scrollCache.scrollBar = new ScrollBarDrawable();
14134            scrollCache.scrollBar.setState(getDrawableState());
14135            scrollCache.scrollBar.setCallback(this);
14136        }
14137
14138        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
14139
14140            if (invalidate) {
14141                // Invalidate to show the scrollbars
14142                postInvalidateOnAnimation();
14143            }
14144
14145            if (scrollCache.state == ScrollabilityCache.OFF) {
14146                // FIXME: this is copied from WindowManagerService.
14147                // We should get this value from the system when it
14148                // is possible to do so.
14149                final int KEY_REPEAT_FIRST_DELAY = 750;
14150                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
14151            }
14152
14153            // Tell mScrollCache when we should start fading. This may
14154            // extend the fade start time if one was already scheduled
14155            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
14156            scrollCache.fadeStartTime = fadeStartTime;
14157            scrollCache.state = ScrollabilityCache.ON;
14158
14159            // Schedule our fader to run, unscheduling any old ones first
14160            if (mAttachInfo != null) {
14161                mAttachInfo.mHandler.removeCallbacks(scrollCache);
14162                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
14163            }
14164
14165            return true;
14166        }
14167
14168        return false;
14169    }
14170
14171    /**
14172     * Do not invalidate views which are not visible and which are not running an animation. They
14173     * will not get drawn and they should not set dirty flags as if they will be drawn
14174     */
14175    private boolean skipInvalidate() {
14176        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
14177                (!(mParent instanceof ViewGroup) ||
14178                        !((ViewGroup) mParent).isViewTransitioning(this));
14179    }
14180
14181    /**
14182     * Mark the area defined by dirty as needing to be drawn. If the view is
14183     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14184     * point in the future.
14185     * <p>
14186     * This must be called from a UI thread. To call from a non-UI thread, call
14187     * {@link #postInvalidate()}.
14188     * <p>
14189     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
14190     * {@code dirty}.
14191     *
14192     * @param dirty the rectangle representing the bounds of the dirty region
14193     */
14194    public void invalidate(Rect dirty) {
14195        final int scrollX = mScrollX;
14196        final int scrollY = mScrollY;
14197        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
14198                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
14199    }
14200
14201    /**
14202     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
14203     * coordinates of the dirty rect are relative to the view. If the view is
14204     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14205     * point in the future.
14206     * <p>
14207     * This must be called from a UI thread. To call from a non-UI thread, call
14208     * {@link #postInvalidate()}.
14209     *
14210     * @param l the left position of the dirty region
14211     * @param t the top position of the dirty region
14212     * @param r the right position of the dirty region
14213     * @param b the bottom position of the dirty region
14214     */
14215    public void invalidate(int l, int t, int r, int b) {
14216        final int scrollX = mScrollX;
14217        final int scrollY = mScrollY;
14218        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
14219    }
14220
14221    /**
14222     * Invalidate the whole view. If the view is visible,
14223     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
14224     * the future.
14225     * <p>
14226     * This must be called from a UI thread. To call from a non-UI thread, call
14227     * {@link #postInvalidate()}.
14228     */
14229    public void invalidate() {
14230        invalidate(true);
14231    }
14232
14233    /**
14234     * This is where the invalidate() work actually happens. A full invalidate()
14235     * causes the drawing cache to be invalidated, but this function can be
14236     * called with invalidateCache set to false to skip that invalidation step
14237     * for cases that do not need it (for example, a component that remains at
14238     * the same dimensions with the same content).
14239     *
14240     * @param invalidateCache Whether the drawing cache for this view should be
14241     *            invalidated as well. This is usually true for a full
14242     *            invalidate, but may be set to false if the View's contents or
14243     *            dimensions have not changed.
14244     * @hide
14245     */
14246    public void invalidate(boolean invalidateCache) {
14247        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
14248    }
14249
14250    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
14251            boolean fullInvalidate) {
14252        if (mGhostView != null) {
14253            mGhostView.invalidate(true);
14254            return;
14255        }
14256
14257        if (skipInvalidate()) {
14258            return;
14259        }
14260
14261        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
14262                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
14263                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
14264                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
14265            if (fullInvalidate) {
14266                mLastIsOpaque = isOpaque();
14267                mPrivateFlags &= ~PFLAG_DRAWN;
14268            }
14269
14270            mPrivateFlags |= PFLAG_DIRTY;
14271
14272            if (invalidateCache) {
14273                mPrivateFlags |= PFLAG_INVALIDATED;
14274                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14275            }
14276
14277            // Propagate the damage rectangle to the parent view.
14278            final AttachInfo ai = mAttachInfo;
14279            final ViewParent p = mParent;
14280            if (p != null && ai != null && l < r && t < b) {
14281                final Rect damage = ai.mTmpInvalRect;
14282                damage.set(l, t, r, b);
14283                p.invalidateChild(this, damage);
14284            }
14285
14286            // Damage the entire projection receiver, if necessary.
14287            if (mBackground != null && mBackground.isProjected()) {
14288                final View receiver = getProjectionReceiver();
14289                if (receiver != null) {
14290                    receiver.damageInParent();
14291                }
14292            }
14293        }
14294    }
14295
14296    /**
14297     * @return this view's projection receiver, or {@code null} if none exists
14298     */
14299    private View getProjectionReceiver() {
14300        ViewParent p = getParent();
14301        while (p != null && p instanceof View) {
14302            final View v = (View) p;
14303            if (v.isProjectionReceiver()) {
14304                return v;
14305            }
14306            p = p.getParent();
14307        }
14308
14309        return null;
14310    }
14311
14312    /**
14313     * @return whether the view is a projection receiver
14314     */
14315    private boolean isProjectionReceiver() {
14316        return mBackground != null;
14317    }
14318
14319    /**
14320     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
14321     * set any flags or handle all of the cases handled by the default invalidation methods.
14322     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
14323     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
14324     * walk up the hierarchy, transforming the dirty rect as necessary.
14325     *
14326     * The method also handles normal invalidation logic if display list properties are not
14327     * being used in this view. The invalidateParent and forceRedraw flags are used by that
14328     * backup approach, to handle these cases used in the various property-setting methods.
14329     *
14330     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
14331     * are not being used in this view
14332     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
14333     * list properties are not being used in this view
14334     */
14335    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
14336        if (!isHardwareAccelerated()
14337                || !mRenderNode.isValid()
14338                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
14339            if (invalidateParent) {
14340                invalidateParentCaches();
14341            }
14342            if (forceRedraw) {
14343                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14344            }
14345            invalidate(false);
14346        } else {
14347            damageInParent();
14348        }
14349    }
14350
14351    /**
14352     * Tells the parent view to damage this view's bounds.
14353     *
14354     * @hide
14355     */
14356    protected void damageInParent() {
14357        final AttachInfo ai = mAttachInfo;
14358        final ViewParent p = mParent;
14359        if (p != null && ai != null) {
14360            final Rect r = ai.mTmpInvalRect;
14361            r.set(0, 0, mRight - mLeft, mBottom - mTop);
14362            if (mParent instanceof ViewGroup) {
14363                ((ViewGroup) mParent).damageChild(this, r);
14364            } else {
14365                mParent.invalidateChild(this, r);
14366            }
14367        }
14368    }
14369
14370    /**
14371     * Utility method to transform a given Rect by the current matrix of this view.
14372     */
14373    void transformRect(final Rect rect) {
14374        if (!getMatrix().isIdentity()) {
14375            RectF boundingRect = mAttachInfo.mTmpTransformRect;
14376            boundingRect.set(rect);
14377            getMatrix().mapRect(boundingRect);
14378            rect.set((int) Math.floor(boundingRect.left),
14379                    (int) Math.floor(boundingRect.top),
14380                    (int) Math.ceil(boundingRect.right),
14381                    (int) Math.ceil(boundingRect.bottom));
14382        }
14383    }
14384
14385    /**
14386     * Used to indicate that the parent of this view should clear its caches. This functionality
14387     * is used to force the parent to rebuild its display list (when hardware-accelerated),
14388     * which is necessary when various parent-managed properties of the view change, such as
14389     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
14390     * clears the parent caches and does not causes an invalidate event.
14391     *
14392     * @hide
14393     */
14394    protected void invalidateParentCaches() {
14395        if (mParent instanceof View) {
14396            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
14397        }
14398    }
14399
14400    /**
14401     * Used to indicate that the parent of this view should be invalidated. This functionality
14402     * is used to force the parent to rebuild its display list (when hardware-accelerated),
14403     * which is necessary when various parent-managed properties of the view change, such as
14404     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
14405     * an invalidation event to the parent.
14406     *
14407     * @hide
14408     */
14409    protected void invalidateParentIfNeeded() {
14410        if (isHardwareAccelerated() && mParent instanceof View) {
14411            ((View) mParent).invalidate(true);
14412        }
14413    }
14414
14415    /**
14416     * @hide
14417     */
14418    protected void invalidateParentIfNeededAndWasQuickRejected() {
14419        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
14420            // View was rejected last time it was drawn by its parent; this may have changed
14421            invalidateParentIfNeeded();
14422        }
14423    }
14424
14425    /**
14426     * Indicates whether this View is opaque. An opaque View guarantees that it will
14427     * draw all the pixels overlapping its bounds using a fully opaque color.
14428     *
14429     * Subclasses of View should override this method whenever possible to indicate
14430     * whether an instance is opaque. Opaque Views are treated in a special way by
14431     * the View hierarchy, possibly allowing it to perform optimizations during
14432     * invalidate/draw passes.
14433     *
14434     * @return True if this View is guaranteed to be fully opaque, false otherwise.
14435     */
14436    @ViewDebug.ExportedProperty(category = "drawing")
14437    public boolean isOpaque() {
14438        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
14439                getFinalAlpha() >= 1.0f;
14440    }
14441
14442    /**
14443     * @hide
14444     */
14445    protected void computeOpaqueFlags() {
14446        // Opaque if:
14447        //   - Has a background
14448        //   - Background is opaque
14449        //   - Doesn't have scrollbars or scrollbars overlay
14450
14451        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
14452            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
14453        } else {
14454            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
14455        }
14456
14457        final int flags = mViewFlags;
14458        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
14459                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
14460                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
14461            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
14462        } else {
14463            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
14464        }
14465    }
14466
14467    /**
14468     * @hide
14469     */
14470    protected boolean hasOpaqueScrollbars() {
14471        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
14472    }
14473
14474    /**
14475     * @return A handler associated with the thread running the View. This
14476     * handler can be used to pump events in the UI events queue.
14477     */
14478    public Handler getHandler() {
14479        final AttachInfo attachInfo = mAttachInfo;
14480        if (attachInfo != null) {
14481            return attachInfo.mHandler;
14482        }
14483        return null;
14484    }
14485
14486    /**
14487     * Returns the queue of runnable for this view.
14488     *
14489     * @return the queue of runnables for this view
14490     */
14491    private HandlerActionQueue getRunQueue() {
14492        if (mRunQueue == null) {
14493            mRunQueue = new HandlerActionQueue();
14494        }
14495        return mRunQueue;
14496    }
14497
14498    /**
14499     * Gets the view root associated with the View.
14500     * @return The view root, or null if none.
14501     * @hide
14502     */
14503    public ViewRootImpl getViewRootImpl() {
14504        if (mAttachInfo != null) {
14505            return mAttachInfo.mViewRootImpl;
14506        }
14507        return null;
14508    }
14509
14510    /**
14511     * @hide
14512     */
14513    public ThreadedRenderer getThreadedRenderer() {
14514        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
14515    }
14516
14517    /**
14518     * <p>Causes the Runnable to be added to the message queue.
14519     * The runnable will be run on the user interface thread.</p>
14520     *
14521     * @param action The Runnable that will be executed.
14522     *
14523     * @return Returns true if the Runnable was successfully placed in to the
14524     *         message queue.  Returns false on failure, usually because the
14525     *         looper processing the message queue is exiting.
14526     *
14527     * @see #postDelayed
14528     * @see #removeCallbacks
14529     */
14530    public boolean post(Runnable action) {
14531        final AttachInfo attachInfo = mAttachInfo;
14532        if (attachInfo != null) {
14533            return attachInfo.mHandler.post(action);
14534        }
14535
14536        // Postpone the runnable until we know on which thread it needs to run.
14537        // Assume that the runnable will be successfully placed after attach.
14538        getRunQueue().post(action);
14539        return true;
14540    }
14541
14542    /**
14543     * <p>Causes the Runnable to be added to the message queue, to be run
14544     * after the specified amount of time elapses.
14545     * The runnable will be run on the user interface thread.</p>
14546     *
14547     * @param action The Runnable that will be executed.
14548     * @param delayMillis The delay (in milliseconds) until the Runnable
14549     *        will be executed.
14550     *
14551     * @return true if the Runnable was successfully placed in to the
14552     *         message queue.  Returns false on failure, usually because the
14553     *         looper processing the message queue is exiting.  Note that a
14554     *         result of true does not mean the Runnable will be processed --
14555     *         if the looper is quit before the delivery time of the message
14556     *         occurs then the message will be dropped.
14557     *
14558     * @see #post
14559     * @see #removeCallbacks
14560     */
14561    public boolean postDelayed(Runnable action, long delayMillis) {
14562        final AttachInfo attachInfo = mAttachInfo;
14563        if (attachInfo != null) {
14564            return attachInfo.mHandler.postDelayed(action, delayMillis);
14565        }
14566
14567        // Postpone the runnable until we know on which thread it needs to run.
14568        // Assume that the runnable will be successfully placed after attach.
14569        getRunQueue().postDelayed(action, delayMillis);
14570        return true;
14571    }
14572
14573    /**
14574     * <p>Causes the Runnable to execute on the next animation time step.
14575     * The runnable will be run on the user interface thread.</p>
14576     *
14577     * @param action The Runnable that will be executed.
14578     *
14579     * @see #postOnAnimationDelayed
14580     * @see #removeCallbacks
14581     */
14582    public void postOnAnimation(Runnable action) {
14583        final AttachInfo attachInfo = mAttachInfo;
14584        if (attachInfo != null) {
14585            attachInfo.mViewRootImpl.mChoreographer.postCallback(
14586                    Choreographer.CALLBACK_ANIMATION, action, null);
14587        } else {
14588            // Postpone the runnable until we know
14589            // on which thread it needs to run.
14590            getRunQueue().post(action);
14591        }
14592    }
14593
14594    /**
14595     * <p>Causes the Runnable to execute on the next animation time step,
14596     * after the specified amount of time elapses.
14597     * The runnable will be run on the user interface thread.</p>
14598     *
14599     * @param action The Runnable that will be executed.
14600     * @param delayMillis The delay (in milliseconds) until the Runnable
14601     *        will be executed.
14602     *
14603     * @see #postOnAnimation
14604     * @see #removeCallbacks
14605     */
14606    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
14607        final AttachInfo attachInfo = mAttachInfo;
14608        if (attachInfo != null) {
14609            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
14610                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
14611        } else {
14612            // Postpone the runnable until we know
14613            // on which thread it needs to run.
14614            getRunQueue().postDelayed(action, delayMillis);
14615        }
14616    }
14617
14618    /**
14619     * <p>Removes the specified Runnable from the message queue.</p>
14620     *
14621     * @param action The Runnable to remove from the message handling queue
14622     *
14623     * @return true if this view could ask the Handler to remove the Runnable,
14624     *         false otherwise. When the returned value is true, the Runnable
14625     *         may or may not have been actually removed from the message queue
14626     *         (for instance, if the Runnable was not in the queue already.)
14627     *
14628     * @see #post
14629     * @see #postDelayed
14630     * @see #postOnAnimation
14631     * @see #postOnAnimationDelayed
14632     */
14633    public boolean removeCallbacks(Runnable action) {
14634        if (action != null) {
14635            final AttachInfo attachInfo = mAttachInfo;
14636            if (attachInfo != null) {
14637                attachInfo.mHandler.removeCallbacks(action);
14638                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14639                        Choreographer.CALLBACK_ANIMATION, action, null);
14640            }
14641            getRunQueue().removeCallbacks(action);
14642        }
14643        return true;
14644    }
14645
14646    /**
14647     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
14648     * Use this to invalidate the View from a non-UI thread.</p>
14649     *
14650     * <p>This method can be invoked from outside of the UI thread
14651     * only when this View is attached to a window.</p>
14652     *
14653     * @see #invalidate()
14654     * @see #postInvalidateDelayed(long)
14655     */
14656    public void postInvalidate() {
14657        postInvalidateDelayed(0);
14658    }
14659
14660    /**
14661     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14662     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
14663     *
14664     * <p>This method can be invoked from outside of the UI thread
14665     * only when this View is attached to a window.</p>
14666     *
14667     * @param left The left coordinate of the rectangle to invalidate.
14668     * @param top The top coordinate of the rectangle to invalidate.
14669     * @param right The right coordinate of the rectangle to invalidate.
14670     * @param bottom The bottom coordinate of the rectangle to invalidate.
14671     *
14672     * @see #invalidate(int, int, int, int)
14673     * @see #invalidate(Rect)
14674     * @see #postInvalidateDelayed(long, int, int, int, int)
14675     */
14676    public void postInvalidate(int left, int top, int right, int bottom) {
14677        postInvalidateDelayed(0, left, top, right, bottom);
14678    }
14679
14680    /**
14681     * <p>Cause an invalidate to happen on a subsequent cycle through the event
14682     * loop. Waits for the specified amount of time.</p>
14683     *
14684     * <p>This method can be invoked from outside of the UI thread
14685     * only when this View is attached to a window.</p>
14686     *
14687     * @param delayMilliseconds the duration in milliseconds to delay the
14688     *         invalidation by
14689     *
14690     * @see #invalidate()
14691     * @see #postInvalidate()
14692     */
14693    public void postInvalidateDelayed(long delayMilliseconds) {
14694        // We try only with the AttachInfo because there's no point in invalidating
14695        // if we are not attached to our window
14696        final AttachInfo attachInfo = mAttachInfo;
14697        if (attachInfo != null) {
14698            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
14699        }
14700    }
14701
14702    /**
14703     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14704     * through the event loop. Waits for the specified amount of time.</p>
14705     *
14706     * <p>This method can be invoked from outside of the UI thread
14707     * only when this View is attached to a window.</p>
14708     *
14709     * @param delayMilliseconds the duration in milliseconds to delay the
14710     *         invalidation by
14711     * @param left The left coordinate of the rectangle to invalidate.
14712     * @param top The top coordinate of the rectangle to invalidate.
14713     * @param right The right coordinate of the rectangle to invalidate.
14714     * @param bottom The bottom coordinate of the rectangle to invalidate.
14715     *
14716     * @see #invalidate(int, int, int, int)
14717     * @see #invalidate(Rect)
14718     * @see #postInvalidate(int, int, int, int)
14719     */
14720    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
14721            int right, int bottom) {
14722
14723        // We try only with the AttachInfo because there's no point in invalidating
14724        // if we are not attached to our window
14725        final AttachInfo attachInfo = mAttachInfo;
14726        if (attachInfo != null) {
14727            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14728            info.target = this;
14729            info.left = left;
14730            info.top = top;
14731            info.right = right;
14732            info.bottom = bottom;
14733
14734            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
14735        }
14736    }
14737
14738    /**
14739     * <p>Cause an invalidate to happen on the next animation time step, typically the
14740     * next display frame.</p>
14741     *
14742     * <p>This method can be invoked from outside of the UI thread
14743     * only when this View is attached to a window.</p>
14744     *
14745     * @see #invalidate()
14746     */
14747    public void postInvalidateOnAnimation() {
14748        // We try only with the AttachInfo because there's no point in invalidating
14749        // if we are not attached to our window
14750        final AttachInfo attachInfo = mAttachInfo;
14751        if (attachInfo != null) {
14752            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
14753        }
14754    }
14755
14756    /**
14757     * <p>Cause an invalidate of the specified area to happen on the next animation
14758     * time step, typically the next display frame.</p>
14759     *
14760     * <p>This method can be invoked from outside of the UI thread
14761     * only when this View is attached to a window.</p>
14762     *
14763     * @param left The left coordinate of the rectangle to invalidate.
14764     * @param top The top coordinate of the rectangle to invalidate.
14765     * @param right The right coordinate of the rectangle to invalidate.
14766     * @param bottom The bottom coordinate of the rectangle to invalidate.
14767     *
14768     * @see #invalidate(int, int, int, int)
14769     * @see #invalidate(Rect)
14770     */
14771    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
14772        // We try only with the AttachInfo because there's no point in invalidating
14773        // if we are not attached to our window
14774        final AttachInfo attachInfo = mAttachInfo;
14775        if (attachInfo != null) {
14776            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14777            info.target = this;
14778            info.left = left;
14779            info.top = top;
14780            info.right = right;
14781            info.bottom = bottom;
14782
14783            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
14784        }
14785    }
14786
14787    /**
14788     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
14789     * This event is sent at most once every
14790     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
14791     */
14792    private void postSendViewScrolledAccessibilityEventCallback() {
14793        if (mSendViewScrolledAccessibilityEvent == null) {
14794            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
14795        }
14796        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
14797            mSendViewScrolledAccessibilityEvent.mIsPending = true;
14798            postDelayed(mSendViewScrolledAccessibilityEvent,
14799                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
14800        }
14801    }
14802
14803    /**
14804     * Called by a parent to request that a child update its values for mScrollX
14805     * and mScrollY if necessary. This will typically be done if the child is
14806     * animating a scroll using a {@link android.widget.Scroller Scroller}
14807     * object.
14808     */
14809    public void computeScroll() {
14810    }
14811
14812    /**
14813     * <p>Indicate whether the horizontal edges are faded when the view is
14814     * scrolled horizontally.</p>
14815     *
14816     * @return true if the horizontal edges should are faded on scroll, false
14817     *         otherwise
14818     *
14819     * @see #setHorizontalFadingEdgeEnabled(boolean)
14820     *
14821     * @attr ref android.R.styleable#View_requiresFadingEdge
14822     */
14823    public boolean isHorizontalFadingEdgeEnabled() {
14824        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
14825    }
14826
14827    /**
14828     * <p>Define whether the horizontal edges should be faded when this view
14829     * is scrolled horizontally.</p>
14830     *
14831     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
14832     *                                    be faded when the view is scrolled
14833     *                                    horizontally
14834     *
14835     * @see #isHorizontalFadingEdgeEnabled()
14836     *
14837     * @attr ref android.R.styleable#View_requiresFadingEdge
14838     */
14839    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
14840        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
14841            if (horizontalFadingEdgeEnabled) {
14842                initScrollCache();
14843            }
14844
14845            mViewFlags ^= FADING_EDGE_HORIZONTAL;
14846        }
14847    }
14848
14849    /**
14850     * <p>Indicate whether the vertical edges are faded when the view is
14851     * scrolled horizontally.</p>
14852     *
14853     * @return true if the vertical edges should are faded on scroll, false
14854     *         otherwise
14855     *
14856     * @see #setVerticalFadingEdgeEnabled(boolean)
14857     *
14858     * @attr ref android.R.styleable#View_requiresFadingEdge
14859     */
14860    public boolean isVerticalFadingEdgeEnabled() {
14861        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
14862    }
14863
14864    /**
14865     * <p>Define whether the vertical edges should be faded when this view
14866     * is scrolled vertically.</p>
14867     *
14868     * @param verticalFadingEdgeEnabled true if the vertical edges should
14869     *                                  be faded when the view is scrolled
14870     *                                  vertically
14871     *
14872     * @see #isVerticalFadingEdgeEnabled()
14873     *
14874     * @attr ref android.R.styleable#View_requiresFadingEdge
14875     */
14876    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
14877        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
14878            if (verticalFadingEdgeEnabled) {
14879                initScrollCache();
14880            }
14881
14882            mViewFlags ^= FADING_EDGE_VERTICAL;
14883        }
14884    }
14885
14886    /**
14887     * Returns the strength, or intensity, of the top faded edge. The strength is
14888     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14889     * returns 0.0 or 1.0 but no value in between.
14890     *
14891     * Subclasses should override this method to provide a smoother fade transition
14892     * when scrolling occurs.
14893     *
14894     * @return the intensity of the top fade as a float between 0.0f and 1.0f
14895     */
14896    protected float getTopFadingEdgeStrength() {
14897        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
14898    }
14899
14900    /**
14901     * Returns the strength, or intensity, of the bottom faded edge. The strength is
14902     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14903     * returns 0.0 or 1.0 but no value in between.
14904     *
14905     * Subclasses should override this method to provide a smoother fade transition
14906     * when scrolling occurs.
14907     *
14908     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
14909     */
14910    protected float getBottomFadingEdgeStrength() {
14911        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
14912                computeVerticalScrollRange() ? 1.0f : 0.0f;
14913    }
14914
14915    /**
14916     * Returns the strength, or intensity, of the left faded edge. The strength is
14917     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14918     * returns 0.0 or 1.0 but no value in between.
14919     *
14920     * Subclasses should override this method to provide a smoother fade transition
14921     * when scrolling occurs.
14922     *
14923     * @return the intensity of the left fade as a float between 0.0f and 1.0f
14924     */
14925    protected float getLeftFadingEdgeStrength() {
14926        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
14927    }
14928
14929    /**
14930     * Returns the strength, or intensity, of the right faded edge. The strength is
14931     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
14932     * returns 0.0 or 1.0 but no value in between.
14933     *
14934     * Subclasses should override this method to provide a smoother fade transition
14935     * when scrolling occurs.
14936     *
14937     * @return the intensity of the right fade as a float between 0.0f and 1.0f
14938     */
14939    protected float getRightFadingEdgeStrength() {
14940        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
14941                computeHorizontalScrollRange() ? 1.0f : 0.0f;
14942    }
14943
14944    /**
14945     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
14946     * scrollbar is not drawn by default.</p>
14947     *
14948     * @return true if the horizontal scrollbar should be painted, false
14949     *         otherwise
14950     *
14951     * @see #setHorizontalScrollBarEnabled(boolean)
14952     */
14953    public boolean isHorizontalScrollBarEnabled() {
14954        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14955    }
14956
14957    /**
14958     * <p>Define whether the horizontal scrollbar should be drawn or not. The
14959     * scrollbar is not drawn by default.</p>
14960     *
14961     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
14962     *                                   be painted
14963     *
14964     * @see #isHorizontalScrollBarEnabled()
14965     */
14966    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
14967        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
14968            mViewFlags ^= SCROLLBARS_HORIZONTAL;
14969            computeOpaqueFlags();
14970            resolvePadding();
14971        }
14972    }
14973
14974    /**
14975     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
14976     * scrollbar is not drawn by default.</p>
14977     *
14978     * @return true if the vertical scrollbar should be painted, false
14979     *         otherwise
14980     *
14981     * @see #setVerticalScrollBarEnabled(boolean)
14982     */
14983    public boolean isVerticalScrollBarEnabled() {
14984        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
14985    }
14986
14987    /**
14988     * <p>Define whether the vertical scrollbar should be drawn or not. The
14989     * scrollbar is not drawn by default.</p>
14990     *
14991     * @param verticalScrollBarEnabled true if the vertical scrollbar should
14992     *                                 be painted
14993     *
14994     * @see #isVerticalScrollBarEnabled()
14995     */
14996    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
14997        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
14998            mViewFlags ^= SCROLLBARS_VERTICAL;
14999            computeOpaqueFlags();
15000            resolvePadding();
15001        }
15002    }
15003
15004    /**
15005     * @hide
15006     */
15007    protected void recomputePadding() {
15008        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15009    }
15010
15011    /**
15012     * Define whether scrollbars will fade when the view is not scrolling.
15013     *
15014     * @param fadeScrollbars whether to enable fading
15015     *
15016     * @attr ref android.R.styleable#View_fadeScrollbars
15017     */
15018    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
15019        initScrollCache();
15020        final ScrollabilityCache scrollabilityCache = mScrollCache;
15021        scrollabilityCache.fadeScrollBars = fadeScrollbars;
15022        if (fadeScrollbars) {
15023            scrollabilityCache.state = ScrollabilityCache.OFF;
15024        } else {
15025            scrollabilityCache.state = ScrollabilityCache.ON;
15026        }
15027    }
15028
15029    /**
15030     *
15031     * Returns true if scrollbars will fade when this view is not scrolling
15032     *
15033     * @return true if scrollbar fading is enabled
15034     *
15035     * @attr ref android.R.styleable#View_fadeScrollbars
15036     */
15037    public boolean isScrollbarFadingEnabled() {
15038        return mScrollCache != null && mScrollCache.fadeScrollBars;
15039    }
15040
15041    /**
15042     *
15043     * Returns the delay before scrollbars fade.
15044     *
15045     * @return the delay before scrollbars fade
15046     *
15047     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15048     */
15049    public int getScrollBarDefaultDelayBeforeFade() {
15050        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
15051                mScrollCache.scrollBarDefaultDelayBeforeFade;
15052    }
15053
15054    /**
15055     * Define the delay before scrollbars fade.
15056     *
15057     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
15058     *
15059     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15060     */
15061    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
15062        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
15063    }
15064
15065    /**
15066     *
15067     * Returns the scrollbar fade duration.
15068     *
15069     * @return the scrollbar fade duration, in milliseconds
15070     *
15071     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15072     */
15073    public int getScrollBarFadeDuration() {
15074        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
15075                mScrollCache.scrollBarFadeDuration;
15076    }
15077
15078    /**
15079     * Define the scrollbar fade duration.
15080     *
15081     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
15082     *
15083     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15084     */
15085    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
15086        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
15087    }
15088
15089    /**
15090     *
15091     * Returns the scrollbar size.
15092     *
15093     * @return the scrollbar size
15094     *
15095     * @attr ref android.R.styleable#View_scrollbarSize
15096     */
15097    public int getScrollBarSize() {
15098        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
15099                mScrollCache.scrollBarSize;
15100    }
15101
15102    /**
15103     * Define the scrollbar size.
15104     *
15105     * @param scrollBarSize - the scrollbar size
15106     *
15107     * @attr ref android.R.styleable#View_scrollbarSize
15108     */
15109    public void setScrollBarSize(int scrollBarSize) {
15110        getScrollCache().scrollBarSize = scrollBarSize;
15111    }
15112
15113    /**
15114     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
15115     * inset. When inset, they add to the padding of the view. And the scrollbars
15116     * can be drawn inside the padding area or on the edge of the view. For example,
15117     * if a view has a background drawable and you want to draw the scrollbars
15118     * inside the padding specified by the drawable, you can use
15119     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
15120     * appear at the edge of the view, ignoring the padding, then you can use
15121     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
15122     * @param style the style of the scrollbars. Should be one of
15123     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
15124     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
15125     * @see #SCROLLBARS_INSIDE_OVERLAY
15126     * @see #SCROLLBARS_INSIDE_INSET
15127     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15128     * @see #SCROLLBARS_OUTSIDE_INSET
15129     *
15130     * @attr ref android.R.styleable#View_scrollbarStyle
15131     */
15132    public void setScrollBarStyle(@ScrollBarStyle int style) {
15133        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
15134            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
15135            computeOpaqueFlags();
15136            resolvePadding();
15137        }
15138    }
15139
15140    /**
15141     * <p>Returns the current scrollbar style.</p>
15142     * @return the current scrollbar style
15143     * @see #SCROLLBARS_INSIDE_OVERLAY
15144     * @see #SCROLLBARS_INSIDE_INSET
15145     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15146     * @see #SCROLLBARS_OUTSIDE_INSET
15147     *
15148     * @attr ref android.R.styleable#View_scrollbarStyle
15149     */
15150    @ViewDebug.ExportedProperty(mapping = {
15151            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
15152            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
15153            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
15154            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
15155    })
15156    @ScrollBarStyle
15157    public int getScrollBarStyle() {
15158        return mViewFlags & SCROLLBARS_STYLE_MASK;
15159    }
15160
15161    /**
15162     * <p>Compute the horizontal range that the horizontal scrollbar
15163     * represents.</p>
15164     *
15165     * <p>The range is expressed in arbitrary units that must be the same as the
15166     * units used by {@link #computeHorizontalScrollExtent()} and
15167     * {@link #computeHorizontalScrollOffset()}.</p>
15168     *
15169     * <p>The default range is the drawing width of this view.</p>
15170     *
15171     * @return the total horizontal range represented by the horizontal
15172     *         scrollbar
15173     *
15174     * @see #computeHorizontalScrollExtent()
15175     * @see #computeHorizontalScrollOffset()
15176     * @see android.widget.ScrollBarDrawable
15177     */
15178    protected int computeHorizontalScrollRange() {
15179        return getWidth();
15180    }
15181
15182    /**
15183     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
15184     * within the horizontal range. This value is used to compute the position
15185     * of the thumb within the scrollbar's track.</p>
15186     *
15187     * <p>The range is expressed in arbitrary units that must be the same as the
15188     * units used by {@link #computeHorizontalScrollRange()} and
15189     * {@link #computeHorizontalScrollExtent()}.</p>
15190     *
15191     * <p>The default offset is the scroll offset of this view.</p>
15192     *
15193     * @return the horizontal offset of the scrollbar's thumb
15194     *
15195     * @see #computeHorizontalScrollRange()
15196     * @see #computeHorizontalScrollExtent()
15197     * @see android.widget.ScrollBarDrawable
15198     */
15199    protected int computeHorizontalScrollOffset() {
15200        return mScrollX;
15201    }
15202
15203    /**
15204     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
15205     * within the horizontal range. This value is used to compute the length
15206     * of the thumb within the scrollbar's track.</p>
15207     *
15208     * <p>The range is expressed in arbitrary units that must be the same as the
15209     * units used by {@link #computeHorizontalScrollRange()} and
15210     * {@link #computeHorizontalScrollOffset()}.</p>
15211     *
15212     * <p>The default extent is the drawing width of this view.</p>
15213     *
15214     * @return the horizontal extent of the scrollbar's thumb
15215     *
15216     * @see #computeHorizontalScrollRange()
15217     * @see #computeHorizontalScrollOffset()
15218     * @see android.widget.ScrollBarDrawable
15219     */
15220    protected int computeHorizontalScrollExtent() {
15221        return getWidth();
15222    }
15223
15224    /**
15225     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
15226     *
15227     * <p>The range is expressed in arbitrary units that must be the same as the
15228     * units used by {@link #computeVerticalScrollExtent()} and
15229     * {@link #computeVerticalScrollOffset()}.</p>
15230     *
15231     * @return the total vertical range represented by the vertical scrollbar
15232     *
15233     * <p>The default range is the drawing height of this view.</p>
15234     *
15235     * @see #computeVerticalScrollExtent()
15236     * @see #computeVerticalScrollOffset()
15237     * @see android.widget.ScrollBarDrawable
15238     */
15239    protected int computeVerticalScrollRange() {
15240        return getHeight();
15241    }
15242
15243    /**
15244     * <p>Compute the vertical offset of the vertical scrollbar's thumb
15245     * within the horizontal range. This value is used to compute the position
15246     * of the thumb within the scrollbar's track.</p>
15247     *
15248     * <p>The range is expressed in arbitrary units that must be the same as the
15249     * units used by {@link #computeVerticalScrollRange()} and
15250     * {@link #computeVerticalScrollExtent()}.</p>
15251     *
15252     * <p>The default offset is the scroll offset of this view.</p>
15253     *
15254     * @return the vertical offset of the scrollbar's thumb
15255     *
15256     * @see #computeVerticalScrollRange()
15257     * @see #computeVerticalScrollExtent()
15258     * @see android.widget.ScrollBarDrawable
15259     */
15260    protected int computeVerticalScrollOffset() {
15261        return mScrollY;
15262    }
15263
15264    /**
15265     * <p>Compute the vertical extent of the vertical scrollbar's thumb
15266     * within the vertical range. This value is used to compute the length
15267     * of the thumb within the scrollbar's track.</p>
15268     *
15269     * <p>The range is expressed in arbitrary units that must be the same as the
15270     * units used by {@link #computeVerticalScrollRange()} and
15271     * {@link #computeVerticalScrollOffset()}.</p>
15272     *
15273     * <p>The default extent is the drawing height of this view.</p>
15274     *
15275     * @return the vertical extent of the scrollbar's thumb
15276     *
15277     * @see #computeVerticalScrollRange()
15278     * @see #computeVerticalScrollOffset()
15279     * @see android.widget.ScrollBarDrawable
15280     */
15281    protected int computeVerticalScrollExtent() {
15282        return getHeight();
15283    }
15284
15285    /**
15286     * Check if this view can be scrolled horizontally in a certain direction.
15287     *
15288     * @param direction Negative to check scrolling left, positive to check scrolling right.
15289     * @return true if this view can be scrolled in the specified direction, false otherwise.
15290     */
15291    public boolean canScrollHorizontally(int direction) {
15292        final int offset = computeHorizontalScrollOffset();
15293        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
15294        if (range == 0) return false;
15295        if (direction < 0) {
15296            return offset > 0;
15297        } else {
15298            return offset < range - 1;
15299        }
15300    }
15301
15302    /**
15303     * Check if this view can be scrolled vertically in a certain direction.
15304     *
15305     * @param direction Negative to check scrolling up, positive to check scrolling down.
15306     * @return true if this view can be scrolled in the specified direction, false otherwise.
15307     */
15308    public boolean canScrollVertically(int direction) {
15309        final int offset = computeVerticalScrollOffset();
15310        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
15311        if (range == 0) return false;
15312        if (direction < 0) {
15313            return offset > 0;
15314        } else {
15315            return offset < range - 1;
15316        }
15317    }
15318
15319    void getScrollIndicatorBounds(@NonNull Rect out) {
15320        out.left = mScrollX;
15321        out.right = mScrollX + mRight - mLeft;
15322        out.top = mScrollY;
15323        out.bottom = mScrollY + mBottom - mTop;
15324    }
15325
15326    private void onDrawScrollIndicators(Canvas c) {
15327        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
15328            // No scroll indicators enabled.
15329            return;
15330        }
15331
15332        final Drawable dr = mScrollIndicatorDrawable;
15333        if (dr == null) {
15334            // Scroll indicators aren't supported here.
15335            return;
15336        }
15337
15338        final int h = dr.getIntrinsicHeight();
15339        final int w = dr.getIntrinsicWidth();
15340        final Rect rect = mAttachInfo.mTmpInvalRect;
15341        getScrollIndicatorBounds(rect);
15342
15343        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
15344            final boolean canScrollUp = canScrollVertically(-1);
15345            if (canScrollUp) {
15346                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
15347                dr.draw(c);
15348            }
15349        }
15350
15351        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
15352            final boolean canScrollDown = canScrollVertically(1);
15353            if (canScrollDown) {
15354                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
15355                dr.draw(c);
15356            }
15357        }
15358
15359        final int leftRtl;
15360        final int rightRtl;
15361        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15362            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
15363            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
15364        } else {
15365            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
15366            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
15367        }
15368
15369        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
15370        if ((mPrivateFlags3 & leftMask) != 0) {
15371            final boolean canScrollLeft = canScrollHorizontally(-1);
15372            if (canScrollLeft) {
15373                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
15374                dr.draw(c);
15375            }
15376        }
15377
15378        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
15379        if ((mPrivateFlags3 & rightMask) != 0) {
15380            final boolean canScrollRight = canScrollHorizontally(1);
15381            if (canScrollRight) {
15382                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
15383                dr.draw(c);
15384            }
15385        }
15386    }
15387
15388    private void getHorizontalScrollBarBounds(Rect bounds) {
15389        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
15390        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
15391                && !isVerticalScrollBarHidden();
15392        final int size = getHorizontalScrollbarHeight();
15393        final int verticalScrollBarGap = drawVerticalScrollBar ?
15394                getVerticalScrollbarWidth() : 0;
15395        final int width = mRight - mLeft;
15396        final int height = mBottom - mTop;
15397        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
15398        bounds.left = mScrollX + (mPaddingLeft & inside);
15399        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
15400        bounds.bottom = bounds.top + size;
15401    }
15402
15403    private void getVerticalScrollBarBounds(Rect bounds) {
15404        if (mRoundScrollbarRenderer == null) {
15405            getStraightVerticalScrollBarBounds(bounds);
15406        } else {
15407            getRoundVerticalScrollBarBounds(bounds);
15408        }
15409    }
15410
15411    private void getRoundVerticalScrollBarBounds(Rect bounds) {
15412        final int width = mRight - mLeft;
15413        final int height = mBottom - mTop;
15414        // Do not take padding into account as we always want the scrollbars
15415        // to hug the screen for round wearable devices.
15416        bounds.left = mScrollX;
15417        bounds.top = mScrollY;
15418        bounds.right = bounds.left + width;
15419        bounds.bottom = mScrollY + height;
15420    }
15421
15422    private void getStraightVerticalScrollBarBounds(Rect bounds) {
15423        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
15424        final int size = getVerticalScrollbarWidth();
15425        int verticalScrollbarPosition = mVerticalScrollbarPosition;
15426        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
15427            verticalScrollbarPosition = isLayoutRtl() ?
15428                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
15429        }
15430        final int width = mRight - mLeft;
15431        final int height = mBottom - mTop;
15432        switch (verticalScrollbarPosition) {
15433            default:
15434            case SCROLLBAR_POSITION_RIGHT:
15435                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
15436                break;
15437            case SCROLLBAR_POSITION_LEFT:
15438                bounds.left = mScrollX + (mUserPaddingLeft & inside);
15439                break;
15440        }
15441        bounds.top = mScrollY + (mPaddingTop & inside);
15442        bounds.right = bounds.left + size;
15443        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
15444    }
15445
15446    /**
15447     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
15448     * scrollbars are painted only if they have been awakened first.</p>
15449     *
15450     * @param canvas the canvas on which to draw the scrollbars
15451     *
15452     * @see #awakenScrollBars(int)
15453     */
15454    protected final void onDrawScrollBars(Canvas canvas) {
15455        // scrollbars are drawn only when the animation is running
15456        final ScrollabilityCache cache = mScrollCache;
15457
15458        if (cache != null) {
15459
15460            int state = cache.state;
15461
15462            if (state == ScrollabilityCache.OFF) {
15463                return;
15464            }
15465
15466            boolean invalidate = false;
15467
15468            if (state == ScrollabilityCache.FADING) {
15469                // We're fading -- get our fade interpolation
15470                if (cache.interpolatorValues == null) {
15471                    cache.interpolatorValues = new float[1];
15472                }
15473
15474                float[] values = cache.interpolatorValues;
15475
15476                // Stops the animation if we're done
15477                if (cache.scrollBarInterpolator.timeToValues(values) ==
15478                        Interpolator.Result.FREEZE_END) {
15479                    cache.state = ScrollabilityCache.OFF;
15480                } else {
15481                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
15482                }
15483
15484                // This will make the scroll bars inval themselves after
15485                // drawing. We only want this when we're fading so that
15486                // we prevent excessive redraws
15487                invalidate = true;
15488            } else {
15489                // We're just on -- but we may have been fading before so
15490                // reset alpha
15491                cache.scrollBar.mutate().setAlpha(255);
15492            }
15493
15494            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
15495            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
15496                    && !isVerticalScrollBarHidden();
15497
15498            // Fork out the scroll bar drawing for round wearable devices.
15499            if (mRoundScrollbarRenderer != null) {
15500                if (drawVerticalScrollBar) {
15501                    final Rect bounds = cache.mScrollBarBounds;
15502                    getVerticalScrollBarBounds(bounds);
15503                    mRoundScrollbarRenderer.drawRoundScrollbars(
15504                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
15505                    if (invalidate) {
15506                        invalidate();
15507                    }
15508                }
15509                // Do not draw horizontal scroll bars for round wearable devices.
15510            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
15511                final ScrollBarDrawable scrollBar = cache.scrollBar;
15512
15513                if (drawHorizontalScrollBar) {
15514                    scrollBar.setParameters(computeHorizontalScrollRange(),
15515                            computeHorizontalScrollOffset(),
15516                            computeHorizontalScrollExtent(), false);
15517                    final Rect bounds = cache.mScrollBarBounds;
15518                    getHorizontalScrollBarBounds(bounds);
15519                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
15520                            bounds.right, bounds.bottom);
15521                    if (invalidate) {
15522                        invalidate(bounds);
15523                    }
15524                }
15525
15526                if (drawVerticalScrollBar) {
15527                    scrollBar.setParameters(computeVerticalScrollRange(),
15528                            computeVerticalScrollOffset(),
15529                            computeVerticalScrollExtent(), true);
15530                    final Rect bounds = cache.mScrollBarBounds;
15531                    getVerticalScrollBarBounds(bounds);
15532                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
15533                            bounds.right, bounds.bottom);
15534                    if (invalidate) {
15535                        invalidate(bounds);
15536                    }
15537                }
15538            }
15539        }
15540    }
15541
15542    /**
15543     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
15544     * FastScroller is visible.
15545     * @return whether to temporarily hide the vertical scrollbar
15546     * @hide
15547     */
15548    protected boolean isVerticalScrollBarHidden() {
15549        return false;
15550    }
15551
15552    /**
15553     * <p>Draw the horizontal scrollbar if
15554     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
15555     *
15556     * @param canvas the canvas on which to draw the scrollbar
15557     * @param scrollBar the scrollbar's drawable
15558     *
15559     * @see #isHorizontalScrollBarEnabled()
15560     * @see #computeHorizontalScrollRange()
15561     * @see #computeHorizontalScrollExtent()
15562     * @see #computeHorizontalScrollOffset()
15563     * @see android.widget.ScrollBarDrawable
15564     * @hide
15565     */
15566    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
15567            int l, int t, int r, int b) {
15568        scrollBar.setBounds(l, t, r, b);
15569        scrollBar.draw(canvas);
15570    }
15571
15572    /**
15573     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
15574     * returns true.</p>
15575     *
15576     * @param canvas the canvas on which to draw the scrollbar
15577     * @param scrollBar the scrollbar's drawable
15578     *
15579     * @see #isVerticalScrollBarEnabled()
15580     * @see #computeVerticalScrollRange()
15581     * @see #computeVerticalScrollExtent()
15582     * @see #computeVerticalScrollOffset()
15583     * @see android.widget.ScrollBarDrawable
15584     * @hide
15585     */
15586    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
15587            int l, int t, int r, int b) {
15588        scrollBar.setBounds(l, t, r, b);
15589        scrollBar.draw(canvas);
15590    }
15591
15592    /**
15593     * Implement this to do your drawing.
15594     *
15595     * @param canvas the canvas on which the background will be drawn
15596     */
15597    protected void onDraw(Canvas canvas) {
15598    }
15599
15600    /*
15601     * Caller is responsible for calling requestLayout if necessary.
15602     * (This allows addViewInLayout to not request a new layout.)
15603     */
15604    void assignParent(ViewParent parent) {
15605        if (mParent == null) {
15606            mParent = parent;
15607        } else if (parent == null) {
15608            mParent = null;
15609        } else {
15610            throw new RuntimeException("view " + this + " being added, but"
15611                    + " it already has a parent");
15612        }
15613    }
15614
15615    /**
15616     * This is called when the view is attached to a window.  At this point it
15617     * has a Surface and will start drawing.  Note that this function is
15618     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
15619     * however it may be called any time before the first onDraw -- including
15620     * before or after {@link #onMeasure(int, int)}.
15621     *
15622     * @see #onDetachedFromWindow()
15623     */
15624    @CallSuper
15625    protected void onAttachedToWindow() {
15626        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
15627            mParent.requestTransparentRegion(this);
15628        }
15629
15630        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15631
15632        jumpDrawablesToCurrentState();
15633
15634        resetSubtreeAccessibilityStateChanged();
15635
15636        // rebuild, since Outline not maintained while View is detached
15637        rebuildOutline();
15638
15639        if (isFocused()) {
15640            InputMethodManager imm = InputMethodManager.peekInstance();
15641            if (imm != null) {
15642                imm.focusIn(this);
15643            }
15644        }
15645    }
15646
15647    /**
15648     * Resolve all RTL related properties.
15649     *
15650     * @return true if resolution of RTL properties has been done
15651     *
15652     * @hide
15653     */
15654    public boolean resolveRtlPropertiesIfNeeded() {
15655        if (!needRtlPropertiesResolution()) return false;
15656
15657        // Order is important here: LayoutDirection MUST be resolved first
15658        if (!isLayoutDirectionResolved()) {
15659            resolveLayoutDirection();
15660            resolveLayoutParams();
15661        }
15662        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
15663        if (!isTextDirectionResolved()) {
15664            resolveTextDirection();
15665        }
15666        if (!isTextAlignmentResolved()) {
15667            resolveTextAlignment();
15668        }
15669        // Should resolve Drawables before Padding because we need the layout direction of the
15670        // Drawable to correctly resolve Padding.
15671        if (!areDrawablesResolved()) {
15672            resolveDrawables();
15673        }
15674        if (!isPaddingResolved()) {
15675            resolvePadding();
15676        }
15677        onRtlPropertiesChanged(getLayoutDirection());
15678        return true;
15679    }
15680
15681    /**
15682     * Reset resolution of all RTL related properties.
15683     *
15684     * @hide
15685     */
15686    public void resetRtlProperties() {
15687        resetResolvedLayoutDirection();
15688        resetResolvedTextDirection();
15689        resetResolvedTextAlignment();
15690        resetResolvedPadding();
15691        resetResolvedDrawables();
15692    }
15693
15694    /**
15695     * @see #onScreenStateChanged(int)
15696     */
15697    void dispatchScreenStateChanged(int screenState) {
15698        onScreenStateChanged(screenState);
15699    }
15700
15701    /**
15702     * This method is called whenever the state of the screen this view is
15703     * attached to changes. A state change will usually occurs when the screen
15704     * turns on or off (whether it happens automatically or the user does it
15705     * manually.)
15706     *
15707     * @param screenState The new state of the screen. Can be either
15708     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
15709     */
15710    public void onScreenStateChanged(int screenState) {
15711    }
15712
15713    /**
15714     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
15715     */
15716    private boolean hasRtlSupport() {
15717        return mContext.getApplicationInfo().hasRtlSupport();
15718    }
15719
15720    /**
15721     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
15722     * RTL not supported)
15723     */
15724    private boolean isRtlCompatibilityMode() {
15725        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
15726        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
15727    }
15728
15729    /**
15730     * @return true if RTL properties need resolution.
15731     *
15732     */
15733    private boolean needRtlPropertiesResolution() {
15734        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
15735    }
15736
15737    /**
15738     * Called when any RTL property (layout direction or text direction or text alignment) has
15739     * been changed.
15740     *
15741     * Subclasses need to override this method to take care of cached information that depends on the
15742     * resolved layout direction, or to inform child views that inherit their layout direction.
15743     *
15744     * The default implementation does nothing.
15745     *
15746     * @param layoutDirection the direction of the layout
15747     *
15748     * @see #LAYOUT_DIRECTION_LTR
15749     * @see #LAYOUT_DIRECTION_RTL
15750     */
15751    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
15752    }
15753
15754    /**
15755     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
15756     * that the parent directionality can and will be resolved before its children.
15757     *
15758     * @return true if resolution has been done, false otherwise.
15759     *
15760     * @hide
15761     */
15762    public boolean resolveLayoutDirection() {
15763        // Clear any previous layout direction resolution
15764        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15765
15766        if (hasRtlSupport()) {
15767            // Set resolved depending on layout direction
15768            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
15769                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
15770                case LAYOUT_DIRECTION_INHERIT:
15771                    // We cannot resolve yet. LTR is by default and let the resolution happen again
15772                    // later to get the correct resolved value
15773                    if (!canResolveLayoutDirection()) return false;
15774
15775                    // Parent has not yet resolved, LTR is still the default
15776                    try {
15777                        if (!mParent.isLayoutDirectionResolved()) return false;
15778
15779                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15780                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15781                        }
15782                    } catch (AbstractMethodError e) {
15783                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15784                                " does not fully implement ViewParent", e);
15785                    }
15786                    break;
15787                case LAYOUT_DIRECTION_RTL:
15788                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15789                    break;
15790                case LAYOUT_DIRECTION_LOCALE:
15791                    if((LAYOUT_DIRECTION_RTL ==
15792                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
15793                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15794                    }
15795                    break;
15796                default:
15797                    // Nothing to do, LTR by default
15798            }
15799        }
15800
15801        // Set to resolved
15802        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15803        return true;
15804    }
15805
15806    /**
15807     * Check if layout direction resolution can be done.
15808     *
15809     * @return true if layout direction resolution can be done otherwise return false.
15810     */
15811    public boolean canResolveLayoutDirection() {
15812        switch (getRawLayoutDirection()) {
15813            case LAYOUT_DIRECTION_INHERIT:
15814                if (mParent != null) {
15815                    try {
15816                        return mParent.canResolveLayoutDirection();
15817                    } catch (AbstractMethodError e) {
15818                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15819                                " does not fully implement ViewParent", e);
15820                    }
15821                }
15822                return false;
15823
15824            default:
15825                return true;
15826        }
15827    }
15828
15829    /**
15830     * Reset the resolved layout direction. Layout direction will be resolved during a call to
15831     * {@link #onMeasure(int, int)}.
15832     *
15833     * @hide
15834     */
15835    public void resetResolvedLayoutDirection() {
15836        // Reset the current resolved bits
15837        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15838    }
15839
15840    /**
15841     * @return true if the layout direction is inherited.
15842     *
15843     * @hide
15844     */
15845    public boolean isLayoutDirectionInherited() {
15846        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
15847    }
15848
15849    /**
15850     * @return true if layout direction has been resolved.
15851     */
15852    public boolean isLayoutDirectionResolved() {
15853        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
15854    }
15855
15856    /**
15857     * Return if padding has been resolved
15858     *
15859     * @hide
15860     */
15861    boolean isPaddingResolved() {
15862        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
15863    }
15864
15865    /**
15866     * Resolves padding depending on layout direction, if applicable, and
15867     * recomputes internal padding values to adjust for scroll bars.
15868     *
15869     * @hide
15870     */
15871    public void resolvePadding() {
15872        final int resolvedLayoutDirection = getLayoutDirection();
15873
15874        if (!isRtlCompatibilityMode()) {
15875            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
15876            // If start / end padding are defined, they will be resolved (hence overriding) to
15877            // left / right or right / left depending on the resolved layout direction.
15878            // If start / end padding are not defined, use the left / right ones.
15879            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
15880                Rect padding = sThreadLocal.get();
15881                if (padding == null) {
15882                    padding = new Rect();
15883                    sThreadLocal.set(padding);
15884                }
15885                mBackground.getPadding(padding);
15886                if (!mLeftPaddingDefined) {
15887                    mUserPaddingLeftInitial = padding.left;
15888                }
15889                if (!mRightPaddingDefined) {
15890                    mUserPaddingRightInitial = padding.right;
15891                }
15892            }
15893            switch (resolvedLayoutDirection) {
15894                case LAYOUT_DIRECTION_RTL:
15895                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15896                        mUserPaddingRight = mUserPaddingStart;
15897                    } else {
15898                        mUserPaddingRight = mUserPaddingRightInitial;
15899                    }
15900                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15901                        mUserPaddingLeft = mUserPaddingEnd;
15902                    } else {
15903                        mUserPaddingLeft = mUserPaddingLeftInitial;
15904                    }
15905                    break;
15906                case LAYOUT_DIRECTION_LTR:
15907                default:
15908                    if (mUserPaddingStart != UNDEFINED_PADDING) {
15909                        mUserPaddingLeft = mUserPaddingStart;
15910                    } else {
15911                        mUserPaddingLeft = mUserPaddingLeftInitial;
15912                    }
15913                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
15914                        mUserPaddingRight = mUserPaddingEnd;
15915                    } else {
15916                        mUserPaddingRight = mUserPaddingRightInitial;
15917                    }
15918            }
15919
15920            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
15921        }
15922
15923        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15924        onRtlPropertiesChanged(resolvedLayoutDirection);
15925
15926        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
15927    }
15928
15929    /**
15930     * Reset the resolved layout direction.
15931     *
15932     * @hide
15933     */
15934    public void resetResolvedPadding() {
15935        resetResolvedPaddingInternal();
15936    }
15937
15938    /**
15939     * Used when we only want to reset *this* view's padding and not trigger overrides
15940     * in ViewGroup that reset children too.
15941     */
15942    void resetResolvedPaddingInternal() {
15943        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
15944    }
15945
15946    /**
15947     * This is called when the view is detached from a window.  At this point it
15948     * no longer has a surface for drawing.
15949     *
15950     * @see #onAttachedToWindow()
15951     */
15952    @CallSuper
15953    protected void onDetachedFromWindow() {
15954    }
15955
15956    /**
15957     * This is a framework-internal mirror of onDetachedFromWindow() that's called
15958     * after onDetachedFromWindow().
15959     *
15960     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
15961     * The super method should be called at the end of the overridden method to ensure
15962     * subclasses are destroyed first
15963     *
15964     * @hide
15965     */
15966    @CallSuper
15967    protected void onDetachedFromWindowInternal() {
15968        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
15969        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15970        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
15971
15972        removeUnsetPressCallback();
15973        removeLongPressCallback();
15974        removePerformClickCallback();
15975        removeSendViewScrolledAccessibilityEventCallback();
15976        stopNestedScroll();
15977
15978        // Anything that started animating right before detach should already
15979        // be in its final state when re-attached.
15980        jumpDrawablesToCurrentState();
15981
15982        destroyDrawingCache();
15983
15984        cleanupDraw();
15985        mCurrentAnimation = null;
15986
15987        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
15988            hideTooltip();
15989        }
15990    }
15991
15992    private void cleanupDraw() {
15993        resetDisplayList();
15994        if (mAttachInfo != null) {
15995            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
15996        }
15997    }
15998
15999    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
16000    }
16001
16002    /**
16003     * @return The number of times this view has been attached to a window
16004     */
16005    protected int getWindowAttachCount() {
16006        return mWindowAttachCount;
16007    }
16008
16009    /**
16010     * Retrieve a unique token identifying the window this view is attached to.
16011     * @return Return the window's token for use in
16012     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
16013     */
16014    public IBinder getWindowToken() {
16015        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
16016    }
16017
16018    /**
16019     * Retrieve the {@link WindowId} for the window this view is
16020     * currently attached to.
16021     */
16022    public WindowId getWindowId() {
16023        if (mAttachInfo == null) {
16024            return null;
16025        }
16026        if (mAttachInfo.mWindowId == null) {
16027            try {
16028                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
16029                        mAttachInfo.mWindowToken);
16030                mAttachInfo.mWindowId = new WindowId(
16031                        mAttachInfo.mIWindowId);
16032            } catch (RemoteException e) {
16033            }
16034        }
16035        return mAttachInfo.mWindowId;
16036    }
16037
16038    /**
16039     * Retrieve a unique token identifying the top-level "real" window of
16040     * the window that this view is attached to.  That is, this is like
16041     * {@link #getWindowToken}, except if the window this view in is a panel
16042     * window (attached to another containing window), then the token of
16043     * the containing window is returned instead.
16044     *
16045     * @return Returns the associated window token, either
16046     * {@link #getWindowToken()} or the containing window's token.
16047     */
16048    public IBinder getApplicationWindowToken() {
16049        AttachInfo ai = mAttachInfo;
16050        if (ai != null) {
16051            IBinder appWindowToken = ai.mPanelParentWindowToken;
16052            if (appWindowToken == null) {
16053                appWindowToken = ai.mWindowToken;
16054            }
16055            return appWindowToken;
16056        }
16057        return null;
16058    }
16059
16060    /**
16061     * Gets the logical display to which the view's window has been attached.
16062     *
16063     * @return The logical display, or null if the view is not currently attached to a window.
16064     */
16065    public Display getDisplay() {
16066        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
16067    }
16068
16069    /**
16070     * Retrieve private session object this view hierarchy is using to
16071     * communicate with the window manager.
16072     * @return the session object to communicate with the window manager
16073     */
16074    /*package*/ IWindowSession getWindowSession() {
16075        return mAttachInfo != null ? mAttachInfo.mSession : null;
16076    }
16077
16078    /**
16079     * Return the visibility value of the least visible component passed.
16080     */
16081    int combineVisibility(int vis1, int vis2) {
16082        // This works because VISIBLE < INVISIBLE < GONE.
16083        return Math.max(vis1, vis2);
16084    }
16085
16086    /**
16087     * @param info the {@link android.view.View.AttachInfo} to associated with
16088     *        this view
16089     */
16090    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
16091        mAttachInfo = info;
16092        if (mOverlay != null) {
16093            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
16094        }
16095        mWindowAttachCount++;
16096        // We will need to evaluate the drawable state at least once.
16097        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16098        if (mFloatingTreeObserver != null) {
16099            info.mTreeObserver.merge(mFloatingTreeObserver);
16100            mFloatingTreeObserver = null;
16101        }
16102
16103        registerPendingFrameMetricsObservers();
16104
16105        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
16106            mAttachInfo.mScrollContainers.add(this);
16107            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
16108        }
16109        // Transfer all pending runnables.
16110        if (mRunQueue != null) {
16111            mRunQueue.executeActions(info.mHandler);
16112            mRunQueue = null;
16113        }
16114        performCollectViewAttributes(mAttachInfo, visibility);
16115        onAttachedToWindow();
16116
16117        ListenerInfo li = mListenerInfo;
16118        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
16119                li != null ? li.mOnAttachStateChangeListeners : null;
16120        if (listeners != null && listeners.size() > 0) {
16121            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
16122            // perform the dispatching. The iterator is a safe guard against listeners that
16123            // could mutate the list by calling the various add/remove methods. This prevents
16124            // the array from being modified while we iterate it.
16125            for (OnAttachStateChangeListener listener : listeners) {
16126                listener.onViewAttachedToWindow(this);
16127            }
16128        }
16129
16130        int vis = info.mWindowVisibility;
16131        if (vis != GONE) {
16132            onWindowVisibilityChanged(vis);
16133            if (isShown()) {
16134                // Calling onVisibilityAggregated directly here since the subtree will also
16135                // receive dispatchAttachedToWindow and this same call
16136                onVisibilityAggregated(vis == VISIBLE);
16137            }
16138        }
16139
16140        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
16141        // As all views in the subtree will already receive dispatchAttachedToWindow
16142        // traversing the subtree again here is not desired.
16143        onVisibilityChanged(this, visibility);
16144
16145        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
16146            // If nobody has evaluated the drawable state yet, then do it now.
16147            refreshDrawableState();
16148        }
16149        needGlobalAttributesUpdate(false);
16150    }
16151
16152    void dispatchDetachedFromWindow() {
16153        AttachInfo info = mAttachInfo;
16154        if (info != null) {
16155            int vis = info.mWindowVisibility;
16156            if (vis != GONE) {
16157                onWindowVisibilityChanged(GONE);
16158                if (isShown()) {
16159                    // Invoking onVisibilityAggregated directly here since the subtree
16160                    // will also receive detached from window
16161                    onVisibilityAggregated(false);
16162                }
16163            }
16164        }
16165
16166        onDetachedFromWindow();
16167        onDetachedFromWindowInternal();
16168
16169        InputMethodManager imm = InputMethodManager.peekInstance();
16170        if (imm != null) {
16171            imm.onViewDetachedFromWindow(this);
16172        }
16173
16174        ListenerInfo li = mListenerInfo;
16175        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
16176                li != null ? li.mOnAttachStateChangeListeners : null;
16177        if (listeners != null && listeners.size() > 0) {
16178            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
16179            // perform the dispatching. The iterator is a safe guard against listeners that
16180            // could mutate the list by calling the various add/remove methods. This prevents
16181            // the array from being modified while we iterate it.
16182            for (OnAttachStateChangeListener listener : listeners) {
16183                listener.onViewDetachedFromWindow(this);
16184            }
16185        }
16186
16187        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
16188            mAttachInfo.mScrollContainers.remove(this);
16189            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
16190        }
16191
16192        mAttachInfo = null;
16193        if (mOverlay != null) {
16194            mOverlay.getOverlayView().dispatchDetachedFromWindow();
16195        }
16196    }
16197
16198    /**
16199     * Cancel any deferred high-level input events that were previously posted to the event queue.
16200     *
16201     * <p>Many views post high-level events such as click handlers to the event queue
16202     * to run deferred in order to preserve a desired user experience - clearing visible
16203     * pressed states before executing, etc. This method will abort any events of this nature
16204     * that are currently in flight.</p>
16205     *
16206     * <p>Custom views that generate their own high-level deferred input events should override
16207     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
16208     *
16209     * <p>This will also cancel pending input events for any child views.</p>
16210     *
16211     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
16212     * This will not impact newer events posted after this call that may occur as a result of
16213     * lower-level input events still waiting in the queue. If you are trying to prevent
16214     * double-submitted  events for the duration of some sort of asynchronous transaction
16215     * you should also take other steps to protect against unexpected double inputs e.g. calling
16216     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
16217     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
16218     */
16219    public final void cancelPendingInputEvents() {
16220        dispatchCancelPendingInputEvents();
16221    }
16222
16223    /**
16224     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
16225     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
16226     */
16227    void dispatchCancelPendingInputEvents() {
16228        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
16229        onCancelPendingInputEvents();
16230        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
16231            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
16232                    " did not call through to super.onCancelPendingInputEvents()");
16233        }
16234    }
16235
16236    /**
16237     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
16238     * a parent view.
16239     *
16240     * <p>This method is responsible for removing any pending high-level input events that were
16241     * posted to the event queue to run later. Custom view classes that post their own deferred
16242     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
16243     * {@link android.os.Handler} should override this method, call
16244     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
16245     * </p>
16246     */
16247    public void onCancelPendingInputEvents() {
16248        removePerformClickCallback();
16249        cancelLongPress();
16250        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
16251    }
16252
16253    /**
16254     * Store this view hierarchy's frozen state into the given container.
16255     *
16256     * @param container The SparseArray in which to save the view's state.
16257     *
16258     * @see #restoreHierarchyState(android.util.SparseArray)
16259     * @see #dispatchSaveInstanceState(android.util.SparseArray)
16260     * @see #onSaveInstanceState()
16261     */
16262    public void saveHierarchyState(SparseArray<Parcelable> container) {
16263        dispatchSaveInstanceState(container);
16264    }
16265
16266    /**
16267     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
16268     * this view and its children. May be overridden to modify how freezing happens to a
16269     * view's children; for example, some views may want to not store state for their children.
16270     *
16271     * @param container The SparseArray in which to save the view's state.
16272     *
16273     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
16274     * @see #saveHierarchyState(android.util.SparseArray)
16275     * @see #onSaveInstanceState()
16276     */
16277    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
16278        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
16279            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
16280            Parcelable state = onSaveInstanceState();
16281            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
16282                throw new IllegalStateException(
16283                        "Derived class did not call super.onSaveInstanceState()");
16284            }
16285            if (state != null) {
16286                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
16287                // + ": " + state);
16288                container.put(mID, state);
16289            }
16290        }
16291    }
16292
16293    /**
16294     * Hook allowing a view to generate a representation of its internal state
16295     * that can later be used to create a new instance with that same state.
16296     * This state should only contain information that is not persistent or can
16297     * not be reconstructed later. For example, you will never store your
16298     * current position on screen because that will be computed again when a
16299     * new instance of the view is placed in its view hierarchy.
16300     * <p>
16301     * Some examples of things you may store here: the current cursor position
16302     * in a text view (but usually not the text itself since that is stored in a
16303     * content provider or other persistent storage), the currently selected
16304     * item in a list view.
16305     *
16306     * @return Returns a Parcelable object containing the view's current dynamic
16307     *         state, or null if there is nothing interesting to save. The
16308     *         default implementation returns null.
16309     * @see #onRestoreInstanceState(android.os.Parcelable)
16310     * @see #saveHierarchyState(android.util.SparseArray)
16311     * @see #dispatchSaveInstanceState(android.util.SparseArray)
16312     * @see #setSaveEnabled(boolean)
16313     */
16314    @CallSuper
16315    protected Parcelable onSaveInstanceState() {
16316        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
16317        if (mStartActivityRequestWho != null) {
16318            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
16319            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
16320            return state;
16321        }
16322        return BaseSavedState.EMPTY_STATE;
16323    }
16324
16325    /**
16326     * Restore this view hierarchy's frozen state from the given container.
16327     *
16328     * @param container The SparseArray which holds previously frozen states.
16329     *
16330     * @see #saveHierarchyState(android.util.SparseArray)
16331     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
16332     * @see #onRestoreInstanceState(android.os.Parcelable)
16333     */
16334    public void restoreHierarchyState(SparseArray<Parcelable> container) {
16335        dispatchRestoreInstanceState(container);
16336    }
16337
16338    /**
16339     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
16340     * state for this view and its children. May be overridden to modify how restoring
16341     * happens to a view's children; for example, some views may want to not store state
16342     * for their children.
16343     *
16344     * @param container The SparseArray which holds previously saved state.
16345     *
16346     * @see #dispatchSaveInstanceState(android.util.SparseArray)
16347     * @see #restoreHierarchyState(android.util.SparseArray)
16348     * @see #onRestoreInstanceState(android.os.Parcelable)
16349     */
16350    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
16351        if (mID != NO_ID) {
16352            Parcelable state = container.get(mID);
16353            if (state != null) {
16354                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
16355                // + ": " + state);
16356                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
16357                onRestoreInstanceState(state);
16358                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
16359                    throw new IllegalStateException(
16360                            "Derived class did not call super.onRestoreInstanceState()");
16361                }
16362            }
16363        }
16364    }
16365
16366    /**
16367     * Hook allowing a view to re-apply a representation of its internal state that had previously
16368     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
16369     * null state.
16370     *
16371     * @param state The frozen state that had previously been returned by
16372     *        {@link #onSaveInstanceState}.
16373     *
16374     * @see #onSaveInstanceState()
16375     * @see #restoreHierarchyState(android.util.SparseArray)
16376     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
16377     */
16378    @CallSuper
16379    protected void onRestoreInstanceState(Parcelable state) {
16380        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
16381        if (state != null && !(state instanceof AbsSavedState)) {
16382            throw new IllegalArgumentException("Wrong state class, expecting View State but "
16383                    + "received " + state.getClass().toString() + " instead. This usually happens "
16384                    + "when two views of different type have the same id in the same hierarchy. "
16385                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
16386                    + "other views do not use the same id.");
16387        }
16388        if (state != null && state instanceof BaseSavedState) {
16389            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
16390        }
16391    }
16392
16393    /**
16394     * <p>Return the time at which the drawing of the view hierarchy started.</p>
16395     *
16396     * @return the drawing start time in milliseconds
16397     */
16398    public long getDrawingTime() {
16399        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
16400    }
16401
16402    /**
16403     * <p>Enables or disables the duplication of the parent's state into this view. When
16404     * duplication is enabled, this view gets its drawable state from its parent rather
16405     * than from its own internal properties.</p>
16406     *
16407     * <p>Note: in the current implementation, setting this property to true after the
16408     * view was added to a ViewGroup might have no effect at all. This property should
16409     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
16410     *
16411     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
16412     * property is enabled, an exception will be thrown.</p>
16413     *
16414     * <p>Note: if the child view uses and updates additional states which are unknown to the
16415     * parent, these states should not be affected by this method.</p>
16416     *
16417     * @param enabled True to enable duplication of the parent's drawable state, false
16418     *                to disable it.
16419     *
16420     * @see #getDrawableState()
16421     * @see #isDuplicateParentStateEnabled()
16422     */
16423    public void setDuplicateParentStateEnabled(boolean enabled) {
16424        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
16425    }
16426
16427    /**
16428     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
16429     *
16430     * @return True if this view's drawable state is duplicated from the parent,
16431     *         false otherwise
16432     *
16433     * @see #getDrawableState()
16434     * @see #setDuplicateParentStateEnabled(boolean)
16435     */
16436    public boolean isDuplicateParentStateEnabled() {
16437        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
16438    }
16439
16440    /**
16441     * <p>Specifies the type of layer backing this view. The layer can be
16442     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
16443     * {@link #LAYER_TYPE_HARDWARE}.</p>
16444     *
16445     * <p>A layer is associated with an optional {@link android.graphics.Paint}
16446     * instance that controls how the layer is composed on screen. The following
16447     * properties of the paint are taken into account when composing the layer:</p>
16448     * <ul>
16449     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
16450     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
16451     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
16452     * </ul>
16453     *
16454     * <p>If this view has an alpha value set to < 1.0 by calling
16455     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
16456     * by this view's alpha value.</p>
16457     *
16458     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
16459     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
16460     * for more information on when and how to use layers.</p>
16461     *
16462     * @param layerType The type of layer to use with this view, must be one of
16463     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
16464     *        {@link #LAYER_TYPE_HARDWARE}
16465     * @param paint The paint used to compose the layer. This argument is optional
16466     *        and can be null. It is ignored when the layer type is
16467     *        {@link #LAYER_TYPE_NONE}
16468     *
16469     * @see #getLayerType()
16470     * @see #LAYER_TYPE_NONE
16471     * @see #LAYER_TYPE_SOFTWARE
16472     * @see #LAYER_TYPE_HARDWARE
16473     * @see #setAlpha(float)
16474     *
16475     * @attr ref android.R.styleable#View_layerType
16476     */
16477    public void setLayerType(int layerType, @Nullable Paint paint) {
16478        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
16479            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
16480                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
16481        }
16482
16483        boolean typeChanged = mRenderNode.setLayerType(layerType);
16484
16485        if (!typeChanged) {
16486            setLayerPaint(paint);
16487            return;
16488        }
16489
16490        if (layerType != LAYER_TYPE_SOFTWARE) {
16491            // Destroy any previous software drawing cache if present
16492            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
16493            // drawing cache created in View#draw when drawing to a SW canvas.
16494            destroyDrawingCache();
16495        }
16496
16497        mLayerType = layerType;
16498        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
16499        mRenderNode.setLayerPaint(mLayerPaint);
16500
16501        // draw() behaves differently if we are on a layer, so we need to
16502        // invalidate() here
16503        invalidateParentCaches();
16504        invalidate(true);
16505    }
16506
16507    /**
16508     * Updates the {@link Paint} object used with the current layer (used only if the current
16509     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
16510     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
16511     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
16512     * ensure that the view gets redrawn immediately.
16513     *
16514     * <p>A layer is associated with an optional {@link android.graphics.Paint}
16515     * instance that controls how the layer is composed on screen. The following
16516     * properties of the paint are taken into account when composing the layer:</p>
16517     * <ul>
16518     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
16519     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
16520     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
16521     * </ul>
16522     *
16523     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
16524     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
16525     *
16526     * @param paint The paint used to compose the layer. This argument is optional
16527     *        and can be null. It is ignored when the layer type is
16528     *        {@link #LAYER_TYPE_NONE}
16529     *
16530     * @see #setLayerType(int, android.graphics.Paint)
16531     */
16532    public void setLayerPaint(@Nullable Paint paint) {
16533        int layerType = getLayerType();
16534        if (layerType != LAYER_TYPE_NONE) {
16535            mLayerPaint = paint;
16536            if (layerType == LAYER_TYPE_HARDWARE) {
16537                if (mRenderNode.setLayerPaint(paint)) {
16538                    invalidateViewProperty(false, false);
16539                }
16540            } else {
16541                invalidate();
16542            }
16543        }
16544    }
16545
16546    /**
16547     * Indicates what type of layer is currently associated with this view. By default
16548     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
16549     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
16550     * for more information on the different types of layers.
16551     *
16552     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
16553     *         {@link #LAYER_TYPE_HARDWARE}
16554     *
16555     * @see #setLayerType(int, android.graphics.Paint)
16556     * @see #buildLayer()
16557     * @see #LAYER_TYPE_NONE
16558     * @see #LAYER_TYPE_SOFTWARE
16559     * @see #LAYER_TYPE_HARDWARE
16560     */
16561    public int getLayerType() {
16562        return mLayerType;
16563    }
16564
16565    /**
16566     * Forces this view's layer to be created and this view to be rendered
16567     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
16568     * invoking this method will have no effect.
16569     *
16570     * This method can for instance be used to render a view into its layer before
16571     * starting an animation. If this view is complex, rendering into the layer
16572     * before starting the animation will avoid skipping frames.
16573     *
16574     * @throws IllegalStateException If this view is not attached to a window
16575     *
16576     * @see #setLayerType(int, android.graphics.Paint)
16577     */
16578    public void buildLayer() {
16579        if (mLayerType == LAYER_TYPE_NONE) return;
16580
16581        final AttachInfo attachInfo = mAttachInfo;
16582        if (attachInfo == null) {
16583            throw new IllegalStateException("This view must be attached to a window first");
16584        }
16585
16586        if (getWidth() == 0 || getHeight() == 0) {
16587            return;
16588        }
16589
16590        switch (mLayerType) {
16591            case LAYER_TYPE_HARDWARE:
16592                updateDisplayListIfDirty();
16593                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
16594                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
16595                }
16596                break;
16597            case LAYER_TYPE_SOFTWARE:
16598                buildDrawingCache(true);
16599                break;
16600        }
16601    }
16602
16603    /**
16604     * Destroys all hardware rendering resources. This method is invoked
16605     * when the system needs to reclaim resources. Upon execution of this
16606     * method, you should free any OpenGL resources created by the view.
16607     *
16608     * Note: you <strong>must</strong> call
16609     * <code>super.destroyHardwareResources()</code> when overriding
16610     * this method.
16611     *
16612     * @hide
16613     */
16614    @CallSuper
16615    protected void destroyHardwareResources() {
16616        if (mOverlay != null) {
16617            mOverlay.getOverlayView().destroyHardwareResources();
16618        }
16619        if (mGhostView != null) {
16620            mGhostView.destroyHardwareResources();
16621        }
16622    }
16623
16624    /**
16625     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
16626     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
16627     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
16628     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
16629     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
16630     * null.</p>
16631     *
16632     * <p>Enabling the drawing cache is similar to
16633     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
16634     * acceleration is turned off. When hardware acceleration is turned on, enabling the
16635     * drawing cache has no effect on rendering because the system uses a different mechanism
16636     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
16637     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
16638     * for information on how to enable software and hardware layers.</p>
16639     *
16640     * <p>This API can be used to manually generate
16641     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
16642     * {@link #getDrawingCache()}.</p>
16643     *
16644     * @param enabled true to enable the drawing cache, false otherwise
16645     *
16646     * @see #isDrawingCacheEnabled()
16647     * @see #getDrawingCache()
16648     * @see #buildDrawingCache()
16649     * @see #setLayerType(int, android.graphics.Paint)
16650     */
16651    public void setDrawingCacheEnabled(boolean enabled) {
16652        mCachingFailed = false;
16653        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
16654    }
16655
16656    /**
16657     * <p>Indicates whether the drawing cache is enabled for this view.</p>
16658     *
16659     * @return true if the drawing cache is enabled
16660     *
16661     * @see #setDrawingCacheEnabled(boolean)
16662     * @see #getDrawingCache()
16663     */
16664    @ViewDebug.ExportedProperty(category = "drawing")
16665    public boolean isDrawingCacheEnabled() {
16666        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
16667    }
16668
16669    /**
16670     * Debugging utility which recursively outputs the dirty state of a view and its
16671     * descendants.
16672     *
16673     * @hide
16674     */
16675    @SuppressWarnings({"UnusedDeclaration"})
16676    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
16677        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
16678                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
16679                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
16680                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
16681        if (clear) {
16682            mPrivateFlags &= clearMask;
16683        }
16684        if (this instanceof ViewGroup) {
16685            ViewGroup parent = (ViewGroup) this;
16686            final int count = parent.getChildCount();
16687            for (int i = 0; i < count; i++) {
16688                final View child = parent.getChildAt(i);
16689                child.outputDirtyFlags(indent + "  ", clear, clearMask);
16690            }
16691        }
16692    }
16693
16694    /**
16695     * This method is used by ViewGroup to cause its children to restore or recreate their
16696     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
16697     * to recreate its own display list, which would happen if it went through the normal
16698     * draw/dispatchDraw mechanisms.
16699     *
16700     * @hide
16701     */
16702    protected void dispatchGetDisplayList() {}
16703
16704    /**
16705     * A view that is not attached or hardware accelerated cannot create a display list.
16706     * This method checks these conditions and returns the appropriate result.
16707     *
16708     * @return true if view has the ability to create a display list, false otherwise.
16709     *
16710     * @hide
16711     */
16712    public boolean canHaveDisplayList() {
16713        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
16714    }
16715
16716    /**
16717     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
16718     * @hide
16719     */
16720    @NonNull
16721    public RenderNode updateDisplayListIfDirty() {
16722        final RenderNode renderNode = mRenderNode;
16723        if (!canHaveDisplayList()) {
16724            // can't populate RenderNode, don't try
16725            return renderNode;
16726        }
16727
16728        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
16729                || !renderNode.isValid()
16730                || (mRecreateDisplayList)) {
16731            // Don't need to recreate the display list, just need to tell our
16732            // children to restore/recreate theirs
16733            if (renderNode.isValid()
16734                    && !mRecreateDisplayList) {
16735                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16736                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16737                dispatchGetDisplayList();
16738
16739                return renderNode; // no work needed
16740            }
16741
16742            // If we got here, we're recreating it. Mark it as such to ensure that
16743            // we copy in child display lists into ours in drawChild()
16744            mRecreateDisplayList = true;
16745
16746            int width = mRight - mLeft;
16747            int height = mBottom - mTop;
16748            int layerType = getLayerType();
16749
16750            final DisplayListCanvas canvas = renderNode.start(width, height);
16751            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
16752
16753            try {
16754                if (layerType == LAYER_TYPE_SOFTWARE) {
16755                    buildDrawingCache(true);
16756                    Bitmap cache = getDrawingCache(true);
16757                    if (cache != null) {
16758                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
16759                    }
16760                } else {
16761                    computeScroll();
16762
16763                    canvas.translate(-mScrollX, -mScrollY);
16764                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16765                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16766
16767                    // Fast path for layouts with no backgrounds
16768                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16769                        dispatchDraw(canvas);
16770                        if (mOverlay != null && !mOverlay.isEmpty()) {
16771                            mOverlay.getOverlayView().draw(canvas);
16772                        }
16773                        if (debugDraw()) {
16774                            debugDrawFocus(canvas);
16775                        }
16776                    } else {
16777                        draw(canvas);
16778                    }
16779                }
16780            } finally {
16781                renderNode.end(canvas);
16782                setDisplayListProperties(renderNode);
16783            }
16784        } else {
16785            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16786            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16787        }
16788        return renderNode;
16789    }
16790
16791    private void resetDisplayList() {
16792        mRenderNode.discardDisplayList();
16793        if (mBackgroundRenderNode != null) {
16794            mBackgroundRenderNode.discardDisplayList();
16795        }
16796    }
16797
16798    /**
16799     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
16800     *
16801     * @return A non-scaled bitmap representing this view or null if cache is disabled.
16802     *
16803     * @see #getDrawingCache(boolean)
16804     */
16805    public Bitmap getDrawingCache() {
16806        return getDrawingCache(false);
16807    }
16808
16809    /**
16810     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
16811     * is null when caching is disabled. If caching is enabled and the cache is not ready,
16812     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
16813     * draw from the cache when the cache is enabled. To benefit from the cache, you must
16814     * request the drawing cache by calling this method and draw it on screen if the
16815     * returned bitmap is not null.</p>
16816     *
16817     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16818     * this method will create a bitmap of the same size as this view. Because this bitmap
16819     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16820     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16821     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16822     * size than the view. This implies that your application must be able to handle this
16823     * size.</p>
16824     *
16825     * @param autoScale Indicates whether the generated bitmap should be scaled based on
16826     *        the current density of the screen when the application is in compatibility
16827     *        mode.
16828     *
16829     * @return A bitmap representing this view or null if cache is disabled.
16830     *
16831     * @see #setDrawingCacheEnabled(boolean)
16832     * @see #isDrawingCacheEnabled()
16833     * @see #buildDrawingCache(boolean)
16834     * @see #destroyDrawingCache()
16835     */
16836    public Bitmap getDrawingCache(boolean autoScale) {
16837        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
16838            return null;
16839        }
16840        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
16841            buildDrawingCache(autoScale);
16842        }
16843        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
16844    }
16845
16846    /**
16847     * <p>Frees the resources used by the drawing cache. If you call
16848     * {@link #buildDrawingCache()} manually without calling
16849     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16850     * should cleanup the cache with this method afterwards.</p>
16851     *
16852     * @see #setDrawingCacheEnabled(boolean)
16853     * @see #buildDrawingCache()
16854     * @see #getDrawingCache()
16855     */
16856    public void destroyDrawingCache() {
16857        if (mDrawingCache != null) {
16858            mDrawingCache.recycle();
16859            mDrawingCache = null;
16860        }
16861        if (mUnscaledDrawingCache != null) {
16862            mUnscaledDrawingCache.recycle();
16863            mUnscaledDrawingCache = null;
16864        }
16865    }
16866
16867    /**
16868     * Setting a solid background color for the drawing cache's bitmaps will improve
16869     * performance and memory usage. Note, though that this should only be used if this
16870     * view will always be drawn on top of a solid color.
16871     *
16872     * @param color The background color to use for the drawing cache's bitmap
16873     *
16874     * @see #setDrawingCacheEnabled(boolean)
16875     * @see #buildDrawingCache()
16876     * @see #getDrawingCache()
16877     */
16878    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
16879        if (color != mDrawingCacheBackgroundColor) {
16880            mDrawingCacheBackgroundColor = color;
16881            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
16882        }
16883    }
16884
16885    /**
16886     * @see #setDrawingCacheBackgroundColor(int)
16887     *
16888     * @return The background color to used for the drawing cache's bitmap
16889     */
16890    @ColorInt
16891    public int getDrawingCacheBackgroundColor() {
16892        return mDrawingCacheBackgroundColor;
16893    }
16894
16895    /**
16896     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
16897     *
16898     * @see #buildDrawingCache(boolean)
16899     */
16900    public void buildDrawingCache() {
16901        buildDrawingCache(false);
16902    }
16903
16904    /**
16905     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
16906     *
16907     * <p>If you call {@link #buildDrawingCache()} manually without calling
16908     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
16909     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
16910     *
16911     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
16912     * this method will create a bitmap of the same size as this view. Because this bitmap
16913     * will be drawn scaled by the parent ViewGroup, the result on screen might show
16914     * scaling artifacts. To avoid such artifacts, you should call this method by setting
16915     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
16916     * size than the view. This implies that your application must be able to handle this
16917     * size.</p>
16918     *
16919     * <p>You should avoid calling this method when hardware acceleration is enabled. If
16920     * you do not need the drawing cache bitmap, calling this method will increase memory
16921     * usage and cause the view to be rendered in software once, thus negatively impacting
16922     * performance.</p>
16923     *
16924     * @see #getDrawingCache()
16925     * @see #destroyDrawingCache()
16926     */
16927    public void buildDrawingCache(boolean autoScale) {
16928        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
16929                mDrawingCache == null : mUnscaledDrawingCache == null)) {
16930            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
16931                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
16932                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
16933            }
16934            try {
16935                buildDrawingCacheImpl(autoScale);
16936            } finally {
16937                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
16938            }
16939        }
16940    }
16941
16942    /**
16943     * private, internal implementation of buildDrawingCache, used to enable tracing
16944     */
16945    private void buildDrawingCacheImpl(boolean autoScale) {
16946        mCachingFailed = false;
16947
16948        int width = mRight - mLeft;
16949        int height = mBottom - mTop;
16950
16951        final AttachInfo attachInfo = mAttachInfo;
16952        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
16953
16954        if (autoScale && scalingRequired) {
16955            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
16956            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
16957        }
16958
16959        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
16960        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
16961        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
16962
16963        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
16964        final long drawingCacheSize =
16965                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
16966        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
16967            if (width > 0 && height > 0) {
16968                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
16969                        + " too large to fit into a software layer (or drawing cache), needs "
16970                        + projectedBitmapSize + " bytes, only "
16971                        + drawingCacheSize + " available");
16972            }
16973            destroyDrawingCache();
16974            mCachingFailed = true;
16975            return;
16976        }
16977
16978        boolean clear = true;
16979        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
16980
16981        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
16982            Bitmap.Config quality;
16983            if (!opaque) {
16984                // Never pick ARGB_4444 because it looks awful
16985                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
16986                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
16987                    case DRAWING_CACHE_QUALITY_AUTO:
16988                    case DRAWING_CACHE_QUALITY_LOW:
16989                    case DRAWING_CACHE_QUALITY_HIGH:
16990                    default:
16991                        quality = Bitmap.Config.ARGB_8888;
16992                        break;
16993                }
16994            } else {
16995                // Optimization for translucent windows
16996                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
16997                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
16998            }
16999
17000            // Try to cleanup memory
17001            if (bitmap != null) bitmap.recycle();
17002
17003            try {
17004                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17005                        width, height, quality);
17006                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
17007                if (autoScale) {
17008                    mDrawingCache = bitmap;
17009                } else {
17010                    mUnscaledDrawingCache = bitmap;
17011                }
17012                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
17013            } catch (OutOfMemoryError e) {
17014                // If there is not enough memory to create the bitmap cache, just
17015                // ignore the issue as bitmap caches are not required to draw the
17016                // view hierarchy
17017                if (autoScale) {
17018                    mDrawingCache = null;
17019                } else {
17020                    mUnscaledDrawingCache = null;
17021                }
17022                mCachingFailed = true;
17023                return;
17024            }
17025
17026            clear = drawingCacheBackgroundColor != 0;
17027        }
17028
17029        Canvas canvas;
17030        if (attachInfo != null) {
17031            canvas = attachInfo.mCanvas;
17032            if (canvas == null) {
17033                canvas = new Canvas();
17034            }
17035            canvas.setBitmap(bitmap);
17036            // Temporarily clobber the cached Canvas in case one of our children
17037            // is also using a drawing cache. Without this, the children would
17038            // steal the canvas by attaching their own bitmap to it and bad, bad
17039            // thing would happen (invisible views, corrupted drawings, etc.)
17040            attachInfo.mCanvas = null;
17041        } else {
17042            // This case should hopefully never or seldom happen
17043            canvas = new Canvas(bitmap);
17044        }
17045
17046        if (clear) {
17047            bitmap.eraseColor(drawingCacheBackgroundColor);
17048        }
17049
17050        computeScroll();
17051        final int restoreCount = canvas.save();
17052
17053        if (autoScale && scalingRequired) {
17054            final float scale = attachInfo.mApplicationScale;
17055            canvas.scale(scale, scale);
17056        }
17057
17058        canvas.translate(-mScrollX, -mScrollY);
17059
17060        mPrivateFlags |= PFLAG_DRAWN;
17061        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
17062                mLayerType != LAYER_TYPE_NONE) {
17063            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
17064        }
17065
17066        // Fast path for layouts with no backgrounds
17067        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17068            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17069            dispatchDraw(canvas);
17070            if (mOverlay != null && !mOverlay.isEmpty()) {
17071                mOverlay.getOverlayView().draw(canvas);
17072            }
17073        } else {
17074            draw(canvas);
17075        }
17076
17077        canvas.restoreToCount(restoreCount);
17078        canvas.setBitmap(null);
17079
17080        if (attachInfo != null) {
17081            // Restore the cached Canvas for our siblings
17082            attachInfo.mCanvas = canvas;
17083        }
17084    }
17085
17086    /**
17087     * Create a snapshot of the view into a bitmap.  We should probably make
17088     * some form of this public, but should think about the API.
17089     *
17090     * @hide
17091     */
17092    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
17093        int width = mRight - mLeft;
17094        int height = mBottom - mTop;
17095
17096        final AttachInfo attachInfo = mAttachInfo;
17097        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
17098        width = (int) ((width * scale) + 0.5f);
17099        height = (int) ((height * scale) + 0.5f);
17100
17101        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17102                width > 0 ? width : 1, height > 0 ? height : 1, quality);
17103        if (bitmap == null) {
17104            throw new OutOfMemoryError();
17105        }
17106
17107        Resources resources = getResources();
17108        if (resources != null) {
17109            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
17110        }
17111
17112        Canvas canvas;
17113        if (attachInfo != null) {
17114            canvas = attachInfo.mCanvas;
17115            if (canvas == null) {
17116                canvas = new Canvas();
17117            }
17118            canvas.setBitmap(bitmap);
17119            // Temporarily clobber the cached Canvas in case one of our children
17120            // is also using a drawing cache. Without this, the children would
17121            // steal the canvas by attaching their own bitmap to it and bad, bad
17122            // things would happen (invisible views, corrupted drawings, etc.)
17123            attachInfo.mCanvas = null;
17124        } else {
17125            // This case should hopefully never or seldom happen
17126            canvas = new Canvas(bitmap);
17127        }
17128
17129        if ((backgroundColor & 0xff000000) != 0) {
17130            bitmap.eraseColor(backgroundColor);
17131        }
17132
17133        computeScroll();
17134        final int restoreCount = canvas.save();
17135        canvas.scale(scale, scale);
17136        canvas.translate(-mScrollX, -mScrollY);
17137
17138        // Temporarily remove the dirty mask
17139        int flags = mPrivateFlags;
17140        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17141
17142        // Fast path for layouts with no backgrounds
17143        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17144            dispatchDraw(canvas);
17145            if (mOverlay != null && !mOverlay.isEmpty()) {
17146                mOverlay.getOverlayView().draw(canvas);
17147            }
17148        } else {
17149            draw(canvas);
17150        }
17151
17152        mPrivateFlags = flags;
17153
17154        canvas.restoreToCount(restoreCount);
17155        canvas.setBitmap(null);
17156
17157        if (attachInfo != null) {
17158            // Restore the cached Canvas for our siblings
17159            attachInfo.mCanvas = canvas;
17160        }
17161
17162        return bitmap;
17163    }
17164
17165    /**
17166     * Indicates whether this View is currently in edit mode. A View is usually
17167     * in edit mode when displayed within a developer tool. For instance, if
17168     * this View is being drawn by a visual user interface builder, this method
17169     * should return true.
17170     *
17171     * Subclasses should check the return value of this method to provide
17172     * different behaviors if their normal behavior might interfere with the
17173     * host environment. For instance: the class spawns a thread in its
17174     * constructor, the drawing code relies on device-specific features, etc.
17175     *
17176     * This method is usually checked in the drawing code of custom widgets.
17177     *
17178     * @return True if this View is in edit mode, false otherwise.
17179     */
17180    public boolean isInEditMode() {
17181        return false;
17182    }
17183
17184    /**
17185     * If the View draws content inside its padding and enables fading edges,
17186     * it needs to support padding offsets. Padding offsets are added to the
17187     * fading edges to extend the length of the fade so that it covers pixels
17188     * drawn inside the padding.
17189     *
17190     * Subclasses of this class should override this method if they need
17191     * to draw content inside the padding.
17192     *
17193     * @return True if padding offset must be applied, false otherwise.
17194     *
17195     * @see #getLeftPaddingOffset()
17196     * @see #getRightPaddingOffset()
17197     * @see #getTopPaddingOffset()
17198     * @see #getBottomPaddingOffset()
17199     *
17200     * @since CURRENT
17201     */
17202    protected boolean isPaddingOffsetRequired() {
17203        return false;
17204    }
17205
17206    /**
17207     * Amount by which to extend the left fading region. Called only when
17208     * {@link #isPaddingOffsetRequired()} returns true.
17209     *
17210     * @return The left padding offset in pixels.
17211     *
17212     * @see #isPaddingOffsetRequired()
17213     *
17214     * @since CURRENT
17215     */
17216    protected int getLeftPaddingOffset() {
17217        return 0;
17218    }
17219
17220    /**
17221     * Amount by which to extend the right fading region. Called only when
17222     * {@link #isPaddingOffsetRequired()} returns true.
17223     *
17224     * @return The right padding offset in pixels.
17225     *
17226     * @see #isPaddingOffsetRequired()
17227     *
17228     * @since CURRENT
17229     */
17230    protected int getRightPaddingOffset() {
17231        return 0;
17232    }
17233
17234    /**
17235     * Amount by which to extend the top fading region. Called only when
17236     * {@link #isPaddingOffsetRequired()} returns true.
17237     *
17238     * @return The top padding offset in pixels.
17239     *
17240     * @see #isPaddingOffsetRequired()
17241     *
17242     * @since CURRENT
17243     */
17244    protected int getTopPaddingOffset() {
17245        return 0;
17246    }
17247
17248    /**
17249     * Amount by which to extend the bottom fading region. Called only when
17250     * {@link #isPaddingOffsetRequired()} returns true.
17251     *
17252     * @return The bottom padding offset in pixels.
17253     *
17254     * @see #isPaddingOffsetRequired()
17255     *
17256     * @since CURRENT
17257     */
17258    protected int getBottomPaddingOffset() {
17259        return 0;
17260    }
17261
17262    /**
17263     * @hide
17264     * @param offsetRequired
17265     */
17266    protected int getFadeTop(boolean offsetRequired) {
17267        int top = mPaddingTop;
17268        if (offsetRequired) top += getTopPaddingOffset();
17269        return top;
17270    }
17271
17272    /**
17273     * @hide
17274     * @param offsetRequired
17275     */
17276    protected int getFadeHeight(boolean offsetRequired) {
17277        int padding = mPaddingTop;
17278        if (offsetRequired) padding += getTopPaddingOffset();
17279        return mBottom - mTop - mPaddingBottom - padding;
17280    }
17281
17282    /**
17283     * <p>Indicates whether this view is attached to a hardware accelerated
17284     * window or not.</p>
17285     *
17286     * <p>Even if this method returns true, it does not mean that every call
17287     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
17288     * accelerated {@link android.graphics.Canvas}. For instance, if this view
17289     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
17290     * window is hardware accelerated,
17291     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
17292     * return false, and this method will return true.</p>
17293     *
17294     * @return True if the view is attached to a window and the window is
17295     *         hardware accelerated; false in any other case.
17296     */
17297    @ViewDebug.ExportedProperty(category = "drawing")
17298    public boolean isHardwareAccelerated() {
17299        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
17300    }
17301
17302    /**
17303     * Sets a rectangular area on this view to which the view will be clipped
17304     * when it is drawn. Setting the value to null will remove the clip bounds
17305     * and the view will draw normally, using its full bounds.
17306     *
17307     * @param clipBounds The rectangular area, in the local coordinates of
17308     * this view, to which future drawing operations will be clipped.
17309     */
17310    public void setClipBounds(Rect clipBounds) {
17311        if (clipBounds == mClipBounds
17312                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
17313            return;
17314        }
17315        if (clipBounds != null) {
17316            if (mClipBounds == null) {
17317                mClipBounds = new Rect(clipBounds);
17318            } else {
17319                mClipBounds.set(clipBounds);
17320            }
17321        } else {
17322            mClipBounds = null;
17323        }
17324        mRenderNode.setClipBounds(mClipBounds);
17325        invalidateViewProperty(false, false);
17326    }
17327
17328    /**
17329     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
17330     *
17331     * @return A copy of the current clip bounds if clip bounds are set,
17332     * otherwise null.
17333     */
17334    public Rect getClipBounds() {
17335        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
17336    }
17337
17338
17339    /**
17340     * Populates an output rectangle with the clip bounds of the view,
17341     * returning {@code true} if successful or {@code false} if the view's
17342     * clip bounds are {@code null}.
17343     *
17344     * @param outRect rectangle in which to place the clip bounds of the view
17345     * @return {@code true} if successful or {@code false} if the view's
17346     *         clip bounds are {@code null}
17347     */
17348    public boolean getClipBounds(Rect outRect) {
17349        if (mClipBounds != null) {
17350            outRect.set(mClipBounds);
17351            return true;
17352        }
17353        return false;
17354    }
17355
17356    /**
17357     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
17358     * case of an active Animation being run on the view.
17359     */
17360    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
17361            Animation a, boolean scalingRequired) {
17362        Transformation invalidationTransform;
17363        final int flags = parent.mGroupFlags;
17364        final boolean initialized = a.isInitialized();
17365        if (!initialized) {
17366            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
17367            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
17368            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
17369            onAnimationStart();
17370        }
17371
17372        final Transformation t = parent.getChildTransformation();
17373        boolean more = a.getTransformation(drawingTime, t, 1f);
17374        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
17375            if (parent.mInvalidationTransformation == null) {
17376                parent.mInvalidationTransformation = new Transformation();
17377            }
17378            invalidationTransform = parent.mInvalidationTransformation;
17379            a.getTransformation(drawingTime, invalidationTransform, 1f);
17380        } else {
17381            invalidationTransform = t;
17382        }
17383
17384        if (more) {
17385            if (!a.willChangeBounds()) {
17386                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
17387                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
17388                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
17389                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
17390                    // The child need to draw an animation, potentially offscreen, so
17391                    // make sure we do not cancel invalidate requests
17392                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
17393                    parent.invalidate(mLeft, mTop, mRight, mBottom);
17394                }
17395            } else {
17396                if (parent.mInvalidateRegion == null) {
17397                    parent.mInvalidateRegion = new RectF();
17398                }
17399                final RectF region = parent.mInvalidateRegion;
17400                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
17401                        invalidationTransform);
17402
17403                // The child need to draw an animation, potentially offscreen, so
17404                // make sure we do not cancel invalidate requests
17405                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
17406
17407                final int left = mLeft + (int) region.left;
17408                final int top = mTop + (int) region.top;
17409                parent.invalidate(left, top, left + (int) (region.width() + .5f),
17410                        top + (int) (region.height() + .5f));
17411            }
17412        }
17413        return more;
17414    }
17415
17416    /**
17417     * This method is called by getDisplayList() when a display list is recorded for a View.
17418     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
17419     */
17420    void setDisplayListProperties(RenderNode renderNode) {
17421        if (renderNode != null) {
17422            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
17423            renderNode.setClipToBounds(mParent instanceof ViewGroup
17424                    && ((ViewGroup) mParent).getClipChildren());
17425
17426            float alpha = 1;
17427            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
17428                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
17429                ViewGroup parentVG = (ViewGroup) mParent;
17430                final Transformation t = parentVG.getChildTransformation();
17431                if (parentVG.getChildStaticTransformation(this, t)) {
17432                    final int transformType = t.getTransformationType();
17433                    if (transformType != Transformation.TYPE_IDENTITY) {
17434                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
17435                            alpha = t.getAlpha();
17436                        }
17437                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
17438                            renderNode.setStaticMatrix(t.getMatrix());
17439                        }
17440                    }
17441                }
17442            }
17443            if (mTransformationInfo != null) {
17444                alpha *= getFinalAlpha();
17445                if (alpha < 1) {
17446                    final int multipliedAlpha = (int) (255 * alpha);
17447                    if (onSetAlpha(multipliedAlpha)) {
17448                        alpha = 1;
17449                    }
17450                }
17451                renderNode.setAlpha(alpha);
17452            } else if (alpha < 1) {
17453                renderNode.setAlpha(alpha);
17454            }
17455        }
17456    }
17457
17458    /**
17459     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
17460     *
17461     * This is where the View specializes rendering behavior based on layer type,
17462     * and hardware acceleration.
17463     */
17464    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
17465        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
17466        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
17467         *
17468         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
17469         * HW accelerated, it can't handle drawing RenderNodes.
17470         */
17471        boolean drawingWithRenderNode = mAttachInfo != null
17472                && mAttachInfo.mHardwareAccelerated
17473                && hardwareAcceleratedCanvas;
17474
17475        boolean more = false;
17476        final boolean childHasIdentityMatrix = hasIdentityMatrix();
17477        final int parentFlags = parent.mGroupFlags;
17478
17479        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
17480            parent.getChildTransformation().clear();
17481            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17482        }
17483
17484        Transformation transformToApply = null;
17485        boolean concatMatrix = false;
17486        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
17487        final Animation a = getAnimation();
17488        if (a != null) {
17489            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
17490            concatMatrix = a.willChangeTransformationMatrix();
17491            if (concatMatrix) {
17492                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
17493            }
17494            transformToApply = parent.getChildTransformation();
17495        } else {
17496            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
17497                // No longer animating: clear out old animation matrix
17498                mRenderNode.setAnimationMatrix(null);
17499                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
17500            }
17501            if (!drawingWithRenderNode
17502                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
17503                final Transformation t = parent.getChildTransformation();
17504                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
17505                if (hasTransform) {
17506                    final int transformType = t.getTransformationType();
17507                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
17508                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
17509                }
17510            }
17511        }
17512
17513        concatMatrix |= !childHasIdentityMatrix;
17514
17515        // Sets the flag as early as possible to allow draw() implementations
17516        // to call invalidate() successfully when doing animations
17517        mPrivateFlags |= PFLAG_DRAWN;
17518
17519        if (!concatMatrix &&
17520                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
17521                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
17522                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
17523                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
17524            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
17525            return more;
17526        }
17527        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
17528
17529        if (hardwareAcceleratedCanvas) {
17530            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
17531            // retain the flag's value temporarily in the mRecreateDisplayList flag
17532            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
17533            mPrivateFlags &= ~PFLAG_INVALIDATED;
17534        }
17535
17536        RenderNode renderNode = null;
17537        Bitmap cache = null;
17538        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
17539        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
17540             if (layerType != LAYER_TYPE_NONE) {
17541                 // If not drawing with RenderNode, treat HW layers as SW
17542                 layerType = LAYER_TYPE_SOFTWARE;
17543                 buildDrawingCache(true);
17544            }
17545            cache = getDrawingCache(true);
17546        }
17547
17548        if (drawingWithRenderNode) {
17549            // Delay getting the display list until animation-driven alpha values are
17550            // set up and possibly passed on to the view
17551            renderNode = updateDisplayListIfDirty();
17552            if (!renderNode.isValid()) {
17553                // Uncommon, but possible. If a view is removed from the hierarchy during the call
17554                // to getDisplayList(), the display list will be marked invalid and we should not
17555                // try to use it again.
17556                renderNode = null;
17557                drawingWithRenderNode = false;
17558            }
17559        }
17560
17561        int sx = 0;
17562        int sy = 0;
17563        if (!drawingWithRenderNode) {
17564            computeScroll();
17565            sx = mScrollX;
17566            sy = mScrollY;
17567        }
17568
17569        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
17570        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
17571
17572        int restoreTo = -1;
17573        if (!drawingWithRenderNode || transformToApply != null) {
17574            restoreTo = canvas.save();
17575        }
17576        if (offsetForScroll) {
17577            canvas.translate(mLeft - sx, mTop - sy);
17578        } else {
17579            if (!drawingWithRenderNode) {
17580                canvas.translate(mLeft, mTop);
17581            }
17582            if (scalingRequired) {
17583                if (drawingWithRenderNode) {
17584                    // TODO: Might not need this if we put everything inside the DL
17585                    restoreTo = canvas.save();
17586                }
17587                // mAttachInfo cannot be null, otherwise scalingRequired == false
17588                final float scale = 1.0f / mAttachInfo.mApplicationScale;
17589                canvas.scale(scale, scale);
17590            }
17591        }
17592
17593        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
17594        if (transformToApply != null
17595                || alpha < 1
17596                || !hasIdentityMatrix()
17597                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17598            if (transformToApply != null || !childHasIdentityMatrix) {
17599                int transX = 0;
17600                int transY = 0;
17601
17602                if (offsetForScroll) {
17603                    transX = -sx;
17604                    transY = -sy;
17605                }
17606
17607                if (transformToApply != null) {
17608                    if (concatMatrix) {
17609                        if (drawingWithRenderNode) {
17610                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
17611                        } else {
17612                            // Undo the scroll translation, apply the transformation matrix,
17613                            // then redo the scroll translate to get the correct result.
17614                            canvas.translate(-transX, -transY);
17615                            canvas.concat(transformToApply.getMatrix());
17616                            canvas.translate(transX, transY);
17617                        }
17618                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17619                    }
17620
17621                    float transformAlpha = transformToApply.getAlpha();
17622                    if (transformAlpha < 1) {
17623                        alpha *= transformAlpha;
17624                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17625                    }
17626                }
17627
17628                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
17629                    canvas.translate(-transX, -transY);
17630                    canvas.concat(getMatrix());
17631                    canvas.translate(transX, transY);
17632                }
17633            }
17634
17635            // Deal with alpha if it is or used to be <1
17636            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17637                if (alpha < 1) {
17638                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17639                } else {
17640                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17641                }
17642                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17643                if (!drawingWithDrawingCache) {
17644                    final int multipliedAlpha = (int) (255 * alpha);
17645                    if (!onSetAlpha(multipliedAlpha)) {
17646                        if (drawingWithRenderNode) {
17647                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
17648                        } else if (layerType == LAYER_TYPE_NONE) {
17649                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
17650                                    multipliedAlpha);
17651                        }
17652                    } else {
17653                        // Alpha is handled by the child directly, clobber the layer's alpha
17654                        mPrivateFlags |= PFLAG_ALPHA_SET;
17655                    }
17656                }
17657            }
17658        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17659            onSetAlpha(255);
17660            mPrivateFlags &= ~PFLAG_ALPHA_SET;
17661        }
17662
17663        if (!drawingWithRenderNode) {
17664            // apply clips directly, since RenderNode won't do it for this draw
17665            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
17666                if (offsetForScroll) {
17667                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
17668                } else {
17669                    if (!scalingRequired || cache == null) {
17670                        canvas.clipRect(0, 0, getWidth(), getHeight());
17671                    } else {
17672                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
17673                    }
17674                }
17675            }
17676
17677            if (mClipBounds != null) {
17678                // clip bounds ignore scroll
17679                canvas.clipRect(mClipBounds);
17680            }
17681        }
17682
17683        if (!drawingWithDrawingCache) {
17684            if (drawingWithRenderNode) {
17685                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17686                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17687            } else {
17688                // Fast path for layouts with no backgrounds
17689                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17690                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17691                    dispatchDraw(canvas);
17692                } else {
17693                    draw(canvas);
17694                }
17695            }
17696        } else if (cache != null) {
17697            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17698            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
17699                // no layer paint, use temporary paint to draw bitmap
17700                Paint cachePaint = parent.mCachePaint;
17701                if (cachePaint == null) {
17702                    cachePaint = new Paint();
17703                    cachePaint.setDither(false);
17704                    parent.mCachePaint = cachePaint;
17705                }
17706                cachePaint.setAlpha((int) (alpha * 255));
17707                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
17708            } else {
17709                // use layer paint to draw the bitmap, merging the two alphas, but also restore
17710                int layerPaintAlpha = mLayerPaint.getAlpha();
17711                if (alpha < 1) {
17712                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
17713                }
17714                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
17715                if (alpha < 1) {
17716                    mLayerPaint.setAlpha(layerPaintAlpha);
17717                }
17718            }
17719        }
17720
17721        if (restoreTo >= 0) {
17722            canvas.restoreToCount(restoreTo);
17723        }
17724
17725        if (a != null && !more) {
17726            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
17727                onSetAlpha(255);
17728            }
17729            parent.finishAnimatingView(this, a);
17730        }
17731
17732        if (more && hardwareAcceleratedCanvas) {
17733            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17734                // alpha animations should cause the child to recreate its display list
17735                invalidate(true);
17736            }
17737        }
17738
17739        mRecreateDisplayList = false;
17740
17741        return more;
17742    }
17743
17744    static Paint getDebugPaint() {
17745        if (sDebugPaint == null) {
17746            sDebugPaint = new Paint();
17747            sDebugPaint.setAntiAlias(false);
17748        }
17749        return sDebugPaint;
17750    }
17751
17752    final int dipsToPixels(int dips) {
17753        float scale = getContext().getResources().getDisplayMetrics().density;
17754        return (int) (dips * scale + 0.5f);
17755    }
17756
17757    final private void debugDrawFocus(Canvas canvas) {
17758        if (isFocused()) {
17759            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
17760            final int l = mScrollX;
17761            final int r = l + mRight - mLeft;
17762            final int t = mScrollY;
17763            final int b = t + mBottom - mTop;
17764
17765            final Paint paint = getDebugPaint();
17766            paint.setColor(DEBUG_CORNERS_COLOR);
17767
17768            // Draw squares in corners.
17769            paint.setStyle(Paint.Style.FILL);
17770            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
17771            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
17772            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
17773            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
17774
17775            // Draw big X across the view.
17776            paint.setStyle(Paint.Style.STROKE);
17777            canvas.drawLine(l, t, r, b, paint);
17778            canvas.drawLine(l, b, r, t, paint);
17779        }
17780    }
17781
17782    /**
17783     * Manually render this view (and all of its children) to the given Canvas.
17784     * The view must have already done a full layout before this function is
17785     * called.  When implementing a view, implement
17786     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
17787     * If you do need to override this method, call the superclass version.
17788     *
17789     * @param canvas The Canvas to which the View is rendered.
17790     */
17791    @CallSuper
17792    public void draw(Canvas canvas) {
17793        final int privateFlags = mPrivateFlags;
17794        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
17795                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
17796        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
17797
17798        /*
17799         * Draw traversal performs several drawing steps which must be executed
17800         * in the appropriate order:
17801         *
17802         *      1. Draw the background
17803         *      2. If necessary, save the canvas' layers to prepare for fading
17804         *      3. Draw view's content
17805         *      4. Draw children
17806         *      5. If necessary, draw the fading edges and restore layers
17807         *      6. Draw decorations (scrollbars for instance)
17808         */
17809
17810        // Step 1, draw the background, if needed
17811        int saveCount;
17812
17813        if (!dirtyOpaque) {
17814            drawBackground(canvas);
17815        }
17816
17817        // skip step 2 & 5 if possible (common case)
17818        final int viewFlags = mViewFlags;
17819        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
17820        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
17821        if (!verticalEdges && !horizontalEdges) {
17822            // Step 3, draw the content
17823            if (!dirtyOpaque) onDraw(canvas);
17824
17825            // Step 4, draw the children
17826            dispatchDraw(canvas);
17827
17828            // Overlay is part of the content and draws beneath Foreground
17829            if (mOverlay != null && !mOverlay.isEmpty()) {
17830                mOverlay.getOverlayView().dispatchDraw(canvas);
17831            }
17832
17833            // Step 6, draw decorations (foreground, scrollbars)
17834            onDrawForeground(canvas);
17835
17836            if (debugDraw()) {
17837                debugDrawFocus(canvas);
17838            }
17839
17840            // we're done...
17841            return;
17842        }
17843
17844        /*
17845         * Here we do the full fledged routine...
17846         * (this is an uncommon case where speed matters less,
17847         * this is why we repeat some of the tests that have been
17848         * done above)
17849         */
17850
17851        boolean drawTop = false;
17852        boolean drawBottom = false;
17853        boolean drawLeft = false;
17854        boolean drawRight = false;
17855
17856        float topFadeStrength = 0.0f;
17857        float bottomFadeStrength = 0.0f;
17858        float leftFadeStrength = 0.0f;
17859        float rightFadeStrength = 0.0f;
17860
17861        // Step 2, save the canvas' layers
17862        int paddingLeft = mPaddingLeft;
17863
17864        final boolean offsetRequired = isPaddingOffsetRequired();
17865        if (offsetRequired) {
17866            paddingLeft += getLeftPaddingOffset();
17867        }
17868
17869        int left = mScrollX + paddingLeft;
17870        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
17871        int top = mScrollY + getFadeTop(offsetRequired);
17872        int bottom = top + getFadeHeight(offsetRequired);
17873
17874        if (offsetRequired) {
17875            right += getRightPaddingOffset();
17876            bottom += getBottomPaddingOffset();
17877        }
17878
17879        final ScrollabilityCache scrollabilityCache = mScrollCache;
17880        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
17881        int length = (int) fadeHeight;
17882
17883        // clip the fade length if top and bottom fades overlap
17884        // overlapping fades produce odd-looking artifacts
17885        if (verticalEdges && (top + length > bottom - length)) {
17886            length = (bottom - top) / 2;
17887        }
17888
17889        // also clip horizontal fades if necessary
17890        if (horizontalEdges && (left + length > right - length)) {
17891            length = (right - left) / 2;
17892        }
17893
17894        if (verticalEdges) {
17895            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
17896            drawTop = topFadeStrength * fadeHeight > 1.0f;
17897            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
17898            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
17899        }
17900
17901        if (horizontalEdges) {
17902            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
17903            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
17904            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
17905            drawRight = rightFadeStrength * fadeHeight > 1.0f;
17906        }
17907
17908        saveCount = canvas.getSaveCount();
17909
17910        int solidColor = getSolidColor();
17911        if (solidColor == 0) {
17912            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
17913
17914            if (drawTop) {
17915                canvas.saveLayer(left, top, right, top + length, null, flags);
17916            }
17917
17918            if (drawBottom) {
17919                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
17920            }
17921
17922            if (drawLeft) {
17923                canvas.saveLayer(left, top, left + length, bottom, null, flags);
17924            }
17925
17926            if (drawRight) {
17927                canvas.saveLayer(right - length, top, right, bottom, null, flags);
17928            }
17929        } else {
17930            scrollabilityCache.setFadeColor(solidColor);
17931        }
17932
17933        // Step 3, draw the content
17934        if (!dirtyOpaque) onDraw(canvas);
17935
17936        // Step 4, draw the children
17937        dispatchDraw(canvas);
17938
17939        // Step 5, draw the fade effect and restore layers
17940        final Paint p = scrollabilityCache.paint;
17941        final Matrix matrix = scrollabilityCache.matrix;
17942        final Shader fade = scrollabilityCache.shader;
17943
17944        if (drawTop) {
17945            matrix.setScale(1, fadeHeight * topFadeStrength);
17946            matrix.postTranslate(left, top);
17947            fade.setLocalMatrix(matrix);
17948            p.setShader(fade);
17949            canvas.drawRect(left, top, right, top + length, p);
17950        }
17951
17952        if (drawBottom) {
17953            matrix.setScale(1, fadeHeight * bottomFadeStrength);
17954            matrix.postRotate(180);
17955            matrix.postTranslate(left, bottom);
17956            fade.setLocalMatrix(matrix);
17957            p.setShader(fade);
17958            canvas.drawRect(left, bottom - length, right, bottom, p);
17959        }
17960
17961        if (drawLeft) {
17962            matrix.setScale(1, fadeHeight * leftFadeStrength);
17963            matrix.postRotate(-90);
17964            matrix.postTranslate(left, top);
17965            fade.setLocalMatrix(matrix);
17966            p.setShader(fade);
17967            canvas.drawRect(left, top, left + length, bottom, p);
17968        }
17969
17970        if (drawRight) {
17971            matrix.setScale(1, fadeHeight * rightFadeStrength);
17972            matrix.postRotate(90);
17973            matrix.postTranslate(right, top);
17974            fade.setLocalMatrix(matrix);
17975            p.setShader(fade);
17976            canvas.drawRect(right - length, top, right, bottom, p);
17977        }
17978
17979        canvas.restoreToCount(saveCount);
17980
17981        // Overlay is part of the content and draws beneath Foreground
17982        if (mOverlay != null && !mOverlay.isEmpty()) {
17983            mOverlay.getOverlayView().dispatchDraw(canvas);
17984        }
17985
17986        // Step 6, draw decorations (foreground, scrollbars)
17987        onDrawForeground(canvas);
17988
17989        if (debugDraw()) {
17990            debugDrawFocus(canvas);
17991        }
17992    }
17993
17994    /**
17995     * Draws the background onto the specified canvas.
17996     *
17997     * @param canvas Canvas on which to draw the background
17998     */
17999    private void drawBackground(Canvas canvas) {
18000        final Drawable background = mBackground;
18001        if (background == null) {
18002            return;
18003        }
18004
18005        setBackgroundBounds();
18006
18007        // Attempt to use a display list if requested.
18008        if (canvas.isHardwareAccelerated() && mAttachInfo != null
18009                && mAttachInfo.mThreadedRenderer != null) {
18010            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
18011
18012            final RenderNode renderNode = mBackgroundRenderNode;
18013            if (renderNode != null && renderNode.isValid()) {
18014                setBackgroundRenderNodeProperties(renderNode);
18015                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18016                return;
18017            }
18018        }
18019
18020        final int scrollX = mScrollX;
18021        final int scrollY = mScrollY;
18022        if ((scrollX | scrollY) == 0) {
18023            background.draw(canvas);
18024        } else {
18025            canvas.translate(scrollX, scrollY);
18026            background.draw(canvas);
18027            canvas.translate(-scrollX, -scrollY);
18028        }
18029    }
18030
18031    /**
18032     * Sets the correct background bounds and rebuilds the outline, if needed.
18033     * <p/>
18034     * This is called by LayoutLib.
18035     */
18036    void setBackgroundBounds() {
18037        if (mBackgroundSizeChanged && mBackground != null) {
18038            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
18039            mBackgroundSizeChanged = false;
18040            rebuildOutline();
18041        }
18042    }
18043
18044    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
18045        renderNode.setTranslationX(mScrollX);
18046        renderNode.setTranslationY(mScrollY);
18047    }
18048
18049    /**
18050     * Creates a new display list or updates the existing display list for the
18051     * specified Drawable.
18052     *
18053     * @param drawable Drawable for which to create a display list
18054     * @param renderNode Existing RenderNode, or {@code null}
18055     * @return A valid display list for the specified drawable
18056     */
18057    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
18058        if (renderNode == null) {
18059            renderNode = RenderNode.create(drawable.getClass().getName(), this);
18060        }
18061
18062        final Rect bounds = drawable.getBounds();
18063        final int width = bounds.width();
18064        final int height = bounds.height();
18065        final DisplayListCanvas canvas = renderNode.start(width, height);
18066
18067        // Reverse left/top translation done by drawable canvas, which will
18068        // instead be applied by rendernode's LTRB bounds below. This way, the
18069        // drawable's bounds match with its rendernode bounds and its content
18070        // will lie within those bounds in the rendernode tree.
18071        canvas.translate(-bounds.left, -bounds.top);
18072
18073        try {
18074            drawable.draw(canvas);
18075        } finally {
18076            renderNode.end(canvas);
18077        }
18078
18079        // Set up drawable properties that are view-independent.
18080        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
18081        renderNode.setProjectBackwards(drawable.isProjected());
18082        renderNode.setProjectionReceiver(true);
18083        renderNode.setClipToBounds(false);
18084        return renderNode;
18085    }
18086
18087    /**
18088     * Returns the overlay for this view, creating it if it does not yet exist.
18089     * Adding drawables to the overlay will cause them to be displayed whenever
18090     * the view itself is redrawn. Objects in the overlay should be actively
18091     * managed: remove them when they should not be displayed anymore. The
18092     * overlay will always have the same size as its host view.
18093     *
18094     * <p>Note: Overlays do not currently work correctly with {@link
18095     * SurfaceView} or {@link TextureView}; contents in overlays for these
18096     * types of views may not display correctly.</p>
18097     *
18098     * @return The ViewOverlay object for this view.
18099     * @see ViewOverlay
18100     */
18101    public ViewOverlay getOverlay() {
18102        if (mOverlay == null) {
18103            mOverlay = new ViewOverlay(mContext, this);
18104        }
18105        return mOverlay;
18106    }
18107
18108    /**
18109     * Override this if your view is known to always be drawn on top of a solid color background,
18110     * and needs to draw fading edges. Returning a non-zero color enables the view system to
18111     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
18112     * should be set to 0xFF.
18113     *
18114     * @see #setVerticalFadingEdgeEnabled(boolean)
18115     * @see #setHorizontalFadingEdgeEnabled(boolean)
18116     *
18117     * @return The known solid color background for this view, or 0 if the color may vary
18118     */
18119    @ViewDebug.ExportedProperty(category = "drawing")
18120    @ColorInt
18121    public int getSolidColor() {
18122        return 0;
18123    }
18124
18125    /**
18126     * Build a human readable string representation of the specified view flags.
18127     *
18128     * @param flags the view flags to convert to a string
18129     * @return a String representing the supplied flags
18130     */
18131    private static String printFlags(int flags) {
18132        String output = "";
18133        int numFlags = 0;
18134        if ((flags & FOCUSABLE) == FOCUSABLE) {
18135            output += "TAKES_FOCUS";
18136            numFlags++;
18137        }
18138
18139        switch (flags & VISIBILITY_MASK) {
18140        case INVISIBLE:
18141            if (numFlags > 0) {
18142                output += " ";
18143            }
18144            output += "INVISIBLE";
18145            // USELESS HERE numFlags++;
18146            break;
18147        case GONE:
18148            if (numFlags > 0) {
18149                output += " ";
18150            }
18151            output += "GONE";
18152            // USELESS HERE numFlags++;
18153            break;
18154        default:
18155            break;
18156        }
18157        return output;
18158    }
18159
18160    /**
18161     * Build a human readable string representation of the specified private
18162     * view flags.
18163     *
18164     * @param privateFlags the private view flags to convert to a string
18165     * @return a String representing the supplied flags
18166     */
18167    private static String printPrivateFlags(int privateFlags) {
18168        String output = "";
18169        int numFlags = 0;
18170
18171        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
18172            output += "WANTS_FOCUS";
18173            numFlags++;
18174        }
18175
18176        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
18177            if (numFlags > 0) {
18178                output += " ";
18179            }
18180            output += "FOCUSED";
18181            numFlags++;
18182        }
18183
18184        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
18185            if (numFlags > 0) {
18186                output += " ";
18187            }
18188            output += "SELECTED";
18189            numFlags++;
18190        }
18191
18192        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
18193            if (numFlags > 0) {
18194                output += " ";
18195            }
18196            output += "IS_ROOT_NAMESPACE";
18197            numFlags++;
18198        }
18199
18200        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
18201            if (numFlags > 0) {
18202                output += " ";
18203            }
18204            output += "HAS_BOUNDS";
18205            numFlags++;
18206        }
18207
18208        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
18209            if (numFlags > 0) {
18210                output += " ";
18211            }
18212            output += "DRAWN";
18213            // USELESS HERE numFlags++;
18214        }
18215        return output;
18216    }
18217
18218    /**
18219     * <p>Indicates whether or not this view's layout will be requested during
18220     * the next hierarchy layout pass.</p>
18221     *
18222     * @return true if the layout will be forced during next layout pass
18223     */
18224    public boolean isLayoutRequested() {
18225        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
18226    }
18227
18228    /**
18229     * Return true if o is a ViewGroup that is laying out using optical bounds.
18230     * @hide
18231     */
18232    public static boolean isLayoutModeOptical(Object o) {
18233        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
18234    }
18235
18236    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
18237        Insets parentInsets = mParent instanceof View ?
18238                ((View) mParent).getOpticalInsets() : Insets.NONE;
18239        Insets childInsets = getOpticalInsets();
18240        return setFrame(
18241                left   + parentInsets.left - childInsets.left,
18242                top    + parentInsets.top  - childInsets.top,
18243                right  + parentInsets.left + childInsets.right,
18244                bottom + parentInsets.top  + childInsets.bottom);
18245    }
18246
18247    /**
18248     * Assign a size and position to a view and all of its
18249     * descendants
18250     *
18251     * <p>This is the second phase of the layout mechanism.
18252     * (The first is measuring). In this phase, each parent calls
18253     * layout on all of its children to position them.
18254     * This is typically done using the child measurements
18255     * that were stored in the measure pass().</p>
18256     *
18257     * <p>Derived classes should not override this method.
18258     * Derived classes with children should override
18259     * onLayout. In that method, they should
18260     * call layout on each of their children.</p>
18261     *
18262     * @param l Left position, relative to parent
18263     * @param t Top position, relative to parent
18264     * @param r Right position, relative to parent
18265     * @param b Bottom position, relative to parent
18266     */
18267    @SuppressWarnings({"unchecked"})
18268    public void layout(int l, int t, int r, int b) {
18269        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
18270            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
18271            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18272        }
18273
18274        int oldL = mLeft;
18275        int oldT = mTop;
18276        int oldB = mBottom;
18277        int oldR = mRight;
18278
18279        boolean changed = isLayoutModeOptical(mParent) ?
18280                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
18281
18282        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
18283            onLayout(changed, l, t, r, b);
18284
18285            if (shouldDrawRoundScrollbar()) {
18286                if(mRoundScrollbarRenderer == null) {
18287                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
18288                }
18289            } else {
18290                mRoundScrollbarRenderer = null;
18291            }
18292
18293            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
18294
18295            ListenerInfo li = mListenerInfo;
18296            if (li != null && li.mOnLayoutChangeListeners != null) {
18297                ArrayList<OnLayoutChangeListener> listenersCopy =
18298                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
18299                int numListeners = listenersCopy.size();
18300                for (int i = 0; i < numListeners; ++i) {
18301                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
18302                }
18303            }
18304        }
18305
18306        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
18307        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
18308    }
18309
18310    /**
18311     * Called from layout when this view should
18312     * assign a size and position to each of its children.
18313     *
18314     * Derived classes with children should override
18315     * this method and call layout on each of
18316     * their children.
18317     * @param changed This is a new size or position for this view
18318     * @param left Left position, relative to parent
18319     * @param top Top position, relative to parent
18320     * @param right Right position, relative to parent
18321     * @param bottom Bottom position, relative to parent
18322     */
18323    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
18324    }
18325
18326    /**
18327     * Assign a size and position to this view.
18328     *
18329     * This is called from layout.
18330     *
18331     * @param left Left position, relative to parent
18332     * @param top Top position, relative to parent
18333     * @param right Right position, relative to parent
18334     * @param bottom Bottom position, relative to parent
18335     * @return true if the new size and position are different than the
18336     *         previous ones
18337     * {@hide}
18338     */
18339    protected boolean setFrame(int left, int top, int right, int bottom) {
18340        boolean changed = false;
18341
18342        if (DBG) {
18343            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
18344                    + right + "," + bottom + ")");
18345        }
18346
18347        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
18348            changed = true;
18349
18350            // Remember our drawn bit
18351            int drawn = mPrivateFlags & PFLAG_DRAWN;
18352
18353            int oldWidth = mRight - mLeft;
18354            int oldHeight = mBottom - mTop;
18355            int newWidth = right - left;
18356            int newHeight = bottom - top;
18357            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
18358
18359            // Invalidate our old position
18360            invalidate(sizeChanged);
18361
18362            mLeft = left;
18363            mTop = top;
18364            mRight = right;
18365            mBottom = bottom;
18366            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
18367
18368            mPrivateFlags |= PFLAG_HAS_BOUNDS;
18369
18370
18371            if (sizeChanged) {
18372                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
18373            }
18374
18375            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
18376                // If we are visible, force the DRAWN bit to on so that
18377                // this invalidate will go through (at least to our parent).
18378                // This is because someone may have invalidated this view
18379                // before this call to setFrame came in, thereby clearing
18380                // the DRAWN bit.
18381                mPrivateFlags |= PFLAG_DRAWN;
18382                invalidate(sizeChanged);
18383                // parent display list may need to be recreated based on a change in the bounds
18384                // of any child
18385                invalidateParentCaches();
18386            }
18387
18388            // Reset drawn bit to original value (invalidate turns it off)
18389            mPrivateFlags |= drawn;
18390
18391            mBackgroundSizeChanged = true;
18392            if (mForegroundInfo != null) {
18393                mForegroundInfo.mBoundsChanged = true;
18394            }
18395
18396            notifySubtreeAccessibilityStateChangedIfNeeded();
18397        }
18398        return changed;
18399    }
18400
18401    /**
18402     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
18403     * @hide
18404     */
18405    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
18406        setFrame(left, top, right, bottom);
18407    }
18408
18409    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
18410        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
18411        if (mOverlay != null) {
18412            mOverlay.getOverlayView().setRight(newWidth);
18413            mOverlay.getOverlayView().setBottom(newHeight);
18414        }
18415        rebuildOutline();
18416    }
18417
18418    /**
18419     * Finalize inflating a view from XML.  This is called as the last phase
18420     * of inflation, after all child views have been added.
18421     *
18422     * <p>Even if the subclass overrides onFinishInflate, they should always be
18423     * sure to call the super method, so that we get called.
18424     */
18425    @CallSuper
18426    protected void onFinishInflate() {
18427    }
18428
18429    /**
18430     * Returns the resources associated with this view.
18431     *
18432     * @return Resources object.
18433     */
18434    public Resources getResources() {
18435        return mResources;
18436    }
18437
18438    /**
18439     * Invalidates the specified Drawable.
18440     *
18441     * @param drawable the drawable to invalidate
18442     */
18443    @Override
18444    public void invalidateDrawable(@NonNull Drawable drawable) {
18445        if (verifyDrawable(drawable)) {
18446            final Rect dirty = drawable.getDirtyBounds();
18447            final int scrollX = mScrollX;
18448            final int scrollY = mScrollY;
18449
18450            invalidate(dirty.left + scrollX, dirty.top + scrollY,
18451                    dirty.right + scrollX, dirty.bottom + scrollY);
18452            rebuildOutline();
18453        }
18454    }
18455
18456    /**
18457     * Schedules an action on a drawable to occur at a specified time.
18458     *
18459     * @param who the recipient of the action
18460     * @param what the action to run on the drawable
18461     * @param when the time at which the action must occur. Uses the
18462     *        {@link SystemClock#uptimeMillis} timebase.
18463     */
18464    @Override
18465    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
18466        if (verifyDrawable(who) && what != null) {
18467            final long delay = when - SystemClock.uptimeMillis();
18468            if (mAttachInfo != null) {
18469                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
18470                        Choreographer.CALLBACK_ANIMATION, what, who,
18471                        Choreographer.subtractFrameDelay(delay));
18472            } else {
18473                // Postpone the runnable until we know
18474                // on which thread it needs to run.
18475                getRunQueue().postDelayed(what, delay);
18476            }
18477        }
18478    }
18479
18480    /**
18481     * Cancels a scheduled action on a drawable.
18482     *
18483     * @param who the recipient of the action
18484     * @param what the action to cancel
18485     */
18486    @Override
18487    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
18488        if (verifyDrawable(who) && what != null) {
18489            if (mAttachInfo != null) {
18490                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
18491                        Choreographer.CALLBACK_ANIMATION, what, who);
18492            }
18493            getRunQueue().removeCallbacks(what);
18494        }
18495    }
18496
18497    /**
18498     * Unschedule any events associated with the given Drawable.  This can be
18499     * used when selecting a new Drawable into a view, so that the previous
18500     * one is completely unscheduled.
18501     *
18502     * @param who The Drawable to unschedule.
18503     *
18504     * @see #drawableStateChanged
18505     */
18506    public void unscheduleDrawable(Drawable who) {
18507        if (mAttachInfo != null && who != null) {
18508            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
18509                    Choreographer.CALLBACK_ANIMATION, null, who);
18510        }
18511    }
18512
18513    /**
18514     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
18515     * that the View directionality can and will be resolved before its Drawables.
18516     *
18517     * Will call {@link View#onResolveDrawables} when resolution is done.
18518     *
18519     * @hide
18520     */
18521    protected void resolveDrawables() {
18522        // Drawables resolution may need to happen before resolving the layout direction (which is
18523        // done only during the measure() call).
18524        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
18525        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
18526        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
18527        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
18528        // direction to be resolved as its resolved value will be the same as its raw value.
18529        if (!isLayoutDirectionResolved() &&
18530                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
18531            return;
18532        }
18533
18534        final int layoutDirection = isLayoutDirectionResolved() ?
18535                getLayoutDirection() : getRawLayoutDirection();
18536
18537        if (mBackground != null) {
18538            mBackground.setLayoutDirection(layoutDirection);
18539        }
18540        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18541            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
18542        }
18543        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
18544        onResolveDrawables(layoutDirection);
18545    }
18546
18547    boolean areDrawablesResolved() {
18548        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
18549    }
18550
18551    /**
18552     * Called when layout direction has been resolved.
18553     *
18554     * The default implementation does nothing.
18555     *
18556     * @param layoutDirection The resolved layout direction.
18557     *
18558     * @see #LAYOUT_DIRECTION_LTR
18559     * @see #LAYOUT_DIRECTION_RTL
18560     *
18561     * @hide
18562     */
18563    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
18564    }
18565
18566    /**
18567     * @hide
18568     */
18569    protected void resetResolvedDrawables() {
18570        resetResolvedDrawablesInternal();
18571    }
18572
18573    void resetResolvedDrawablesInternal() {
18574        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
18575    }
18576
18577    /**
18578     * If your view subclass is displaying its own Drawable objects, it should
18579     * override this function and return true for any Drawable it is
18580     * displaying.  This allows animations for those drawables to be
18581     * scheduled.
18582     *
18583     * <p>Be sure to call through to the super class when overriding this
18584     * function.
18585     *
18586     * @param who The Drawable to verify.  Return true if it is one you are
18587     *            displaying, else return the result of calling through to the
18588     *            super class.
18589     *
18590     * @return boolean If true than the Drawable is being displayed in the
18591     *         view; else false and it is not allowed to animate.
18592     *
18593     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
18594     * @see #drawableStateChanged()
18595     */
18596    @CallSuper
18597    protected boolean verifyDrawable(@NonNull Drawable who) {
18598        // Avoid verifying the scroll bar drawable so that we don't end up in
18599        // an invalidation loop. This effectively prevents the scroll bar
18600        // drawable from triggering invalidations and scheduling runnables.
18601        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
18602    }
18603
18604    /**
18605     * This function is called whenever the state of the view changes in such
18606     * a way that it impacts the state of drawables being shown.
18607     * <p>
18608     * If the View has a StateListAnimator, it will also be called to run necessary state
18609     * change animations.
18610     * <p>
18611     * Be sure to call through to the superclass when overriding this function.
18612     *
18613     * @see Drawable#setState(int[])
18614     */
18615    @CallSuper
18616    protected void drawableStateChanged() {
18617        final int[] state = getDrawableState();
18618        boolean changed = false;
18619
18620        final Drawable bg = mBackground;
18621        if (bg != null && bg.isStateful()) {
18622            changed |= bg.setState(state);
18623        }
18624
18625        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18626        if (fg != null && fg.isStateful()) {
18627            changed |= fg.setState(state);
18628        }
18629
18630        if (mScrollCache != null) {
18631            final Drawable scrollBar = mScrollCache.scrollBar;
18632            if (scrollBar != null && scrollBar.isStateful()) {
18633                changed |= scrollBar.setState(state)
18634                        && mScrollCache.state != ScrollabilityCache.OFF;
18635            }
18636        }
18637
18638        if (mStateListAnimator != null) {
18639            mStateListAnimator.setState(state);
18640        }
18641
18642        if (changed) {
18643            invalidate();
18644        }
18645    }
18646
18647    /**
18648     * This function is called whenever the view hotspot changes and needs to
18649     * be propagated to drawables or child views managed by the view.
18650     * <p>
18651     * Dispatching to child views is handled by
18652     * {@link #dispatchDrawableHotspotChanged(float, float)}.
18653     * <p>
18654     * Be sure to call through to the superclass when overriding this function.
18655     *
18656     * @param x hotspot x coordinate
18657     * @param y hotspot y coordinate
18658     */
18659    @CallSuper
18660    public void drawableHotspotChanged(float x, float y) {
18661        if (mBackground != null) {
18662            mBackground.setHotspot(x, y);
18663        }
18664        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18665            mForegroundInfo.mDrawable.setHotspot(x, y);
18666        }
18667
18668        dispatchDrawableHotspotChanged(x, y);
18669    }
18670
18671    /**
18672     * Dispatches drawableHotspotChanged to all of this View's children.
18673     *
18674     * @param x hotspot x coordinate
18675     * @param y hotspot y coordinate
18676     * @see #drawableHotspotChanged(float, float)
18677     */
18678    public void dispatchDrawableHotspotChanged(float x, float y) {
18679    }
18680
18681    /**
18682     * Call this to force a view to update its drawable state. This will cause
18683     * drawableStateChanged to be called on this view. Views that are interested
18684     * in the new state should call getDrawableState.
18685     *
18686     * @see #drawableStateChanged
18687     * @see #getDrawableState
18688     */
18689    public void refreshDrawableState() {
18690        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
18691        drawableStateChanged();
18692
18693        ViewParent parent = mParent;
18694        if (parent != null) {
18695            parent.childDrawableStateChanged(this);
18696        }
18697    }
18698
18699    /**
18700     * Return an array of resource IDs of the drawable states representing the
18701     * current state of the view.
18702     *
18703     * @return The current drawable state
18704     *
18705     * @see Drawable#setState(int[])
18706     * @see #drawableStateChanged()
18707     * @see #onCreateDrawableState(int)
18708     */
18709    public final int[] getDrawableState() {
18710        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
18711            return mDrawableState;
18712        } else {
18713            mDrawableState = onCreateDrawableState(0);
18714            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
18715            return mDrawableState;
18716        }
18717    }
18718
18719    /**
18720     * Generate the new {@link android.graphics.drawable.Drawable} state for
18721     * this view. This is called by the view
18722     * system when the cached Drawable state is determined to be invalid.  To
18723     * retrieve the current state, you should use {@link #getDrawableState}.
18724     *
18725     * @param extraSpace if non-zero, this is the number of extra entries you
18726     * would like in the returned array in which you can place your own
18727     * states.
18728     *
18729     * @return Returns an array holding the current {@link Drawable} state of
18730     * the view.
18731     *
18732     * @see #mergeDrawableStates(int[], int[])
18733     */
18734    protected int[] onCreateDrawableState(int extraSpace) {
18735        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
18736                mParent instanceof View) {
18737            return ((View) mParent).onCreateDrawableState(extraSpace);
18738        }
18739
18740        int[] drawableState;
18741
18742        int privateFlags = mPrivateFlags;
18743
18744        int viewStateIndex = 0;
18745        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
18746        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
18747        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
18748        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
18749        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
18750        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
18751        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
18752                ThreadedRenderer.isAvailable()) {
18753            // This is set if HW acceleration is requested, even if the current
18754            // process doesn't allow it.  This is just to allow app preview
18755            // windows to better match their app.
18756            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
18757        }
18758        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
18759
18760        final int privateFlags2 = mPrivateFlags2;
18761        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
18762            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
18763        }
18764        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
18765            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
18766        }
18767
18768        drawableState = StateSet.get(viewStateIndex);
18769
18770        //noinspection ConstantIfStatement
18771        if (false) {
18772            Log.i("View", "drawableStateIndex=" + viewStateIndex);
18773            Log.i("View", toString()
18774                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
18775                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
18776                    + " fo=" + hasFocus()
18777                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
18778                    + " wf=" + hasWindowFocus()
18779                    + ": " + Arrays.toString(drawableState));
18780        }
18781
18782        if (extraSpace == 0) {
18783            return drawableState;
18784        }
18785
18786        final int[] fullState;
18787        if (drawableState != null) {
18788            fullState = new int[drawableState.length + extraSpace];
18789            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
18790        } else {
18791            fullState = new int[extraSpace];
18792        }
18793
18794        return fullState;
18795    }
18796
18797    /**
18798     * Merge your own state values in <var>additionalState</var> into the base
18799     * state values <var>baseState</var> that were returned by
18800     * {@link #onCreateDrawableState(int)}.
18801     *
18802     * @param baseState The base state values returned by
18803     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
18804     * own additional state values.
18805     *
18806     * @param additionalState The additional state values you would like
18807     * added to <var>baseState</var>; this array is not modified.
18808     *
18809     * @return As a convenience, the <var>baseState</var> array you originally
18810     * passed into the function is returned.
18811     *
18812     * @see #onCreateDrawableState(int)
18813     */
18814    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
18815        final int N = baseState.length;
18816        int i = N - 1;
18817        while (i >= 0 && baseState[i] == 0) {
18818            i--;
18819        }
18820        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
18821        return baseState;
18822    }
18823
18824    /**
18825     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
18826     * on all Drawable objects associated with this view.
18827     * <p>
18828     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
18829     * attached to this view.
18830     */
18831    @CallSuper
18832    public void jumpDrawablesToCurrentState() {
18833        if (mBackground != null) {
18834            mBackground.jumpToCurrentState();
18835        }
18836        if (mStateListAnimator != null) {
18837            mStateListAnimator.jumpToCurrentState();
18838        }
18839        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18840            mForegroundInfo.mDrawable.jumpToCurrentState();
18841        }
18842    }
18843
18844    /**
18845     * Sets the background color for this view.
18846     * @param color the color of the background
18847     */
18848    @RemotableViewMethod
18849    public void setBackgroundColor(@ColorInt int color) {
18850        if (mBackground instanceof ColorDrawable) {
18851            ((ColorDrawable) mBackground.mutate()).setColor(color);
18852            computeOpaqueFlags();
18853            mBackgroundResource = 0;
18854        } else {
18855            setBackground(new ColorDrawable(color));
18856        }
18857    }
18858
18859    /**
18860     * Set the background to a given resource. The resource should refer to
18861     * a Drawable object or 0 to remove the background.
18862     * @param resid The identifier of the resource.
18863     *
18864     * @attr ref android.R.styleable#View_background
18865     */
18866    @RemotableViewMethod
18867    public void setBackgroundResource(@DrawableRes int resid) {
18868        if (resid != 0 && resid == mBackgroundResource) {
18869            return;
18870        }
18871
18872        Drawable d = null;
18873        if (resid != 0) {
18874            d = mContext.getDrawable(resid);
18875        }
18876        setBackground(d);
18877
18878        mBackgroundResource = resid;
18879    }
18880
18881    /**
18882     * Set the background to a given Drawable, or remove the background. If the
18883     * background has padding, this View's padding is set to the background's
18884     * padding. However, when a background is removed, this View's padding isn't
18885     * touched. If setting the padding is desired, please use
18886     * {@link #setPadding(int, int, int, int)}.
18887     *
18888     * @param background The Drawable to use as the background, or null to remove the
18889     *        background
18890     */
18891    public void setBackground(Drawable background) {
18892        //noinspection deprecation
18893        setBackgroundDrawable(background);
18894    }
18895
18896    /**
18897     * @deprecated use {@link #setBackground(Drawable)} instead
18898     */
18899    @Deprecated
18900    public void setBackgroundDrawable(Drawable background) {
18901        computeOpaqueFlags();
18902
18903        if (background == mBackground) {
18904            return;
18905        }
18906
18907        boolean requestLayout = false;
18908
18909        mBackgroundResource = 0;
18910
18911        /*
18912         * Regardless of whether we're setting a new background or not, we want
18913         * to clear the previous drawable. setVisible first while we still have the callback set.
18914         */
18915        if (mBackground != null) {
18916            if (isAttachedToWindow()) {
18917                mBackground.setVisible(false, false);
18918            }
18919            mBackground.setCallback(null);
18920            unscheduleDrawable(mBackground);
18921        }
18922
18923        if (background != null) {
18924            Rect padding = sThreadLocal.get();
18925            if (padding == null) {
18926                padding = new Rect();
18927                sThreadLocal.set(padding);
18928            }
18929            resetResolvedDrawablesInternal();
18930            background.setLayoutDirection(getLayoutDirection());
18931            if (background.getPadding(padding)) {
18932                resetResolvedPaddingInternal();
18933                switch (background.getLayoutDirection()) {
18934                    case LAYOUT_DIRECTION_RTL:
18935                        mUserPaddingLeftInitial = padding.right;
18936                        mUserPaddingRightInitial = padding.left;
18937                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
18938                        break;
18939                    case LAYOUT_DIRECTION_LTR:
18940                    default:
18941                        mUserPaddingLeftInitial = padding.left;
18942                        mUserPaddingRightInitial = padding.right;
18943                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
18944                }
18945                mLeftPaddingDefined = false;
18946                mRightPaddingDefined = false;
18947            }
18948
18949            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
18950            // if it has a different minimum size, we should layout again
18951            if (mBackground == null
18952                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
18953                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
18954                requestLayout = true;
18955            }
18956
18957            // Set mBackground before we set this as the callback and start making other
18958            // background drawable state change calls. In particular, the setVisible call below
18959            // can result in drawables attempting to start animations or otherwise invalidate,
18960            // which requires the view set as the callback (us) to recognize the drawable as
18961            // belonging to it as per verifyDrawable.
18962            mBackground = background;
18963            if (background.isStateful()) {
18964                background.setState(getDrawableState());
18965            }
18966            if (isAttachedToWindow()) {
18967                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
18968            }
18969
18970            applyBackgroundTint();
18971
18972            // Set callback last, since the view may still be initializing.
18973            background.setCallback(this);
18974
18975            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
18976                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
18977                requestLayout = true;
18978            }
18979        } else {
18980            /* Remove the background */
18981            mBackground = null;
18982            if ((mViewFlags & WILL_NOT_DRAW) != 0
18983                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
18984                mPrivateFlags |= PFLAG_SKIP_DRAW;
18985            }
18986
18987            /*
18988             * When the background is set, we try to apply its padding to this
18989             * View. When the background is removed, we don't touch this View's
18990             * padding. This is noted in the Javadocs. Hence, we don't need to
18991             * requestLayout(), the invalidate() below is sufficient.
18992             */
18993
18994            // The old background's minimum size could have affected this
18995            // View's layout, so let's requestLayout
18996            requestLayout = true;
18997        }
18998
18999        computeOpaqueFlags();
19000
19001        if (requestLayout) {
19002            requestLayout();
19003        }
19004
19005        mBackgroundSizeChanged = true;
19006        invalidate(true);
19007        invalidateOutline();
19008    }
19009
19010    /**
19011     * Gets the background drawable
19012     *
19013     * @return The drawable used as the background for this view, if any.
19014     *
19015     * @see #setBackground(Drawable)
19016     *
19017     * @attr ref android.R.styleable#View_background
19018     */
19019    public Drawable getBackground() {
19020        return mBackground;
19021    }
19022
19023    /**
19024     * Applies a tint to the background drawable. Does not modify the current tint
19025     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
19026     * <p>
19027     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
19028     * mutate the drawable and apply the specified tint and tint mode using
19029     * {@link Drawable#setTintList(ColorStateList)}.
19030     *
19031     * @param tint the tint to apply, may be {@code null} to clear tint
19032     *
19033     * @attr ref android.R.styleable#View_backgroundTint
19034     * @see #getBackgroundTintList()
19035     * @see Drawable#setTintList(ColorStateList)
19036     */
19037    public void setBackgroundTintList(@Nullable ColorStateList tint) {
19038        if (mBackgroundTint == null) {
19039            mBackgroundTint = new TintInfo();
19040        }
19041        mBackgroundTint.mTintList = tint;
19042        mBackgroundTint.mHasTintList = true;
19043
19044        applyBackgroundTint();
19045    }
19046
19047    /**
19048     * Return the tint applied to the background drawable, if specified.
19049     *
19050     * @return the tint applied to the background drawable
19051     * @attr ref android.R.styleable#View_backgroundTint
19052     * @see #setBackgroundTintList(ColorStateList)
19053     */
19054    @Nullable
19055    public ColorStateList getBackgroundTintList() {
19056        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
19057    }
19058
19059    /**
19060     * Specifies the blending mode used to apply the tint specified by
19061     * {@link #setBackgroundTintList(ColorStateList)}} to the background
19062     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
19063     *
19064     * @param tintMode the blending mode used to apply the tint, may be
19065     *                 {@code null} to clear tint
19066     * @attr ref android.R.styleable#View_backgroundTintMode
19067     * @see #getBackgroundTintMode()
19068     * @see Drawable#setTintMode(PorterDuff.Mode)
19069     */
19070    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
19071        if (mBackgroundTint == null) {
19072            mBackgroundTint = new TintInfo();
19073        }
19074        mBackgroundTint.mTintMode = tintMode;
19075        mBackgroundTint.mHasTintMode = true;
19076
19077        applyBackgroundTint();
19078    }
19079
19080    /**
19081     * Return the blending mode used to apply the tint to the background
19082     * drawable, if specified.
19083     *
19084     * @return the blending mode used to apply the tint to the background
19085     *         drawable
19086     * @attr ref android.R.styleable#View_backgroundTintMode
19087     * @see #setBackgroundTintMode(PorterDuff.Mode)
19088     */
19089    @Nullable
19090    public PorterDuff.Mode getBackgroundTintMode() {
19091        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
19092    }
19093
19094    private void applyBackgroundTint() {
19095        if (mBackground != null && mBackgroundTint != null) {
19096            final TintInfo tintInfo = mBackgroundTint;
19097            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
19098                mBackground = mBackground.mutate();
19099
19100                if (tintInfo.mHasTintList) {
19101                    mBackground.setTintList(tintInfo.mTintList);
19102                }
19103
19104                if (tintInfo.mHasTintMode) {
19105                    mBackground.setTintMode(tintInfo.mTintMode);
19106                }
19107
19108                // The drawable (or one of its children) may not have been
19109                // stateful before applying the tint, so let's try again.
19110                if (mBackground.isStateful()) {
19111                    mBackground.setState(getDrawableState());
19112                }
19113            }
19114        }
19115    }
19116
19117    /**
19118     * Returns the drawable used as the foreground of this View. The
19119     * foreground drawable, if non-null, is always drawn on top of the view's content.
19120     *
19121     * @return a Drawable or null if no foreground was set
19122     *
19123     * @see #onDrawForeground(Canvas)
19124     */
19125    public Drawable getForeground() {
19126        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19127    }
19128
19129    /**
19130     * Supply a Drawable that is to be rendered on top of all of the content in the view.
19131     *
19132     * @param foreground the Drawable to be drawn on top of the children
19133     *
19134     * @attr ref android.R.styleable#View_foreground
19135     */
19136    public void setForeground(Drawable foreground) {
19137        if (mForegroundInfo == null) {
19138            if (foreground == null) {
19139                // Nothing to do.
19140                return;
19141            }
19142            mForegroundInfo = new ForegroundInfo();
19143        }
19144
19145        if (foreground == mForegroundInfo.mDrawable) {
19146            // Nothing to do
19147            return;
19148        }
19149
19150        if (mForegroundInfo.mDrawable != null) {
19151            if (isAttachedToWindow()) {
19152                mForegroundInfo.mDrawable.setVisible(false, false);
19153            }
19154            mForegroundInfo.mDrawable.setCallback(null);
19155            unscheduleDrawable(mForegroundInfo.mDrawable);
19156        }
19157
19158        mForegroundInfo.mDrawable = foreground;
19159        mForegroundInfo.mBoundsChanged = true;
19160        if (foreground != null) {
19161            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19162                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19163            }
19164            foreground.setLayoutDirection(getLayoutDirection());
19165            if (foreground.isStateful()) {
19166                foreground.setState(getDrawableState());
19167            }
19168            applyForegroundTint();
19169            if (isAttachedToWindow()) {
19170                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19171            }
19172            // Set callback last, since the view may still be initializing.
19173            foreground.setCallback(this);
19174        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
19175            mPrivateFlags |= PFLAG_SKIP_DRAW;
19176        }
19177        requestLayout();
19178        invalidate();
19179    }
19180
19181    /**
19182     * Magic bit used to support features of framework-internal window decor implementation details.
19183     * This used to live exclusively in FrameLayout.
19184     *
19185     * @return true if the foreground should draw inside the padding region or false
19186     *         if it should draw inset by the view's padding
19187     * @hide internal use only; only used by FrameLayout and internal screen layouts.
19188     */
19189    public boolean isForegroundInsidePadding() {
19190        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
19191    }
19192
19193    /**
19194     * Describes how the foreground is positioned.
19195     *
19196     * @return foreground gravity.
19197     *
19198     * @see #setForegroundGravity(int)
19199     *
19200     * @attr ref android.R.styleable#View_foregroundGravity
19201     */
19202    public int getForegroundGravity() {
19203        return mForegroundInfo != null ? mForegroundInfo.mGravity
19204                : Gravity.START | Gravity.TOP;
19205    }
19206
19207    /**
19208     * Describes how the foreground is positioned. Defaults to START and TOP.
19209     *
19210     * @param gravity see {@link android.view.Gravity}
19211     *
19212     * @see #getForegroundGravity()
19213     *
19214     * @attr ref android.R.styleable#View_foregroundGravity
19215     */
19216    public void setForegroundGravity(int gravity) {
19217        if (mForegroundInfo == null) {
19218            mForegroundInfo = new ForegroundInfo();
19219        }
19220
19221        if (mForegroundInfo.mGravity != gravity) {
19222            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
19223                gravity |= Gravity.START;
19224            }
19225
19226            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
19227                gravity |= Gravity.TOP;
19228            }
19229
19230            mForegroundInfo.mGravity = gravity;
19231            requestLayout();
19232        }
19233    }
19234
19235    /**
19236     * Applies a tint to the foreground drawable. Does not modify the current tint
19237     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
19238     * <p>
19239     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
19240     * mutate the drawable and apply the specified tint and tint mode using
19241     * {@link Drawable#setTintList(ColorStateList)}.
19242     *
19243     * @param tint the tint to apply, may be {@code null} to clear tint
19244     *
19245     * @attr ref android.R.styleable#View_foregroundTint
19246     * @see #getForegroundTintList()
19247     * @see Drawable#setTintList(ColorStateList)
19248     */
19249    public void setForegroundTintList(@Nullable ColorStateList tint) {
19250        if (mForegroundInfo == null) {
19251            mForegroundInfo = new ForegroundInfo();
19252        }
19253        if (mForegroundInfo.mTintInfo == null) {
19254            mForegroundInfo.mTintInfo = new TintInfo();
19255        }
19256        mForegroundInfo.mTintInfo.mTintList = tint;
19257        mForegroundInfo.mTintInfo.mHasTintList = true;
19258
19259        applyForegroundTint();
19260    }
19261
19262    /**
19263     * Return the tint applied to the foreground drawable, if specified.
19264     *
19265     * @return the tint applied to the foreground drawable
19266     * @attr ref android.R.styleable#View_foregroundTint
19267     * @see #setForegroundTintList(ColorStateList)
19268     */
19269    @Nullable
19270    public ColorStateList getForegroundTintList() {
19271        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
19272                ? mForegroundInfo.mTintInfo.mTintList : null;
19273    }
19274
19275    /**
19276     * Specifies the blending mode used to apply the tint specified by
19277     * {@link #setForegroundTintList(ColorStateList)}} to the background
19278     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
19279     *
19280     * @param tintMode the blending mode used to apply the tint, may be
19281     *                 {@code null} to clear tint
19282     * @attr ref android.R.styleable#View_foregroundTintMode
19283     * @see #getForegroundTintMode()
19284     * @see Drawable#setTintMode(PorterDuff.Mode)
19285     */
19286    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
19287        if (mForegroundInfo == null) {
19288            mForegroundInfo = new ForegroundInfo();
19289        }
19290        if (mForegroundInfo.mTintInfo == null) {
19291            mForegroundInfo.mTintInfo = new TintInfo();
19292        }
19293        mForegroundInfo.mTintInfo.mTintMode = tintMode;
19294        mForegroundInfo.mTintInfo.mHasTintMode = true;
19295
19296        applyForegroundTint();
19297    }
19298
19299    /**
19300     * Return the blending mode used to apply the tint to the foreground
19301     * drawable, if specified.
19302     *
19303     * @return the blending mode used to apply the tint to the foreground
19304     *         drawable
19305     * @attr ref android.R.styleable#View_foregroundTintMode
19306     * @see #setForegroundTintMode(PorterDuff.Mode)
19307     */
19308    @Nullable
19309    public PorterDuff.Mode getForegroundTintMode() {
19310        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
19311                ? mForegroundInfo.mTintInfo.mTintMode : null;
19312    }
19313
19314    private void applyForegroundTint() {
19315        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19316                && mForegroundInfo.mTintInfo != null) {
19317            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
19318            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
19319                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
19320
19321                if (tintInfo.mHasTintList) {
19322                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
19323                }
19324
19325                if (tintInfo.mHasTintMode) {
19326                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
19327                }
19328
19329                // The drawable (or one of its children) may not have been
19330                // stateful before applying the tint, so let's try again.
19331                if (mForegroundInfo.mDrawable.isStateful()) {
19332                    mForegroundInfo.mDrawable.setState(getDrawableState());
19333                }
19334            }
19335        }
19336    }
19337
19338    /**
19339     * Draw any foreground content for this view.
19340     *
19341     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
19342     * drawable or other view-specific decorations. The foreground is drawn on top of the
19343     * primary view content.</p>
19344     *
19345     * @param canvas canvas to draw into
19346     */
19347    public void onDrawForeground(Canvas canvas) {
19348        onDrawScrollIndicators(canvas);
19349        onDrawScrollBars(canvas);
19350
19351        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19352        if (foreground != null) {
19353            if (mForegroundInfo.mBoundsChanged) {
19354                mForegroundInfo.mBoundsChanged = false;
19355                final Rect selfBounds = mForegroundInfo.mSelfBounds;
19356                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
19357
19358                if (mForegroundInfo.mInsidePadding) {
19359                    selfBounds.set(0, 0, getWidth(), getHeight());
19360                } else {
19361                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
19362                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
19363                }
19364
19365                final int ld = getLayoutDirection();
19366                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
19367                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
19368                foreground.setBounds(overlayBounds);
19369            }
19370
19371            foreground.draw(canvas);
19372        }
19373    }
19374
19375    /**
19376     * Sets the padding. The view may add on the space required to display
19377     * the scrollbars, depending on the style and visibility of the scrollbars.
19378     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
19379     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
19380     * from the values set in this call.
19381     *
19382     * @attr ref android.R.styleable#View_padding
19383     * @attr ref android.R.styleable#View_paddingBottom
19384     * @attr ref android.R.styleable#View_paddingLeft
19385     * @attr ref android.R.styleable#View_paddingRight
19386     * @attr ref android.R.styleable#View_paddingTop
19387     * @param left the left padding in pixels
19388     * @param top the top padding in pixels
19389     * @param right the right padding in pixels
19390     * @param bottom the bottom padding in pixels
19391     */
19392    public void setPadding(int left, int top, int right, int bottom) {
19393        resetResolvedPaddingInternal();
19394
19395        mUserPaddingStart = UNDEFINED_PADDING;
19396        mUserPaddingEnd = UNDEFINED_PADDING;
19397
19398        mUserPaddingLeftInitial = left;
19399        mUserPaddingRightInitial = right;
19400
19401        mLeftPaddingDefined = true;
19402        mRightPaddingDefined = true;
19403
19404        internalSetPadding(left, top, right, bottom);
19405    }
19406
19407    /**
19408     * @hide
19409     */
19410    protected void internalSetPadding(int left, int top, int right, int bottom) {
19411        mUserPaddingLeft = left;
19412        mUserPaddingRight = right;
19413        mUserPaddingBottom = bottom;
19414
19415        final int viewFlags = mViewFlags;
19416        boolean changed = false;
19417
19418        // Common case is there are no scroll bars.
19419        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
19420            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
19421                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
19422                        ? 0 : getVerticalScrollbarWidth();
19423                switch (mVerticalScrollbarPosition) {
19424                    case SCROLLBAR_POSITION_DEFAULT:
19425                        if (isLayoutRtl()) {
19426                            left += offset;
19427                        } else {
19428                            right += offset;
19429                        }
19430                        break;
19431                    case SCROLLBAR_POSITION_RIGHT:
19432                        right += offset;
19433                        break;
19434                    case SCROLLBAR_POSITION_LEFT:
19435                        left += offset;
19436                        break;
19437                }
19438            }
19439            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
19440                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
19441                        ? 0 : getHorizontalScrollbarHeight();
19442            }
19443        }
19444
19445        if (mPaddingLeft != left) {
19446            changed = true;
19447            mPaddingLeft = left;
19448        }
19449        if (mPaddingTop != top) {
19450            changed = true;
19451            mPaddingTop = top;
19452        }
19453        if (mPaddingRight != right) {
19454            changed = true;
19455            mPaddingRight = right;
19456        }
19457        if (mPaddingBottom != bottom) {
19458            changed = true;
19459            mPaddingBottom = bottom;
19460        }
19461
19462        if (changed) {
19463            requestLayout();
19464            invalidateOutline();
19465        }
19466    }
19467
19468    /**
19469     * Sets the relative padding. The view may add on the space required to display
19470     * the scrollbars, depending on the style and visibility of the scrollbars.
19471     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
19472     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
19473     * from the values set in this call.
19474     *
19475     * @attr ref android.R.styleable#View_padding
19476     * @attr ref android.R.styleable#View_paddingBottom
19477     * @attr ref android.R.styleable#View_paddingStart
19478     * @attr ref android.R.styleable#View_paddingEnd
19479     * @attr ref android.R.styleable#View_paddingTop
19480     * @param start the start padding in pixels
19481     * @param top the top padding in pixels
19482     * @param end the end padding in pixels
19483     * @param bottom the bottom padding in pixels
19484     */
19485    public void setPaddingRelative(int start, int top, int end, int bottom) {
19486        resetResolvedPaddingInternal();
19487
19488        mUserPaddingStart = start;
19489        mUserPaddingEnd = end;
19490        mLeftPaddingDefined = true;
19491        mRightPaddingDefined = true;
19492
19493        switch(getLayoutDirection()) {
19494            case LAYOUT_DIRECTION_RTL:
19495                mUserPaddingLeftInitial = end;
19496                mUserPaddingRightInitial = start;
19497                internalSetPadding(end, top, start, bottom);
19498                break;
19499            case LAYOUT_DIRECTION_LTR:
19500            default:
19501                mUserPaddingLeftInitial = start;
19502                mUserPaddingRightInitial = end;
19503                internalSetPadding(start, top, end, bottom);
19504        }
19505    }
19506
19507    /**
19508     * Returns the top padding of this view.
19509     *
19510     * @return the top padding in pixels
19511     */
19512    public int getPaddingTop() {
19513        return mPaddingTop;
19514    }
19515
19516    /**
19517     * Returns the bottom padding of this view. If there are inset and enabled
19518     * scrollbars, this value may include the space required to display the
19519     * scrollbars as well.
19520     *
19521     * @return the bottom padding in pixels
19522     */
19523    public int getPaddingBottom() {
19524        return mPaddingBottom;
19525    }
19526
19527    /**
19528     * Returns the left padding of this view. If there are inset and enabled
19529     * scrollbars, this value may include the space required to display the
19530     * scrollbars as well.
19531     *
19532     * @return the left padding in pixels
19533     */
19534    public int getPaddingLeft() {
19535        if (!isPaddingResolved()) {
19536            resolvePadding();
19537        }
19538        return mPaddingLeft;
19539    }
19540
19541    /**
19542     * Returns the start padding of this view depending on its resolved layout direction.
19543     * If there are inset and enabled scrollbars, this value may include the space
19544     * required to display the scrollbars as well.
19545     *
19546     * @return the start padding in pixels
19547     */
19548    public int getPaddingStart() {
19549        if (!isPaddingResolved()) {
19550            resolvePadding();
19551        }
19552        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
19553                mPaddingRight : mPaddingLeft;
19554    }
19555
19556    /**
19557     * Returns the right padding of this view. If there are inset and enabled
19558     * scrollbars, this value may include the space required to display the
19559     * scrollbars as well.
19560     *
19561     * @return the right padding in pixels
19562     */
19563    public int getPaddingRight() {
19564        if (!isPaddingResolved()) {
19565            resolvePadding();
19566        }
19567        return mPaddingRight;
19568    }
19569
19570    /**
19571     * Returns the end padding of this view depending on its resolved layout direction.
19572     * If there are inset and enabled scrollbars, this value may include the space
19573     * required to display the scrollbars as well.
19574     *
19575     * @return the end padding in pixels
19576     */
19577    public int getPaddingEnd() {
19578        if (!isPaddingResolved()) {
19579            resolvePadding();
19580        }
19581        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
19582                mPaddingLeft : mPaddingRight;
19583    }
19584
19585    /**
19586     * Return if the padding has been set through relative values
19587     * {@link #setPaddingRelative(int, int, int, int)} or through
19588     * @attr ref android.R.styleable#View_paddingStart or
19589     * @attr ref android.R.styleable#View_paddingEnd
19590     *
19591     * @return true if the padding is relative or false if it is not.
19592     */
19593    public boolean isPaddingRelative() {
19594        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
19595    }
19596
19597    Insets computeOpticalInsets() {
19598        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
19599    }
19600
19601    /**
19602     * @hide
19603     */
19604    public void resetPaddingToInitialValues() {
19605        if (isRtlCompatibilityMode()) {
19606            mPaddingLeft = mUserPaddingLeftInitial;
19607            mPaddingRight = mUserPaddingRightInitial;
19608            return;
19609        }
19610        if (isLayoutRtl()) {
19611            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
19612            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
19613        } else {
19614            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
19615            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
19616        }
19617    }
19618
19619    /**
19620     * @hide
19621     */
19622    public Insets getOpticalInsets() {
19623        if (mLayoutInsets == null) {
19624            mLayoutInsets = computeOpticalInsets();
19625        }
19626        return mLayoutInsets;
19627    }
19628
19629    /**
19630     * Set this view's optical insets.
19631     *
19632     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
19633     * property. Views that compute their own optical insets should call it as part of measurement.
19634     * This method does not request layout. If you are setting optical insets outside of
19635     * measure/layout itself you will want to call requestLayout() yourself.
19636     * </p>
19637     * @hide
19638     */
19639    public void setOpticalInsets(Insets insets) {
19640        mLayoutInsets = insets;
19641    }
19642
19643    /**
19644     * Changes the selection state of this view. A view can be selected or not.
19645     * Note that selection is not the same as focus. Views are typically
19646     * selected in the context of an AdapterView like ListView or GridView;
19647     * the selected view is the view that is highlighted.
19648     *
19649     * @param selected true if the view must be selected, false otherwise
19650     */
19651    public void setSelected(boolean selected) {
19652        //noinspection DoubleNegation
19653        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
19654            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
19655            if (!selected) resetPressedState();
19656            invalidate(true);
19657            refreshDrawableState();
19658            dispatchSetSelected(selected);
19659            if (selected) {
19660                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
19661            } else {
19662                notifyViewAccessibilityStateChangedIfNeeded(
19663                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
19664            }
19665        }
19666    }
19667
19668    /**
19669     * Dispatch setSelected to all of this View's children.
19670     *
19671     * @see #setSelected(boolean)
19672     *
19673     * @param selected The new selected state
19674     */
19675    protected void dispatchSetSelected(boolean selected) {
19676    }
19677
19678    /**
19679     * Indicates the selection state of this view.
19680     *
19681     * @return true if the view is selected, false otherwise
19682     */
19683    @ViewDebug.ExportedProperty
19684    public boolean isSelected() {
19685        return (mPrivateFlags & PFLAG_SELECTED) != 0;
19686    }
19687
19688    /**
19689     * Changes the activated state of this view. A view can be activated or not.
19690     * Note that activation is not the same as selection.  Selection is
19691     * a transient property, representing the view (hierarchy) the user is
19692     * currently interacting with.  Activation is a longer-term state that the
19693     * user can move views in and out of.  For example, in a list view with
19694     * single or multiple selection enabled, the views in the current selection
19695     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
19696     * here.)  The activated state is propagated down to children of the view it
19697     * is set on.
19698     *
19699     * @param activated true if the view must be activated, false otherwise
19700     */
19701    public void setActivated(boolean activated) {
19702        //noinspection DoubleNegation
19703        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
19704            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
19705            invalidate(true);
19706            refreshDrawableState();
19707            dispatchSetActivated(activated);
19708        }
19709    }
19710
19711    /**
19712     * Dispatch setActivated to all of this View's children.
19713     *
19714     * @see #setActivated(boolean)
19715     *
19716     * @param activated The new activated state
19717     */
19718    protected void dispatchSetActivated(boolean activated) {
19719    }
19720
19721    /**
19722     * Indicates the activation state of this view.
19723     *
19724     * @return true if the view is activated, false otherwise
19725     */
19726    @ViewDebug.ExportedProperty
19727    public boolean isActivated() {
19728        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
19729    }
19730
19731    /**
19732     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
19733     * observer can be used to get notifications when global events, like
19734     * layout, happen.
19735     *
19736     * The returned ViewTreeObserver observer is not guaranteed to remain
19737     * valid for the lifetime of this View. If the caller of this method keeps
19738     * a long-lived reference to ViewTreeObserver, it should always check for
19739     * the return value of {@link ViewTreeObserver#isAlive()}.
19740     *
19741     * @return The ViewTreeObserver for this view's hierarchy.
19742     */
19743    public ViewTreeObserver getViewTreeObserver() {
19744        if (mAttachInfo != null) {
19745            return mAttachInfo.mTreeObserver;
19746        }
19747        if (mFloatingTreeObserver == null) {
19748            mFloatingTreeObserver = new ViewTreeObserver(mContext);
19749        }
19750        return mFloatingTreeObserver;
19751    }
19752
19753    /**
19754     * <p>Finds the topmost view in the current view hierarchy.</p>
19755     *
19756     * @return the topmost view containing this view
19757     */
19758    public View getRootView() {
19759        if (mAttachInfo != null) {
19760            final View v = mAttachInfo.mRootView;
19761            if (v != null) {
19762                return v;
19763            }
19764        }
19765
19766        View parent = this;
19767
19768        while (parent.mParent != null && parent.mParent instanceof View) {
19769            parent = (View) parent.mParent;
19770        }
19771
19772        return parent;
19773    }
19774
19775    /**
19776     * Transforms a motion event from view-local coordinates to on-screen
19777     * coordinates.
19778     *
19779     * @param ev the view-local motion event
19780     * @return false if the transformation could not be applied
19781     * @hide
19782     */
19783    public boolean toGlobalMotionEvent(MotionEvent ev) {
19784        final AttachInfo info = mAttachInfo;
19785        if (info == null) {
19786            return false;
19787        }
19788
19789        final Matrix m = info.mTmpMatrix;
19790        m.set(Matrix.IDENTITY_MATRIX);
19791        transformMatrixToGlobal(m);
19792        ev.transform(m);
19793        return true;
19794    }
19795
19796    /**
19797     * Transforms a motion event from on-screen coordinates to view-local
19798     * coordinates.
19799     *
19800     * @param ev the on-screen motion event
19801     * @return false if the transformation could not be applied
19802     * @hide
19803     */
19804    public boolean toLocalMotionEvent(MotionEvent ev) {
19805        final AttachInfo info = mAttachInfo;
19806        if (info == null) {
19807            return false;
19808        }
19809
19810        final Matrix m = info.mTmpMatrix;
19811        m.set(Matrix.IDENTITY_MATRIX);
19812        transformMatrixToLocal(m);
19813        ev.transform(m);
19814        return true;
19815    }
19816
19817    /**
19818     * Modifies the input matrix such that it maps view-local coordinates to
19819     * on-screen coordinates.
19820     *
19821     * @param m input matrix to modify
19822     * @hide
19823     */
19824    public void transformMatrixToGlobal(Matrix m) {
19825        final ViewParent parent = mParent;
19826        if (parent instanceof View) {
19827            final View vp = (View) parent;
19828            vp.transformMatrixToGlobal(m);
19829            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
19830        } else if (parent instanceof ViewRootImpl) {
19831            final ViewRootImpl vr = (ViewRootImpl) parent;
19832            vr.transformMatrixToGlobal(m);
19833            m.preTranslate(0, -vr.mCurScrollY);
19834        }
19835
19836        m.preTranslate(mLeft, mTop);
19837
19838        if (!hasIdentityMatrix()) {
19839            m.preConcat(getMatrix());
19840        }
19841    }
19842
19843    /**
19844     * Modifies the input matrix such that it maps on-screen coordinates to
19845     * view-local coordinates.
19846     *
19847     * @param m input matrix to modify
19848     * @hide
19849     */
19850    public void transformMatrixToLocal(Matrix m) {
19851        final ViewParent parent = mParent;
19852        if (parent instanceof View) {
19853            final View vp = (View) parent;
19854            vp.transformMatrixToLocal(m);
19855            m.postTranslate(vp.mScrollX, vp.mScrollY);
19856        } else if (parent instanceof ViewRootImpl) {
19857            final ViewRootImpl vr = (ViewRootImpl) parent;
19858            vr.transformMatrixToLocal(m);
19859            m.postTranslate(0, vr.mCurScrollY);
19860        }
19861
19862        m.postTranslate(-mLeft, -mTop);
19863
19864        if (!hasIdentityMatrix()) {
19865            m.postConcat(getInverseMatrix());
19866        }
19867    }
19868
19869    /**
19870     * @hide
19871     */
19872    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
19873            @ViewDebug.IntToString(from = 0, to = "x"),
19874            @ViewDebug.IntToString(from = 1, to = "y")
19875    })
19876    public int[] getLocationOnScreen() {
19877        int[] location = new int[2];
19878        getLocationOnScreen(location);
19879        return location;
19880    }
19881
19882    /**
19883     * <p>Computes the coordinates of this view on the screen. The argument
19884     * must be an array of two integers. After the method returns, the array
19885     * contains the x and y location in that order.</p>
19886     *
19887     * @param outLocation an array of two integers in which to hold the coordinates
19888     */
19889    public void getLocationOnScreen(@Size(2) int[] outLocation) {
19890        getLocationInWindow(outLocation);
19891
19892        final AttachInfo info = mAttachInfo;
19893        if (info != null) {
19894            outLocation[0] += info.mWindowLeft;
19895            outLocation[1] += info.mWindowTop;
19896        }
19897    }
19898
19899    /**
19900     * <p>Computes the coordinates of this view in its window. The argument
19901     * must be an array of two integers. After the method returns, the array
19902     * contains the x and y location in that order.</p>
19903     *
19904     * @param outLocation an array of two integers in which to hold the coordinates
19905     */
19906    public void getLocationInWindow(@Size(2) int[] outLocation) {
19907        if (outLocation == null || outLocation.length < 2) {
19908            throw new IllegalArgumentException("outLocation must be an array of two integers");
19909        }
19910
19911        outLocation[0] = 0;
19912        outLocation[1] = 0;
19913
19914        transformFromViewToWindowSpace(outLocation);
19915    }
19916
19917    /** @hide */
19918    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
19919        if (inOutLocation == null || inOutLocation.length < 2) {
19920            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
19921        }
19922
19923        if (mAttachInfo == null) {
19924            // When the view is not attached to a window, this method does not make sense
19925            inOutLocation[0] = inOutLocation[1] = 0;
19926            return;
19927        }
19928
19929        float position[] = mAttachInfo.mTmpTransformLocation;
19930        position[0] = inOutLocation[0];
19931        position[1] = inOutLocation[1];
19932
19933        if (!hasIdentityMatrix()) {
19934            getMatrix().mapPoints(position);
19935        }
19936
19937        position[0] += mLeft;
19938        position[1] += mTop;
19939
19940        ViewParent viewParent = mParent;
19941        while (viewParent instanceof View) {
19942            final View view = (View) viewParent;
19943
19944            position[0] -= view.mScrollX;
19945            position[1] -= view.mScrollY;
19946
19947            if (!view.hasIdentityMatrix()) {
19948                view.getMatrix().mapPoints(position);
19949            }
19950
19951            position[0] += view.mLeft;
19952            position[1] += view.mTop;
19953
19954            viewParent = view.mParent;
19955         }
19956
19957        if (viewParent instanceof ViewRootImpl) {
19958            // *cough*
19959            final ViewRootImpl vr = (ViewRootImpl) viewParent;
19960            position[1] -= vr.mCurScrollY;
19961        }
19962
19963        inOutLocation[0] = Math.round(position[0]);
19964        inOutLocation[1] = Math.round(position[1]);
19965    }
19966
19967    /**
19968     * {@hide}
19969     * @param id the id of the view to be found
19970     * @return the view of the specified id, null if cannot be found
19971     */
19972    protected View findViewTraversal(@IdRes int id) {
19973        if (id == mID) {
19974            return this;
19975        }
19976        return null;
19977    }
19978
19979    /**
19980     * {@hide}
19981     * @param tag the tag of the view to be found
19982     * @return the view of specified tag, null if cannot be found
19983     */
19984    protected View findViewWithTagTraversal(Object tag) {
19985        if (tag != null && tag.equals(mTag)) {
19986            return this;
19987        }
19988        return null;
19989    }
19990
19991    /**
19992     * {@hide}
19993     * @param predicate The predicate to evaluate.
19994     * @param childToSkip If not null, ignores this child during the recursive traversal.
19995     * @return The first view that matches the predicate or null.
19996     */
19997    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
19998        if (predicate.apply(this)) {
19999            return this;
20000        }
20001        return null;
20002    }
20003
20004    /**
20005     * Look for a child view with the given id.  If this view has the given
20006     * id, return this view.
20007     *
20008     * @param id The id to search for.
20009     * @return The view that has the given id in the hierarchy or null
20010     */
20011    @Nullable
20012    public final View findViewById(@IdRes int id) {
20013        if (id < 0) {
20014            return null;
20015        }
20016        return findViewTraversal(id);
20017    }
20018
20019    /**
20020     * Finds a view by its unuque and stable accessibility id.
20021     *
20022     * @param accessibilityId The searched accessibility id.
20023     * @return The found view.
20024     */
20025    final View findViewByAccessibilityId(int accessibilityId) {
20026        if (accessibilityId < 0) {
20027            return null;
20028        }
20029        View view = findViewByAccessibilityIdTraversal(accessibilityId);
20030        if (view != null) {
20031            return view.includeForAccessibility() ? view : null;
20032        }
20033        return null;
20034    }
20035
20036    /**
20037     * Performs the traversal to find a view by its unuque and stable accessibility id.
20038     *
20039     * <strong>Note:</strong>This method does not stop at the root namespace
20040     * boundary since the user can touch the screen at an arbitrary location
20041     * potentially crossing the root namespace bounday which will send an
20042     * accessibility event to accessibility services and they should be able
20043     * to obtain the event source. Also accessibility ids are guaranteed to be
20044     * unique in the window.
20045     *
20046     * @param accessibilityId The accessibility id.
20047     * @return The found view.
20048     *
20049     * @hide
20050     */
20051    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
20052        if (getAccessibilityViewId() == accessibilityId) {
20053            return this;
20054        }
20055        return null;
20056    }
20057
20058    /**
20059     * Look for a child view with the given tag.  If this view has the given
20060     * tag, return this view.
20061     *
20062     * @param tag The tag to search for, using "tag.equals(getTag())".
20063     * @return The View that has the given tag in the hierarchy or null
20064     */
20065    public final View findViewWithTag(Object tag) {
20066        if (tag == null) {
20067            return null;
20068        }
20069        return findViewWithTagTraversal(tag);
20070    }
20071
20072    /**
20073     * {@hide}
20074     * Look for a child view that matches the specified predicate.
20075     * If this view matches the predicate, return this view.
20076     *
20077     * @param predicate The predicate to evaluate.
20078     * @return The first view that matches the predicate or null.
20079     */
20080    public final View findViewByPredicate(Predicate<View> predicate) {
20081        return findViewByPredicateTraversal(predicate, null);
20082    }
20083
20084    /**
20085     * {@hide}
20086     * Look for a child view that matches the specified predicate,
20087     * starting with the specified view and its descendents and then
20088     * recusively searching the ancestors and siblings of that view
20089     * until this view is reached.
20090     *
20091     * This method is useful in cases where the predicate does not match
20092     * a single unique view (perhaps multiple views use the same id)
20093     * and we are trying to find the view that is "closest" in scope to the
20094     * starting view.
20095     *
20096     * @param start The view to start from.
20097     * @param predicate The predicate to evaluate.
20098     * @return The first view that matches the predicate or null.
20099     */
20100    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
20101        View childToSkip = null;
20102        for (;;) {
20103            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
20104            if (view != null || start == this) {
20105                return view;
20106            }
20107
20108            ViewParent parent = start.getParent();
20109            if (parent == null || !(parent instanceof View)) {
20110                return null;
20111            }
20112
20113            childToSkip = start;
20114            start = (View) parent;
20115        }
20116    }
20117
20118    /**
20119     * Sets the identifier for this view. The identifier does not have to be
20120     * unique in this view's hierarchy. The identifier should be a positive
20121     * number.
20122     *
20123     * @see #NO_ID
20124     * @see #getId()
20125     * @see #findViewById(int)
20126     *
20127     * @param id a number used to identify the view
20128     *
20129     * @attr ref android.R.styleable#View_id
20130     */
20131    public void setId(@IdRes int id) {
20132        mID = id;
20133        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
20134            mID = generateViewId();
20135        }
20136    }
20137
20138    /**
20139     * {@hide}
20140     *
20141     * @param isRoot true if the view belongs to the root namespace, false
20142     *        otherwise
20143     */
20144    public void setIsRootNamespace(boolean isRoot) {
20145        if (isRoot) {
20146            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
20147        } else {
20148            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
20149        }
20150    }
20151
20152    /**
20153     * {@hide}
20154     *
20155     * @return true if the view belongs to the root namespace, false otherwise
20156     */
20157    public boolean isRootNamespace() {
20158        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
20159    }
20160
20161    /**
20162     * Returns this view's identifier.
20163     *
20164     * @return a positive integer used to identify the view or {@link #NO_ID}
20165     *         if the view has no ID
20166     *
20167     * @see #setId(int)
20168     * @see #findViewById(int)
20169     * @attr ref android.R.styleable#View_id
20170     */
20171    @IdRes
20172    @ViewDebug.CapturedViewProperty
20173    public int getId() {
20174        return mID;
20175    }
20176
20177    /**
20178     * Returns this view's tag.
20179     *
20180     * @return the Object stored in this view as a tag, or {@code null} if not
20181     *         set
20182     *
20183     * @see #setTag(Object)
20184     * @see #getTag(int)
20185     */
20186    @ViewDebug.ExportedProperty
20187    public Object getTag() {
20188        return mTag;
20189    }
20190
20191    /**
20192     * Sets the tag associated with this view. A tag can be used to mark
20193     * a view in its hierarchy and does not have to be unique within the
20194     * hierarchy. Tags can also be used to store data within a view without
20195     * resorting to another data structure.
20196     *
20197     * @param tag an Object to tag the view with
20198     *
20199     * @see #getTag()
20200     * @see #setTag(int, Object)
20201     */
20202    public void setTag(final Object tag) {
20203        mTag = tag;
20204    }
20205
20206    /**
20207     * Returns the tag associated with this view and the specified key.
20208     *
20209     * @param key The key identifying the tag
20210     *
20211     * @return the Object stored in this view as a tag, or {@code null} if not
20212     *         set
20213     *
20214     * @see #setTag(int, Object)
20215     * @see #getTag()
20216     */
20217    public Object getTag(int key) {
20218        if (mKeyedTags != null) return mKeyedTags.get(key);
20219        return null;
20220    }
20221
20222    /**
20223     * Sets a tag associated with this view and a key. A tag can be used
20224     * to mark a view in its hierarchy and does not have to be unique within
20225     * the hierarchy. Tags can also be used to store data within a view
20226     * without resorting to another data structure.
20227     *
20228     * The specified key should be an id declared in the resources of the
20229     * application to ensure it is unique (see the <a
20230     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
20231     * Keys identified as belonging to
20232     * the Android framework or not associated with any package will cause
20233     * an {@link IllegalArgumentException} to be thrown.
20234     *
20235     * @param key The key identifying the tag
20236     * @param tag An Object to tag the view with
20237     *
20238     * @throws IllegalArgumentException If they specified key is not valid
20239     *
20240     * @see #setTag(Object)
20241     * @see #getTag(int)
20242     */
20243    public void setTag(int key, final Object tag) {
20244        // If the package id is 0x00 or 0x01, it's either an undefined package
20245        // or a framework id
20246        if ((key >>> 24) < 2) {
20247            throw new IllegalArgumentException("The key must be an application-specific "
20248                    + "resource id.");
20249        }
20250
20251        setKeyedTag(key, tag);
20252    }
20253
20254    /**
20255     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
20256     * framework id.
20257     *
20258     * @hide
20259     */
20260    public void setTagInternal(int key, Object tag) {
20261        if ((key >>> 24) != 0x1) {
20262            throw new IllegalArgumentException("The key must be a framework-specific "
20263                    + "resource id.");
20264        }
20265
20266        setKeyedTag(key, tag);
20267    }
20268
20269    private void setKeyedTag(int key, Object tag) {
20270        if (mKeyedTags == null) {
20271            mKeyedTags = new SparseArray<Object>(2);
20272        }
20273
20274        mKeyedTags.put(key, tag);
20275    }
20276
20277    /**
20278     * Prints information about this view in the log output, with the tag
20279     * {@link #VIEW_LOG_TAG}.
20280     *
20281     * @hide
20282     */
20283    public void debug() {
20284        debug(0);
20285    }
20286
20287    /**
20288     * Prints information about this view in the log output, with the tag
20289     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
20290     * indentation defined by the <code>depth</code>.
20291     *
20292     * @param depth the indentation level
20293     *
20294     * @hide
20295     */
20296    protected void debug(int depth) {
20297        String output = debugIndent(depth - 1);
20298
20299        output += "+ " + this;
20300        int id = getId();
20301        if (id != -1) {
20302            output += " (id=" + id + ")";
20303        }
20304        Object tag = getTag();
20305        if (tag != null) {
20306            output += " (tag=" + tag + ")";
20307        }
20308        Log.d(VIEW_LOG_TAG, output);
20309
20310        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
20311            output = debugIndent(depth) + " FOCUSED";
20312            Log.d(VIEW_LOG_TAG, output);
20313        }
20314
20315        output = debugIndent(depth);
20316        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
20317                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
20318                + "} ";
20319        Log.d(VIEW_LOG_TAG, output);
20320
20321        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
20322                || mPaddingBottom != 0) {
20323            output = debugIndent(depth);
20324            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
20325                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
20326            Log.d(VIEW_LOG_TAG, output);
20327        }
20328
20329        output = debugIndent(depth);
20330        output += "mMeasureWidth=" + mMeasuredWidth +
20331                " mMeasureHeight=" + mMeasuredHeight;
20332        Log.d(VIEW_LOG_TAG, output);
20333
20334        output = debugIndent(depth);
20335        if (mLayoutParams == null) {
20336            output += "BAD! no layout params";
20337        } else {
20338            output = mLayoutParams.debug(output);
20339        }
20340        Log.d(VIEW_LOG_TAG, output);
20341
20342        output = debugIndent(depth);
20343        output += "flags={";
20344        output += View.printFlags(mViewFlags);
20345        output += "}";
20346        Log.d(VIEW_LOG_TAG, output);
20347
20348        output = debugIndent(depth);
20349        output += "privateFlags={";
20350        output += View.printPrivateFlags(mPrivateFlags);
20351        output += "}";
20352        Log.d(VIEW_LOG_TAG, output);
20353    }
20354
20355    /**
20356     * Creates a string of whitespaces used for indentation.
20357     *
20358     * @param depth the indentation level
20359     * @return a String containing (depth * 2 + 3) * 2 white spaces
20360     *
20361     * @hide
20362     */
20363    protected static String debugIndent(int depth) {
20364        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
20365        for (int i = 0; i < (depth * 2) + 3; i++) {
20366            spaces.append(' ').append(' ');
20367        }
20368        return spaces.toString();
20369    }
20370
20371    /**
20372     * <p>Return the offset of the widget's text baseline from the widget's top
20373     * boundary. If this widget does not support baseline alignment, this
20374     * method returns -1. </p>
20375     *
20376     * @return the offset of the baseline within the widget's bounds or -1
20377     *         if baseline alignment is not supported
20378     */
20379    @ViewDebug.ExportedProperty(category = "layout")
20380    public int getBaseline() {
20381        return -1;
20382    }
20383
20384    /**
20385     * Returns whether the view hierarchy is currently undergoing a layout pass. This
20386     * information is useful to avoid situations such as calling {@link #requestLayout()} during
20387     * a layout pass.
20388     *
20389     * @return whether the view hierarchy is currently undergoing a layout pass
20390     */
20391    public boolean isInLayout() {
20392        ViewRootImpl viewRoot = getViewRootImpl();
20393        return (viewRoot != null && viewRoot.isInLayout());
20394    }
20395
20396    /**
20397     * Call this when something has changed which has invalidated the
20398     * layout of this view. This will schedule a layout pass of the view
20399     * tree. This should not be called while the view hierarchy is currently in a layout
20400     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
20401     * end of the current layout pass (and then layout will run again) or after the current
20402     * frame is drawn and the next layout occurs.
20403     *
20404     * <p>Subclasses which override this method should call the superclass method to
20405     * handle possible request-during-layout errors correctly.</p>
20406     */
20407    @CallSuper
20408    public void requestLayout() {
20409        if (mMeasureCache != null) mMeasureCache.clear();
20410
20411        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
20412            // Only trigger request-during-layout logic if this is the view requesting it,
20413            // not the views in its parent hierarchy
20414            ViewRootImpl viewRoot = getViewRootImpl();
20415            if (viewRoot != null && viewRoot.isInLayout()) {
20416                if (!viewRoot.requestLayoutDuringLayout(this)) {
20417                    return;
20418                }
20419            }
20420            mAttachInfo.mViewRequestingLayout = this;
20421        }
20422
20423        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
20424        mPrivateFlags |= PFLAG_INVALIDATED;
20425
20426        if (mParent != null && !mParent.isLayoutRequested()) {
20427            mParent.requestLayout();
20428        }
20429        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
20430            mAttachInfo.mViewRequestingLayout = null;
20431        }
20432    }
20433
20434    /**
20435     * Forces this view to be laid out during the next layout pass.
20436     * This method does not call requestLayout() or forceLayout()
20437     * on the parent.
20438     */
20439    public void forceLayout() {
20440        if (mMeasureCache != null) mMeasureCache.clear();
20441
20442        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
20443        mPrivateFlags |= PFLAG_INVALIDATED;
20444    }
20445
20446    /**
20447     * <p>
20448     * This is called to find out how big a view should be. The parent
20449     * supplies constraint information in the width and height parameters.
20450     * </p>
20451     *
20452     * <p>
20453     * The actual measurement work of a view is performed in
20454     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
20455     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
20456     * </p>
20457     *
20458     *
20459     * @param widthMeasureSpec Horizontal space requirements as imposed by the
20460     *        parent
20461     * @param heightMeasureSpec Vertical space requirements as imposed by the
20462     *        parent
20463     *
20464     * @see #onMeasure(int, int)
20465     */
20466    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
20467        boolean optical = isLayoutModeOptical(this);
20468        if (optical != isLayoutModeOptical(mParent)) {
20469            Insets insets = getOpticalInsets();
20470            int oWidth  = insets.left + insets.right;
20471            int oHeight = insets.top  + insets.bottom;
20472            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
20473            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
20474        }
20475
20476        // Suppress sign extension for the low bytes
20477        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
20478        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
20479
20480        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
20481
20482        // Optimize layout by avoiding an extra EXACTLY pass when the view is
20483        // already measured as the correct size. In API 23 and below, this
20484        // extra pass is required to make LinearLayout re-distribute weight.
20485        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
20486                || heightMeasureSpec != mOldHeightMeasureSpec;
20487        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
20488                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
20489        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
20490                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
20491        final boolean needsLayout = specChanged
20492                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
20493
20494        if (forceLayout || needsLayout) {
20495            // first clears the measured dimension flag
20496            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
20497
20498            resolveRtlPropertiesIfNeeded();
20499
20500            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
20501            if (cacheIndex < 0 || sIgnoreMeasureCache) {
20502                // measure ourselves, this should set the measured dimension flag back
20503                onMeasure(widthMeasureSpec, heightMeasureSpec);
20504                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
20505            } else {
20506                long value = mMeasureCache.valueAt(cacheIndex);
20507                // Casting a long to int drops the high 32 bits, no mask needed
20508                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
20509                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
20510            }
20511
20512            // flag not set, setMeasuredDimension() was not invoked, we raise
20513            // an exception to warn the developer
20514            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
20515                throw new IllegalStateException("View with id " + getId() + ": "
20516                        + getClass().getName() + "#onMeasure() did not set the"
20517                        + " measured dimension by calling"
20518                        + " setMeasuredDimension()");
20519            }
20520
20521            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
20522        }
20523
20524        mOldWidthMeasureSpec = widthMeasureSpec;
20525        mOldHeightMeasureSpec = heightMeasureSpec;
20526
20527        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
20528                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
20529    }
20530
20531    /**
20532     * <p>
20533     * Measure the view and its content to determine the measured width and the
20534     * measured height. This method is invoked by {@link #measure(int, int)} and
20535     * should be overridden by subclasses to provide accurate and efficient
20536     * measurement of their contents.
20537     * </p>
20538     *
20539     * <p>
20540     * <strong>CONTRACT:</strong> When overriding this method, you
20541     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
20542     * measured width and height of this view. Failure to do so will trigger an
20543     * <code>IllegalStateException</code>, thrown by
20544     * {@link #measure(int, int)}. Calling the superclass'
20545     * {@link #onMeasure(int, int)} is a valid use.
20546     * </p>
20547     *
20548     * <p>
20549     * The base class implementation of measure defaults to the background size,
20550     * unless a larger size is allowed by the MeasureSpec. Subclasses should
20551     * override {@link #onMeasure(int, int)} to provide better measurements of
20552     * their content.
20553     * </p>
20554     *
20555     * <p>
20556     * If this method is overridden, it is the subclass's responsibility to make
20557     * sure the measured height and width are at least the view's minimum height
20558     * and width ({@link #getSuggestedMinimumHeight()} and
20559     * {@link #getSuggestedMinimumWidth()}).
20560     * </p>
20561     *
20562     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
20563     *                         The requirements are encoded with
20564     *                         {@link android.view.View.MeasureSpec}.
20565     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
20566     *                         The requirements are encoded with
20567     *                         {@link android.view.View.MeasureSpec}.
20568     *
20569     * @see #getMeasuredWidth()
20570     * @see #getMeasuredHeight()
20571     * @see #setMeasuredDimension(int, int)
20572     * @see #getSuggestedMinimumHeight()
20573     * @see #getSuggestedMinimumWidth()
20574     * @see android.view.View.MeasureSpec#getMode(int)
20575     * @see android.view.View.MeasureSpec#getSize(int)
20576     */
20577    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
20578        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
20579                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
20580    }
20581
20582    /**
20583     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
20584     * measured width and measured height. Failing to do so will trigger an
20585     * exception at measurement time.</p>
20586     *
20587     * @param measuredWidth The measured width of this view.  May be a complex
20588     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20589     * {@link #MEASURED_STATE_TOO_SMALL}.
20590     * @param measuredHeight The measured height of this view.  May be a complex
20591     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20592     * {@link #MEASURED_STATE_TOO_SMALL}.
20593     */
20594    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
20595        boolean optical = isLayoutModeOptical(this);
20596        if (optical != isLayoutModeOptical(mParent)) {
20597            Insets insets = getOpticalInsets();
20598            int opticalWidth  = insets.left + insets.right;
20599            int opticalHeight = insets.top  + insets.bottom;
20600
20601            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
20602            measuredHeight += optical ? opticalHeight : -opticalHeight;
20603        }
20604        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
20605    }
20606
20607    /**
20608     * Sets the measured dimension without extra processing for things like optical bounds.
20609     * Useful for reapplying consistent values that have already been cooked with adjustments
20610     * for optical bounds, etc. such as those from the measurement cache.
20611     *
20612     * @param measuredWidth The measured width of this view.  May be a complex
20613     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20614     * {@link #MEASURED_STATE_TOO_SMALL}.
20615     * @param measuredHeight The measured height of this view.  May be a complex
20616     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20617     * {@link #MEASURED_STATE_TOO_SMALL}.
20618     */
20619    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
20620        mMeasuredWidth = measuredWidth;
20621        mMeasuredHeight = measuredHeight;
20622
20623        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
20624    }
20625
20626    /**
20627     * Merge two states as returned by {@link #getMeasuredState()}.
20628     * @param curState The current state as returned from a view or the result
20629     * of combining multiple views.
20630     * @param newState The new view state to combine.
20631     * @return Returns a new integer reflecting the combination of the two
20632     * states.
20633     */
20634    public static int combineMeasuredStates(int curState, int newState) {
20635        return curState | newState;
20636    }
20637
20638    /**
20639     * Version of {@link #resolveSizeAndState(int, int, int)}
20640     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
20641     */
20642    public static int resolveSize(int size, int measureSpec) {
20643        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
20644    }
20645
20646    /**
20647     * Utility to reconcile a desired size and state, with constraints imposed
20648     * by a MeasureSpec. Will take the desired size, unless a different size
20649     * is imposed by the constraints. The returned value is a compound integer,
20650     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
20651     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
20652     * resulting size is smaller than the size the view wants to be.
20653     *
20654     * @param size How big the view wants to be.
20655     * @param measureSpec Constraints imposed by the parent.
20656     * @param childMeasuredState Size information bit mask for the view's
20657     *                           children.
20658     * @return Size information bit mask as defined by
20659     *         {@link #MEASURED_SIZE_MASK} and
20660     *         {@link #MEASURED_STATE_TOO_SMALL}.
20661     */
20662    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
20663        final int specMode = MeasureSpec.getMode(measureSpec);
20664        final int specSize = MeasureSpec.getSize(measureSpec);
20665        final int result;
20666        switch (specMode) {
20667            case MeasureSpec.AT_MOST:
20668                if (specSize < size) {
20669                    result = specSize | MEASURED_STATE_TOO_SMALL;
20670                } else {
20671                    result = size;
20672                }
20673                break;
20674            case MeasureSpec.EXACTLY:
20675                result = specSize;
20676                break;
20677            case MeasureSpec.UNSPECIFIED:
20678            default:
20679                result = size;
20680        }
20681        return result | (childMeasuredState & MEASURED_STATE_MASK);
20682    }
20683
20684    /**
20685     * Utility to return a default size. Uses the supplied size if the
20686     * MeasureSpec imposed no constraints. Will get larger if allowed
20687     * by the MeasureSpec.
20688     *
20689     * @param size Default size for this view
20690     * @param measureSpec Constraints imposed by the parent
20691     * @return The size this view should be.
20692     */
20693    public static int getDefaultSize(int size, int measureSpec) {
20694        int result = size;
20695        int specMode = MeasureSpec.getMode(measureSpec);
20696        int specSize = MeasureSpec.getSize(measureSpec);
20697
20698        switch (specMode) {
20699        case MeasureSpec.UNSPECIFIED:
20700            result = size;
20701            break;
20702        case MeasureSpec.AT_MOST:
20703        case MeasureSpec.EXACTLY:
20704            result = specSize;
20705            break;
20706        }
20707        return result;
20708    }
20709
20710    /**
20711     * Returns the suggested minimum height that the view should use. This
20712     * returns the maximum of the view's minimum height
20713     * and the background's minimum height
20714     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
20715     * <p>
20716     * When being used in {@link #onMeasure(int, int)}, the caller should still
20717     * ensure the returned height is within the requirements of the parent.
20718     *
20719     * @return The suggested minimum height of the view.
20720     */
20721    protected int getSuggestedMinimumHeight() {
20722        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
20723
20724    }
20725
20726    /**
20727     * Returns the suggested minimum width that the view should use. This
20728     * returns the maximum of the view's minimum width
20729     * and the background's minimum width
20730     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
20731     * <p>
20732     * When being used in {@link #onMeasure(int, int)}, the caller should still
20733     * ensure the returned width is within the requirements of the parent.
20734     *
20735     * @return The suggested minimum width of the view.
20736     */
20737    protected int getSuggestedMinimumWidth() {
20738        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
20739    }
20740
20741    /**
20742     * Returns the minimum height of the view.
20743     *
20744     * @return the minimum height the view will try to be, in pixels
20745     *
20746     * @see #setMinimumHeight(int)
20747     *
20748     * @attr ref android.R.styleable#View_minHeight
20749     */
20750    public int getMinimumHeight() {
20751        return mMinHeight;
20752    }
20753
20754    /**
20755     * Sets the minimum height of the view. It is not guaranteed the view will
20756     * be able to achieve this minimum height (for example, if its parent layout
20757     * constrains it with less available height).
20758     *
20759     * @param minHeight The minimum height the view will try to be, in pixels
20760     *
20761     * @see #getMinimumHeight()
20762     *
20763     * @attr ref android.R.styleable#View_minHeight
20764     */
20765    @RemotableViewMethod
20766    public void setMinimumHeight(int minHeight) {
20767        mMinHeight = minHeight;
20768        requestLayout();
20769    }
20770
20771    /**
20772     * Returns the minimum width of the view.
20773     *
20774     * @return the minimum width the view will try to be, in pixels
20775     *
20776     * @see #setMinimumWidth(int)
20777     *
20778     * @attr ref android.R.styleable#View_minWidth
20779     */
20780    public int getMinimumWidth() {
20781        return mMinWidth;
20782    }
20783
20784    /**
20785     * Sets the minimum width of the view. It is not guaranteed the view will
20786     * be able to achieve this minimum width (for example, if its parent layout
20787     * constrains it with less available width).
20788     *
20789     * @param minWidth The minimum width the view will try to be, in pixels
20790     *
20791     * @see #getMinimumWidth()
20792     *
20793     * @attr ref android.R.styleable#View_minWidth
20794     */
20795    public void setMinimumWidth(int minWidth) {
20796        mMinWidth = minWidth;
20797        requestLayout();
20798
20799    }
20800
20801    /**
20802     * Get the animation currently associated with this view.
20803     *
20804     * @return The animation that is currently playing or
20805     *         scheduled to play for this view.
20806     */
20807    public Animation getAnimation() {
20808        return mCurrentAnimation;
20809    }
20810
20811    /**
20812     * Start the specified animation now.
20813     *
20814     * @param animation the animation to start now
20815     */
20816    public void startAnimation(Animation animation) {
20817        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
20818        setAnimation(animation);
20819        invalidateParentCaches();
20820        invalidate(true);
20821    }
20822
20823    /**
20824     * Cancels any animations for this view.
20825     */
20826    public void clearAnimation() {
20827        if (mCurrentAnimation != null) {
20828            mCurrentAnimation.detach();
20829        }
20830        mCurrentAnimation = null;
20831        invalidateParentIfNeeded();
20832    }
20833
20834    /**
20835     * Sets the next animation to play for this view.
20836     * If you want the animation to play immediately, use
20837     * {@link #startAnimation(android.view.animation.Animation)} instead.
20838     * This method provides allows fine-grained
20839     * control over the start time and invalidation, but you
20840     * must make sure that 1) the animation has a start time set, and
20841     * 2) the view's parent (which controls animations on its children)
20842     * will be invalidated when the animation is supposed to
20843     * start.
20844     *
20845     * @param animation The next animation, or null.
20846     */
20847    public void setAnimation(Animation animation) {
20848        mCurrentAnimation = animation;
20849
20850        if (animation != null) {
20851            // If the screen is off assume the animation start time is now instead of
20852            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
20853            // would cause the animation to start when the screen turns back on
20854            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
20855                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
20856                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
20857            }
20858            animation.reset();
20859        }
20860    }
20861
20862    /**
20863     * Invoked by a parent ViewGroup to notify the start of the animation
20864     * currently associated with this view. If you override this method,
20865     * always call super.onAnimationStart();
20866     *
20867     * @see #setAnimation(android.view.animation.Animation)
20868     * @see #getAnimation()
20869     */
20870    @CallSuper
20871    protected void onAnimationStart() {
20872        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
20873    }
20874
20875    /**
20876     * Invoked by a parent ViewGroup to notify the end of the animation
20877     * currently associated with this view. If you override this method,
20878     * always call super.onAnimationEnd();
20879     *
20880     * @see #setAnimation(android.view.animation.Animation)
20881     * @see #getAnimation()
20882     */
20883    @CallSuper
20884    protected void onAnimationEnd() {
20885        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
20886    }
20887
20888    /**
20889     * Invoked if there is a Transform that involves alpha. Subclass that can
20890     * draw themselves with the specified alpha should return true, and then
20891     * respect that alpha when their onDraw() is called. If this returns false
20892     * then the view may be redirected to draw into an offscreen buffer to
20893     * fulfill the request, which will look fine, but may be slower than if the
20894     * subclass handles it internally. The default implementation returns false.
20895     *
20896     * @param alpha The alpha (0..255) to apply to the view's drawing
20897     * @return true if the view can draw with the specified alpha.
20898     */
20899    protected boolean onSetAlpha(int alpha) {
20900        return false;
20901    }
20902
20903    /**
20904     * This is used by the RootView to perform an optimization when
20905     * the view hierarchy contains one or several SurfaceView.
20906     * SurfaceView is always considered transparent, but its children are not,
20907     * therefore all View objects remove themselves from the global transparent
20908     * region (passed as a parameter to this function).
20909     *
20910     * @param region The transparent region for this ViewAncestor (window).
20911     *
20912     * @return Returns true if the effective visibility of the view at this
20913     * point is opaque, regardless of the transparent region; returns false
20914     * if it is possible for underlying windows to be seen behind the view.
20915     *
20916     * {@hide}
20917     */
20918    public boolean gatherTransparentRegion(Region region) {
20919        final AttachInfo attachInfo = mAttachInfo;
20920        if (region != null && attachInfo != null) {
20921            final int pflags = mPrivateFlags;
20922            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
20923                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
20924                // remove it from the transparent region.
20925                final int[] location = attachInfo.mTransparentLocation;
20926                getLocationInWindow(location);
20927                // When a view has Z value, then it will be better to leave some area below the view
20928                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
20929                // the bottom part needs more offset than the left, top and right parts due to the
20930                // spot light effects.
20931                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
20932                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
20933                        location[0] + mRight - mLeft + shadowOffset,
20934                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
20935            } else {
20936                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
20937                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
20938                    // the background drawable's non-transparent parts from this transparent region.
20939                    applyDrawableToTransparentRegion(mBackground, region);
20940                }
20941                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20942                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
20943                    // Similarly, we remove the foreground drawable's non-transparent parts.
20944                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
20945                }
20946            }
20947        }
20948        return true;
20949    }
20950
20951    /**
20952     * Play a sound effect for this view.
20953     *
20954     * <p>The framework will play sound effects for some built in actions, such as
20955     * clicking, but you may wish to play these effects in your widget,
20956     * for instance, for internal navigation.
20957     *
20958     * <p>The sound effect will only be played if sound effects are enabled by the user, and
20959     * {@link #isSoundEffectsEnabled()} is true.
20960     *
20961     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
20962     */
20963    public void playSoundEffect(int soundConstant) {
20964        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
20965            return;
20966        }
20967        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
20968    }
20969
20970    /**
20971     * BZZZTT!!1!
20972     *
20973     * <p>Provide haptic feedback to the user for this view.
20974     *
20975     * <p>The framework will provide haptic feedback for some built in actions,
20976     * such as long presses, but you may wish to provide feedback for your
20977     * own widget.
20978     *
20979     * <p>The feedback will only be performed if
20980     * {@link #isHapticFeedbackEnabled()} is true.
20981     *
20982     * @param feedbackConstant One of the constants defined in
20983     * {@link HapticFeedbackConstants}
20984     */
20985    public boolean performHapticFeedback(int feedbackConstant) {
20986        return performHapticFeedback(feedbackConstant, 0);
20987    }
20988
20989    /**
20990     * BZZZTT!!1!
20991     *
20992     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
20993     *
20994     * @param feedbackConstant One of the constants defined in
20995     * {@link HapticFeedbackConstants}
20996     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
20997     */
20998    public boolean performHapticFeedback(int feedbackConstant, int flags) {
20999        if (mAttachInfo == null) {
21000            return false;
21001        }
21002        //noinspection SimplifiableIfStatement
21003        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
21004                && !isHapticFeedbackEnabled()) {
21005            return false;
21006        }
21007        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
21008                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
21009    }
21010
21011    /**
21012     * Request that the visibility of the status bar or other screen/window
21013     * decorations be changed.
21014     *
21015     * <p>This method is used to put the over device UI into temporary modes
21016     * where the user's attention is focused more on the application content,
21017     * by dimming or hiding surrounding system affordances.  This is typically
21018     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
21019     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
21020     * to be placed behind the action bar (and with these flags other system
21021     * affordances) so that smooth transitions between hiding and showing them
21022     * can be done.
21023     *
21024     * <p>Two representative examples of the use of system UI visibility is
21025     * implementing a content browsing application (like a magazine reader)
21026     * and a video playing application.
21027     *
21028     * <p>The first code shows a typical implementation of a View in a content
21029     * browsing application.  In this implementation, the application goes
21030     * into a content-oriented mode by hiding the status bar and action bar,
21031     * and putting the navigation elements into lights out mode.  The user can
21032     * then interact with content while in this mode.  Such an application should
21033     * provide an easy way for the user to toggle out of the mode (such as to
21034     * check information in the status bar or access notifications).  In the
21035     * implementation here, this is done simply by tapping on the content.
21036     *
21037     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
21038     *      content}
21039     *
21040     * <p>This second code sample shows a typical implementation of a View
21041     * in a video playing application.  In this situation, while the video is
21042     * playing the application would like to go into a complete full-screen mode,
21043     * to use as much of the display as possible for the video.  When in this state
21044     * the user can not interact with the application; the system intercepts
21045     * touching on the screen to pop the UI out of full screen mode.  See
21046     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
21047     *
21048     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
21049     *      content}
21050     *
21051     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21052     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
21053     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
21054     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
21055     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
21056     */
21057    public void setSystemUiVisibility(int visibility) {
21058        if (visibility != mSystemUiVisibility) {
21059            mSystemUiVisibility = visibility;
21060            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
21061                mParent.recomputeViewAttributes(this);
21062            }
21063        }
21064    }
21065
21066    /**
21067     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
21068     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21069     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
21070     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
21071     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
21072     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
21073     */
21074    public int getSystemUiVisibility() {
21075        return mSystemUiVisibility;
21076    }
21077
21078    /**
21079     * Returns the current system UI visibility that is currently set for
21080     * the entire window.  This is the combination of the
21081     * {@link #setSystemUiVisibility(int)} values supplied by all of the
21082     * views in the window.
21083     */
21084    public int getWindowSystemUiVisibility() {
21085        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
21086    }
21087
21088    /**
21089     * Override to find out when the window's requested system UI visibility
21090     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
21091     * This is different from the callbacks received through
21092     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
21093     * in that this is only telling you about the local request of the window,
21094     * not the actual values applied by the system.
21095     */
21096    public void onWindowSystemUiVisibilityChanged(int visible) {
21097    }
21098
21099    /**
21100     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
21101     * the view hierarchy.
21102     */
21103    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
21104        onWindowSystemUiVisibilityChanged(visible);
21105    }
21106
21107    /**
21108     * Set a listener to receive callbacks when the visibility of the system bar changes.
21109     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
21110     */
21111    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
21112        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
21113        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
21114            mParent.recomputeViewAttributes(this);
21115        }
21116    }
21117
21118    /**
21119     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
21120     * the view hierarchy.
21121     */
21122    public void dispatchSystemUiVisibilityChanged(int visibility) {
21123        ListenerInfo li = mListenerInfo;
21124        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
21125            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
21126                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
21127        }
21128    }
21129
21130    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
21131        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
21132        if (val != mSystemUiVisibility) {
21133            setSystemUiVisibility(val);
21134            return true;
21135        }
21136        return false;
21137    }
21138
21139    /** @hide */
21140    public void setDisabledSystemUiVisibility(int flags) {
21141        if (mAttachInfo != null) {
21142            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
21143                mAttachInfo.mDisabledSystemUiVisibility = flags;
21144                if (mParent != null) {
21145                    mParent.recomputeViewAttributes(this);
21146                }
21147            }
21148        }
21149    }
21150
21151    /**
21152     * Creates an image that the system displays during the drag and drop
21153     * operation. This is called a &quot;drag shadow&quot;. The default implementation
21154     * for a DragShadowBuilder based on a View returns an image that has exactly the same
21155     * appearance as the given View. The default also positions the center of the drag shadow
21156     * directly under the touch point. If no View is provided (the constructor with no parameters
21157     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
21158     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
21159     * default is an invisible drag shadow.
21160     * <p>
21161     * You are not required to use the View you provide to the constructor as the basis of the
21162     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
21163     * anything you want as the drag shadow.
21164     * </p>
21165     * <p>
21166     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
21167     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
21168     *  size and position of the drag shadow. It uses this data to construct a
21169     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
21170     *  so that your application can draw the shadow image in the Canvas.
21171     * </p>
21172     *
21173     * <div class="special reference">
21174     * <h3>Developer Guides</h3>
21175     * <p>For a guide to implementing drag and drop features, read the
21176     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21177     * </div>
21178     */
21179    public static class DragShadowBuilder {
21180        private final WeakReference<View> mView;
21181
21182        /**
21183         * Constructs a shadow image builder based on a View. By default, the resulting drag
21184         * shadow will have the same appearance and dimensions as the View, with the touch point
21185         * over the center of the View.
21186         * @param view A View. Any View in scope can be used.
21187         */
21188        public DragShadowBuilder(View view) {
21189            mView = new WeakReference<View>(view);
21190        }
21191
21192        /**
21193         * Construct a shadow builder object with no associated View.  This
21194         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
21195         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
21196         * to supply the drag shadow's dimensions and appearance without
21197         * reference to any View object. If they are not overridden, then the result is an
21198         * invisible drag shadow.
21199         */
21200        public DragShadowBuilder() {
21201            mView = new WeakReference<View>(null);
21202        }
21203
21204        /**
21205         * Returns the View object that had been passed to the
21206         * {@link #View.DragShadowBuilder(View)}
21207         * constructor.  If that View parameter was {@code null} or if the
21208         * {@link #View.DragShadowBuilder()}
21209         * constructor was used to instantiate the builder object, this method will return
21210         * null.
21211         *
21212         * @return The View object associate with this builder object.
21213         */
21214        @SuppressWarnings({"JavadocReference"})
21215        final public View getView() {
21216            return mView.get();
21217        }
21218
21219        /**
21220         * Provides the metrics for the shadow image. These include the dimensions of
21221         * the shadow image, and the point within that shadow that should
21222         * be centered under the touch location while dragging.
21223         * <p>
21224         * The default implementation sets the dimensions of the shadow to be the
21225         * same as the dimensions of the View itself and centers the shadow under
21226         * the touch point.
21227         * </p>
21228         *
21229         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
21230         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
21231         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
21232         * image.
21233         *
21234         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
21235         * shadow image that should be underneath the touch point during the drag and drop
21236         * operation. Your application must set {@link android.graphics.Point#x} to the
21237         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
21238         */
21239        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
21240            final View view = mView.get();
21241            if (view != null) {
21242                outShadowSize.set(view.getWidth(), view.getHeight());
21243                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
21244            } else {
21245                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
21246            }
21247        }
21248
21249        /**
21250         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
21251         * based on the dimensions it received from the
21252         * {@link #onProvideShadowMetrics(Point, Point)} callback.
21253         *
21254         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
21255         */
21256        public void onDrawShadow(Canvas canvas) {
21257            final View view = mView.get();
21258            if (view != null) {
21259                view.draw(canvas);
21260            } else {
21261                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
21262            }
21263        }
21264    }
21265
21266    /**
21267     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
21268     * startDragAndDrop()} for newer platform versions.
21269     */
21270    @Deprecated
21271    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
21272                                   Object myLocalState, int flags) {
21273        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
21274    }
21275
21276    /**
21277     * Starts a drag and drop operation. When your application calls this method, it passes a
21278     * {@link android.view.View.DragShadowBuilder} object to the system. The
21279     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
21280     * to get metrics for the drag shadow, and then calls the object's
21281     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
21282     * <p>
21283     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
21284     *  drag events to all the View objects in your application that are currently visible. It does
21285     *  this either by calling the View object's drag listener (an implementation of
21286     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
21287     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
21288     *  Both are passed a {@link android.view.DragEvent} object that has a
21289     *  {@link android.view.DragEvent#getAction()} value of
21290     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
21291     * </p>
21292     * <p>
21293     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
21294     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
21295     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
21296     * to the View the user selected for dragging.
21297     * </p>
21298     * @param data A {@link android.content.ClipData} object pointing to the data to be
21299     * transferred by the drag and drop operation.
21300     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
21301     * drag shadow.
21302     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
21303     * drop operation. When dispatching drag events to views in the same activity this object
21304     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
21305     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
21306     * will return null).
21307     * <p>
21308     * myLocalState is a lightweight mechanism for the sending information from the dragged View
21309     * to the target Views. For example, it can contain flags that differentiate between a
21310     * a copy operation and a move operation.
21311     * </p>
21312     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
21313     * flags, or any combination of the following:
21314     *     <ul>
21315     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
21316     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
21317     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
21318     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
21319     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
21320     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
21321     *     </ul>
21322     * @return {@code true} if the method completes successfully, or
21323     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
21324     * do a drag, and so no drag operation is in progress.
21325     */
21326    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
21327            Object myLocalState, int flags) {
21328        if (ViewDebug.DEBUG_DRAG) {
21329            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
21330        }
21331        if (mAttachInfo == null) {
21332            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
21333            return false;
21334        }
21335
21336        if (data != null) {
21337            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
21338        }
21339
21340        boolean okay = false;
21341
21342        Point shadowSize = new Point();
21343        Point shadowTouchPoint = new Point();
21344        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
21345
21346        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
21347                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
21348            throw new IllegalStateException("Drag shadow dimensions must not be negative");
21349        }
21350
21351        if (ViewDebug.DEBUG_DRAG) {
21352            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
21353                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
21354        }
21355        if (mAttachInfo.mDragSurface != null) {
21356            mAttachInfo.mDragSurface.release();
21357        }
21358        mAttachInfo.mDragSurface = new Surface();
21359        try {
21360            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
21361                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
21362            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
21363                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
21364            if (mAttachInfo.mDragToken != null) {
21365                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
21366                try {
21367                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
21368                    shadowBuilder.onDrawShadow(canvas);
21369                } finally {
21370                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
21371                }
21372
21373                final ViewRootImpl root = getViewRootImpl();
21374
21375                // Cache the local state object for delivery with DragEvents
21376                root.setLocalDragState(myLocalState);
21377
21378                // repurpose 'shadowSize' for the last touch point
21379                root.getLastTouchPoint(shadowSize);
21380
21381                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
21382                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
21383                        shadowTouchPoint.x, shadowTouchPoint.y, data);
21384                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
21385            }
21386        } catch (Exception e) {
21387            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
21388            mAttachInfo.mDragSurface.destroy();
21389            mAttachInfo.mDragSurface = null;
21390        }
21391
21392        return okay;
21393    }
21394
21395    /**
21396     * Cancels an ongoing drag and drop operation.
21397     * <p>
21398     * A {@link android.view.DragEvent} object with
21399     * {@link android.view.DragEvent#getAction()} value of
21400     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
21401     * {@link android.view.DragEvent#getResult()} value of {@code false}
21402     * will be sent to every
21403     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
21404     * even if they are not currently visible.
21405     * </p>
21406     * <p>
21407     * This method can be called on any View in the same window as the View on which
21408     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
21409     * was called.
21410     * </p>
21411     */
21412    public final void cancelDragAndDrop() {
21413        if (ViewDebug.DEBUG_DRAG) {
21414            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
21415        }
21416        if (mAttachInfo == null) {
21417            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
21418            return;
21419        }
21420        if (mAttachInfo.mDragToken != null) {
21421            try {
21422                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
21423            } catch (Exception e) {
21424                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
21425            }
21426            mAttachInfo.mDragToken = null;
21427        } else {
21428            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
21429        }
21430    }
21431
21432    /**
21433     * Updates the drag shadow for the ongoing drag and drop operation.
21434     *
21435     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
21436     * new drag shadow.
21437     */
21438    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
21439        if (ViewDebug.DEBUG_DRAG) {
21440            Log.d(VIEW_LOG_TAG, "updateDragShadow");
21441        }
21442        if (mAttachInfo == null) {
21443            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
21444            return;
21445        }
21446        if (mAttachInfo.mDragToken != null) {
21447            try {
21448                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
21449                try {
21450                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
21451                    shadowBuilder.onDrawShadow(canvas);
21452                } finally {
21453                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
21454                }
21455            } catch (Exception e) {
21456                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
21457            }
21458        } else {
21459            Log.e(VIEW_LOG_TAG, "No active drag");
21460        }
21461    }
21462
21463    /**
21464     * Starts a move from {startX, startY}, the amount of the movement will be the offset
21465     * between {startX, startY} and the new cursor positon.
21466     * @param startX horizontal coordinate where the move started.
21467     * @param startY vertical coordinate where the move started.
21468     * @return whether moving was started successfully.
21469     * @hide
21470     */
21471    public final boolean startMovingTask(float startX, float startY) {
21472        if (ViewDebug.DEBUG_POSITIONING) {
21473            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
21474        }
21475        try {
21476            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
21477        } catch (RemoteException e) {
21478            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
21479        }
21480        return false;
21481    }
21482
21483    /**
21484     * Handles drag events sent by the system following a call to
21485     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
21486     * startDragAndDrop()}.
21487     *<p>
21488     * When the system calls this method, it passes a
21489     * {@link android.view.DragEvent} object. A call to
21490     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
21491     * in DragEvent. The method uses these to determine what is happening in the drag and drop
21492     * operation.
21493     * @param event The {@link android.view.DragEvent} sent by the system.
21494     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
21495     * in DragEvent, indicating the type of drag event represented by this object.
21496     * @return {@code true} if the method was successful, otherwise {@code false}.
21497     * <p>
21498     *  The method should return {@code true} in response to an action type of
21499     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
21500     *  operation.
21501     * </p>
21502     * <p>
21503     *  The method should also return {@code true} in response to an action type of
21504     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
21505     *  {@code false} if it didn't.
21506     * </p>
21507     * <p>
21508     *  For all other events, the return value is ignored.
21509     * </p>
21510     */
21511    public boolean onDragEvent(DragEvent event) {
21512        return false;
21513    }
21514
21515    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
21516    boolean dispatchDragEnterExitInPreN(DragEvent event) {
21517        return callDragEventHandler(event);
21518    }
21519
21520    /**
21521     * Detects if this View is enabled and has a drag event listener.
21522     * If both are true, then it calls the drag event listener with the
21523     * {@link android.view.DragEvent} it received. If the drag event listener returns
21524     * {@code true}, then dispatchDragEvent() returns {@code true}.
21525     * <p>
21526     * For all other cases, the method calls the
21527     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
21528     * method and returns its result.
21529     * </p>
21530     * <p>
21531     * This ensures that a drag event is always consumed, even if the View does not have a drag
21532     * event listener. However, if the View has a listener and the listener returns true, then
21533     * onDragEvent() is not called.
21534     * </p>
21535     */
21536    public boolean dispatchDragEvent(DragEvent event) {
21537        event.mEventHandlerWasCalled = true;
21538        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
21539            event.mAction == DragEvent.ACTION_DROP) {
21540            // About to deliver an event with coordinates to this view. Notify that now this view
21541            // has drag focus. This will send exit/enter events as needed.
21542            getViewRootImpl().setDragFocus(this, event);
21543        }
21544        return callDragEventHandler(event);
21545    }
21546
21547    final boolean callDragEventHandler(DragEvent event) {
21548        final boolean result;
21549
21550        ListenerInfo li = mListenerInfo;
21551        //noinspection SimplifiableIfStatement
21552        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
21553                && li.mOnDragListener.onDrag(this, event)) {
21554            result = true;
21555        } else {
21556            result = onDragEvent(event);
21557        }
21558
21559        switch (event.mAction) {
21560            case DragEvent.ACTION_DRAG_ENTERED: {
21561                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
21562                refreshDrawableState();
21563            } break;
21564            case DragEvent.ACTION_DRAG_EXITED: {
21565                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
21566                refreshDrawableState();
21567            } break;
21568            case DragEvent.ACTION_DRAG_ENDED: {
21569                mPrivateFlags2 &= ~View.DRAG_MASK;
21570                refreshDrawableState();
21571            } break;
21572        }
21573
21574        return result;
21575    }
21576
21577    boolean canAcceptDrag() {
21578        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
21579    }
21580
21581    /**
21582     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
21583     * it is ever exposed at all.
21584     * @hide
21585     */
21586    public void onCloseSystemDialogs(String reason) {
21587    }
21588
21589    /**
21590     * Given a Drawable whose bounds have been set to draw into this view,
21591     * update a Region being computed for
21592     * {@link #gatherTransparentRegion(android.graphics.Region)} so
21593     * that any non-transparent parts of the Drawable are removed from the
21594     * given transparent region.
21595     *
21596     * @param dr The Drawable whose transparency is to be applied to the region.
21597     * @param region A Region holding the current transparency information,
21598     * where any parts of the region that are set are considered to be
21599     * transparent.  On return, this region will be modified to have the
21600     * transparency information reduced by the corresponding parts of the
21601     * Drawable that are not transparent.
21602     * {@hide}
21603     */
21604    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
21605        if (DBG) {
21606            Log.i("View", "Getting transparent region for: " + this);
21607        }
21608        final Region r = dr.getTransparentRegion();
21609        final Rect db = dr.getBounds();
21610        final AttachInfo attachInfo = mAttachInfo;
21611        if (r != null && attachInfo != null) {
21612            final int w = getRight()-getLeft();
21613            final int h = getBottom()-getTop();
21614            if (db.left > 0) {
21615                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
21616                r.op(0, 0, db.left, h, Region.Op.UNION);
21617            }
21618            if (db.right < w) {
21619                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
21620                r.op(db.right, 0, w, h, Region.Op.UNION);
21621            }
21622            if (db.top > 0) {
21623                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
21624                r.op(0, 0, w, db.top, Region.Op.UNION);
21625            }
21626            if (db.bottom < h) {
21627                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
21628                r.op(0, db.bottom, w, h, Region.Op.UNION);
21629            }
21630            final int[] location = attachInfo.mTransparentLocation;
21631            getLocationInWindow(location);
21632            r.translate(location[0], location[1]);
21633            region.op(r, Region.Op.INTERSECT);
21634        } else {
21635            region.op(db, Region.Op.DIFFERENCE);
21636        }
21637    }
21638
21639    private void checkForLongClick(int delayOffset, float x, float y) {
21640        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
21641            mHasPerformedLongPress = false;
21642
21643            if (mPendingCheckForLongPress == null) {
21644                mPendingCheckForLongPress = new CheckForLongPress();
21645            }
21646            mPendingCheckForLongPress.setAnchor(x, y);
21647            mPendingCheckForLongPress.rememberWindowAttachCount();
21648            mPendingCheckForLongPress.rememberPressedState();
21649            postDelayed(mPendingCheckForLongPress,
21650                    ViewConfiguration.getLongPressTimeout() - delayOffset);
21651        }
21652    }
21653
21654    /**
21655     * Inflate a view from an XML resource.  This convenience method wraps the {@link
21656     * LayoutInflater} class, which provides a full range of options for view inflation.
21657     *
21658     * @param context The Context object for your activity or application.
21659     * @param resource The resource ID to inflate
21660     * @param root A view group that will be the parent.  Used to properly inflate the
21661     * layout_* parameters.
21662     * @see LayoutInflater
21663     */
21664    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
21665        LayoutInflater factory = LayoutInflater.from(context);
21666        return factory.inflate(resource, root);
21667    }
21668
21669    /**
21670     * Scroll the view with standard behavior for scrolling beyond the normal
21671     * content boundaries. Views that call this method should override
21672     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
21673     * results of an over-scroll operation.
21674     *
21675     * Views can use this method to handle any touch or fling-based scrolling.
21676     *
21677     * @param deltaX Change in X in pixels
21678     * @param deltaY Change in Y in pixels
21679     * @param scrollX Current X scroll value in pixels before applying deltaX
21680     * @param scrollY Current Y scroll value in pixels before applying deltaY
21681     * @param scrollRangeX Maximum content scroll range along the X axis
21682     * @param scrollRangeY Maximum content scroll range along the Y axis
21683     * @param maxOverScrollX Number of pixels to overscroll by in either direction
21684     *          along the X axis.
21685     * @param maxOverScrollY Number of pixels to overscroll by in either direction
21686     *          along the Y axis.
21687     * @param isTouchEvent true if this scroll operation is the result of a touch event.
21688     * @return true if scrolling was clamped to an over-scroll boundary along either
21689     *          axis, false otherwise.
21690     */
21691    @SuppressWarnings({"UnusedParameters"})
21692    protected boolean overScrollBy(int deltaX, int deltaY,
21693            int scrollX, int scrollY,
21694            int scrollRangeX, int scrollRangeY,
21695            int maxOverScrollX, int maxOverScrollY,
21696            boolean isTouchEvent) {
21697        final int overScrollMode = mOverScrollMode;
21698        final boolean canScrollHorizontal =
21699                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
21700        final boolean canScrollVertical =
21701                computeVerticalScrollRange() > computeVerticalScrollExtent();
21702        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
21703                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
21704        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
21705                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
21706
21707        int newScrollX = scrollX + deltaX;
21708        if (!overScrollHorizontal) {
21709            maxOverScrollX = 0;
21710        }
21711
21712        int newScrollY = scrollY + deltaY;
21713        if (!overScrollVertical) {
21714            maxOverScrollY = 0;
21715        }
21716
21717        // Clamp values if at the limits and record
21718        final int left = -maxOverScrollX;
21719        final int right = maxOverScrollX + scrollRangeX;
21720        final int top = -maxOverScrollY;
21721        final int bottom = maxOverScrollY + scrollRangeY;
21722
21723        boolean clampedX = false;
21724        if (newScrollX > right) {
21725            newScrollX = right;
21726            clampedX = true;
21727        } else if (newScrollX < left) {
21728            newScrollX = left;
21729            clampedX = true;
21730        }
21731
21732        boolean clampedY = false;
21733        if (newScrollY > bottom) {
21734            newScrollY = bottom;
21735            clampedY = true;
21736        } else if (newScrollY < top) {
21737            newScrollY = top;
21738            clampedY = true;
21739        }
21740
21741        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
21742
21743        return clampedX || clampedY;
21744    }
21745
21746    /**
21747     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
21748     * respond to the results of an over-scroll operation.
21749     *
21750     * @param scrollX New X scroll value in pixels
21751     * @param scrollY New Y scroll value in pixels
21752     * @param clampedX True if scrollX was clamped to an over-scroll boundary
21753     * @param clampedY True if scrollY was clamped to an over-scroll boundary
21754     */
21755    protected void onOverScrolled(int scrollX, int scrollY,
21756            boolean clampedX, boolean clampedY) {
21757        // Intentionally empty.
21758    }
21759
21760    /**
21761     * Returns the over-scroll mode for this view. The result will be
21762     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21763     * (allow over-scrolling only if the view content is larger than the container),
21764     * or {@link #OVER_SCROLL_NEVER}.
21765     *
21766     * @return This view's over-scroll mode.
21767     */
21768    public int getOverScrollMode() {
21769        return mOverScrollMode;
21770    }
21771
21772    /**
21773     * Set the over-scroll mode for this view. Valid over-scroll modes are
21774     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21775     * (allow over-scrolling only if the view content is larger than the container),
21776     * or {@link #OVER_SCROLL_NEVER}.
21777     *
21778     * Setting the over-scroll mode of a view will have an effect only if the
21779     * view is capable of scrolling.
21780     *
21781     * @param overScrollMode The new over-scroll mode for this view.
21782     */
21783    public void setOverScrollMode(int overScrollMode) {
21784        if (overScrollMode != OVER_SCROLL_ALWAYS &&
21785                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
21786                overScrollMode != OVER_SCROLL_NEVER) {
21787            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
21788        }
21789        mOverScrollMode = overScrollMode;
21790    }
21791
21792    /**
21793     * Enable or disable nested scrolling for this view.
21794     *
21795     * <p>If this property is set to true the view will be permitted to initiate nested
21796     * scrolling operations with a compatible parent view in the current hierarchy. If this
21797     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
21798     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
21799     * the nested scroll.</p>
21800     *
21801     * @param enabled true to enable nested scrolling, false to disable
21802     *
21803     * @see #isNestedScrollingEnabled()
21804     */
21805    public void setNestedScrollingEnabled(boolean enabled) {
21806        if (enabled) {
21807            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
21808        } else {
21809            stopNestedScroll();
21810            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
21811        }
21812    }
21813
21814    /**
21815     * Returns true if nested scrolling is enabled for this view.
21816     *
21817     * <p>If nested scrolling is enabled and this View class implementation supports it,
21818     * this view will act as a nested scrolling child view when applicable, forwarding data
21819     * about the scroll operation in progress to a compatible and cooperating nested scrolling
21820     * parent.</p>
21821     *
21822     * @return true if nested scrolling is enabled
21823     *
21824     * @see #setNestedScrollingEnabled(boolean)
21825     */
21826    public boolean isNestedScrollingEnabled() {
21827        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
21828                PFLAG3_NESTED_SCROLLING_ENABLED;
21829    }
21830
21831    /**
21832     * Begin a nestable scroll operation along the given axes.
21833     *
21834     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
21835     *
21836     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
21837     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
21838     * In the case of touch scrolling the nested scroll will be terminated automatically in
21839     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
21840     * In the event of programmatic scrolling the caller must explicitly call
21841     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
21842     *
21843     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
21844     * If it returns false the caller may ignore the rest of this contract until the next scroll.
21845     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
21846     *
21847     * <p>At each incremental step of the scroll the caller should invoke
21848     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
21849     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
21850     * parent at least partially consumed the scroll and the caller should adjust the amount it
21851     * scrolls by.</p>
21852     *
21853     * <p>After applying the remainder of the scroll delta the caller should invoke
21854     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
21855     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
21856     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
21857     * </p>
21858     *
21859     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
21860     *             {@link #SCROLL_AXIS_VERTICAL}.
21861     * @return true if a cooperative parent was found and nested scrolling has been enabled for
21862     *         the current gesture.
21863     *
21864     * @see #stopNestedScroll()
21865     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21866     * @see #dispatchNestedScroll(int, int, int, int, int[])
21867     */
21868    public boolean startNestedScroll(int axes) {
21869        if (hasNestedScrollingParent()) {
21870            // Already in progress
21871            return true;
21872        }
21873        if (isNestedScrollingEnabled()) {
21874            ViewParent p = getParent();
21875            View child = this;
21876            while (p != null) {
21877                try {
21878                    if (p.onStartNestedScroll(child, this, axes)) {
21879                        mNestedScrollingParent = p;
21880                        p.onNestedScrollAccepted(child, this, axes);
21881                        return true;
21882                    }
21883                } catch (AbstractMethodError e) {
21884                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
21885                            "method onStartNestedScroll", e);
21886                    // Allow the search upward to continue
21887                }
21888                if (p instanceof View) {
21889                    child = (View) p;
21890                }
21891                p = p.getParent();
21892            }
21893        }
21894        return false;
21895    }
21896
21897    /**
21898     * Stop a nested scroll in progress.
21899     *
21900     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
21901     *
21902     * @see #startNestedScroll(int)
21903     */
21904    public void stopNestedScroll() {
21905        if (mNestedScrollingParent != null) {
21906            mNestedScrollingParent.onStopNestedScroll(this);
21907            mNestedScrollingParent = null;
21908        }
21909    }
21910
21911    /**
21912     * Returns true if this view has a nested scrolling parent.
21913     *
21914     * <p>The presence of a nested scrolling parent indicates that this view has initiated
21915     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
21916     *
21917     * @return whether this view has a nested scrolling parent
21918     */
21919    public boolean hasNestedScrollingParent() {
21920        return mNestedScrollingParent != null;
21921    }
21922
21923    /**
21924     * Dispatch one step of a nested scroll in progress.
21925     *
21926     * <p>Implementations of views that support nested scrolling should call this to report
21927     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
21928     * is not currently in progress or nested scrolling is not
21929     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
21930     *
21931     * <p>Compatible View implementations should also call
21932     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
21933     * consuming a component of the scroll event themselves.</p>
21934     *
21935     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
21936     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
21937     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
21938     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
21939     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21940     *                       in local view coordinates of this view from before this operation
21941     *                       to after it completes. View implementations may use this to adjust
21942     *                       expected input coordinate tracking.
21943     * @return true if the event was dispatched, false if it could not be dispatched.
21944     * @see #dispatchNestedPreScroll(int, int, int[], int[])
21945     */
21946    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
21947            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
21948        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21949            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
21950                int startX = 0;
21951                int startY = 0;
21952                if (offsetInWindow != null) {
21953                    getLocationInWindow(offsetInWindow);
21954                    startX = offsetInWindow[0];
21955                    startY = offsetInWindow[1];
21956                }
21957
21958                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
21959                        dxUnconsumed, dyUnconsumed);
21960
21961                if (offsetInWindow != null) {
21962                    getLocationInWindow(offsetInWindow);
21963                    offsetInWindow[0] -= startX;
21964                    offsetInWindow[1] -= startY;
21965                }
21966                return true;
21967            } else if (offsetInWindow != null) {
21968                // No motion, no dispatch. Keep offsetInWindow up to date.
21969                offsetInWindow[0] = 0;
21970                offsetInWindow[1] = 0;
21971            }
21972        }
21973        return false;
21974    }
21975
21976    /**
21977     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
21978     *
21979     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
21980     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
21981     * scrolling operation to consume some or all of the scroll operation before the child view
21982     * consumes it.</p>
21983     *
21984     * @param dx Horizontal scroll distance in pixels
21985     * @param dy Vertical scroll distance in pixels
21986     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
21987     *                 and consumed[1] the consumed dy.
21988     * @param offsetInWindow Optional. If not null, on return this will contain the offset
21989     *                       in local view coordinates of this view from before this operation
21990     *                       to after it completes. View implementations may use this to adjust
21991     *                       expected input coordinate tracking.
21992     * @return true if the parent consumed some or all of the scroll delta
21993     * @see #dispatchNestedScroll(int, int, int, int, int[])
21994     */
21995    public boolean dispatchNestedPreScroll(int dx, int dy,
21996            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
21997        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
21998            if (dx != 0 || dy != 0) {
21999                int startX = 0;
22000                int startY = 0;
22001                if (offsetInWindow != null) {
22002                    getLocationInWindow(offsetInWindow);
22003                    startX = offsetInWindow[0];
22004                    startY = offsetInWindow[1];
22005                }
22006
22007                if (consumed == null) {
22008                    if (mTempNestedScrollConsumed == null) {
22009                        mTempNestedScrollConsumed = new int[2];
22010                    }
22011                    consumed = mTempNestedScrollConsumed;
22012                }
22013                consumed[0] = 0;
22014                consumed[1] = 0;
22015                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
22016
22017                if (offsetInWindow != null) {
22018                    getLocationInWindow(offsetInWindow);
22019                    offsetInWindow[0] -= startX;
22020                    offsetInWindow[1] -= startY;
22021                }
22022                return consumed[0] != 0 || consumed[1] != 0;
22023            } else if (offsetInWindow != null) {
22024                offsetInWindow[0] = 0;
22025                offsetInWindow[1] = 0;
22026            }
22027        }
22028        return false;
22029    }
22030
22031    /**
22032     * Dispatch a fling to a nested scrolling parent.
22033     *
22034     * <p>This method should be used to indicate that a nested scrolling child has detected
22035     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
22036     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
22037     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
22038     * along a scrollable axis.</p>
22039     *
22040     * <p>If a nested scrolling child view would normally fling but it is at the edge of
22041     * its own content, it can use this method to delegate the fling to its nested scrolling
22042     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
22043     *
22044     * @param velocityX Horizontal fling velocity in pixels per second
22045     * @param velocityY Vertical fling velocity in pixels per second
22046     * @param consumed true if the child consumed the fling, false otherwise
22047     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
22048     */
22049    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
22050        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22051            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
22052        }
22053        return false;
22054    }
22055
22056    /**
22057     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
22058     *
22059     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
22060     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
22061     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
22062     * before the child view consumes it. If this method returns <code>true</code>, a nested
22063     * parent view consumed the fling and this view should not scroll as a result.</p>
22064     *
22065     * <p>For a better user experience, only one view in a nested scrolling chain should consume
22066     * the fling at a time. If a parent view consumed the fling this method will return false.
22067     * Custom view implementations should account for this in two ways:</p>
22068     *
22069     * <ul>
22070     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
22071     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
22072     *     position regardless.</li>
22073     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
22074     *     even to settle back to a valid idle position.</li>
22075     * </ul>
22076     *
22077     * <p>Views should also not offer fling velocities to nested parent views along an axis
22078     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
22079     * should not offer a horizontal fling velocity to its parents since scrolling along that
22080     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
22081     *
22082     * @param velocityX Horizontal fling velocity in pixels per second
22083     * @param velocityY Vertical fling velocity in pixels per second
22084     * @return true if a nested scrolling parent consumed the fling
22085     */
22086    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
22087        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22088            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
22089        }
22090        return false;
22091    }
22092
22093    /**
22094     * Gets a scale factor that determines the distance the view should scroll
22095     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
22096     * @return The vertical scroll scale factor.
22097     * @hide
22098     */
22099    protected float getVerticalScrollFactor() {
22100        if (mVerticalScrollFactor == 0) {
22101            TypedValue outValue = new TypedValue();
22102            if (!mContext.getTheme().resolveAttribute(
22103                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
22104                throw new IllegalStateException(
22105                        "Expected theme to define listPreferredItemHeight.");
22106            }
22107            mVerticalScrollFactor = outValue.getDimension(
22108                    mContext.getResources().getDisplayMetrics());
22109        }
22110        return mVerticalScrollFactor;
22111    }
22112
22113    /**
22114     * Gets a scale factor that determines the distance the view should scroll
22115     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
22116     * @return The horizontal scroll scale factor.
22117     * @hide
22118     */
22119    protected float getHorizontalScrollFactor() {
22120        // TODO: Should use something else.
22121        return getVerticalScrollFactor();
22122    }
22123
22124    /**
22125     * Return the value specifying the text direction or policy that was set with
22126     * {@link #setTextDirection(int)}.
22127     *
22128     * @return the defined text direction. It can be one of:
22129     *
22130     * {@link #TEXT_DIRECTION_INHERIT},
22131     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22132     * {@link #TEXT_DIRECTION_ANY_RTL},
22133     * {@link #TEXT_DIRECTION_LTR},
22134     * {@link #TEXT_DIRECTION_RTL},
22135     * {@link #TEXT_DIRECTION_LOCALE},
22136     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22137     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
22138     *
22139     * @attr ref android.R.styleable#View_textDirection
22140     *
22141     * @hide
22142     */
22143    @ViewDebug.ExportedProperty(category = "text", mapping = {
22144            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
22145            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
22146            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
22147            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
22148            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
22149            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
22150            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
22151            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
22152    })
22153    public int getRawTextDirection() {
22154        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
22155    }
22156
22157    /**
22158     * Set the text direction.
22159     *
22160     * @param textDirection the direction to set. Should be one of:
22161     *
22162     * {@link #TEXT_DIRECTION_INHERIT},
22163     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22164     * {@link #TEXT_DIRECTION_ANY_RTL},
22165     * {@link #TEXT_DIRECTION_LTR},
22166     * {@link #TEXT_DIRECTION_RTL},
22167     * {@link #TEXT_DIRECTION_LOCALE}
22168     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22169     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
22170     *
22171     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
22172     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
22173     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
22174     *
22175     * @attr ref android.R.styleable#View_textDirection
22176     */
22177    public void setTextDirection(int textDirection) {
22178        if (getRawTextDirection() != textDirection) {
22179            // Reset the current text direction and the resolved one
22180            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
22181            resetResolvedTextDirection();
22182            // Set the new text direction
22183            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
22184            // Do resolution
22185            resolveTextDirection();
22186            // Notify change
22187            onRtlPropertiesChanged(getLayoutDirection());
22188            // Refresh
22189            requestLayout();
22190            invalidate(true);
22191        }
22192    }
22193
22194    /**
22195     * Return the resolved text direction.
22196     *
22197     * @return the resolved text direction. Returns one of:
22198     *
22199     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22200     * {@link #TEXT_DIRECTION_ANY_RTL},
22201     * {@link #TEXT_DIRECTION_LTR},
22202     * {@link #TEXT_DIRECTION_RTL},
22203     * {@link #TEXT_DIRECTION_LOCALE},
22204     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22205     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
22206     *
22207     * @attr ref android.R.styleable#View_textDirection
22208     */
22209    @ViewDebug.ExportedProperty(category = "text", mapping = {
22210            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
22211            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
22212            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
22213            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
22214            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
22215            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
22216            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
22217            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
22218    })
22219    public int getTextDirection() {
22220        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
22221    }
22222
22223    /**
22224     * Resolve the text direction.
22225     *
22226     * @return true if resolution has been done, false otherwise.
22227     *
22228     * @hide
22229     */
22230    public boolean resolveTextDirection() {
22231        // Reset any previous text direction resolution
22232        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
22233
22234        if (hasRtlSupport()) {
22235            // Set resolved text direction flag depending on text direction flag
22236            final int textDirection = getRawTextDirection();
22237            switch(textDirection) {
22238                case TEXT_DIRECTION_INHERIT:
22239                    if (!canResolveTextDirection()) {
22240                        // We cannot do the resolution if there is no parent, so use the default one
22241                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22242                        // Resolution will need to happen again later
22243                        return false;
22244                    }
22245
22246                    // Parent has not yet resolved, so we still return the default
22247                    try {
22248                        if (!mParent.isTextDirectionResolved()) {
22249                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22250                            // Resolution will need to happen again later
22251                            return false;
22252                        }
22253                    } catch (AbstractMethodError e) {
22254                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22255                                " does not fully implement ViewParent", e);
22256                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
22257                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22258                        return true;
22259                    }
22260
22261                    // Set current resolved direction to the same value as the parent's one
22262                    int parentResolvedDirection;
22263                    try {
22264                        parentResolvedDirection = mParent.getTextDirection();
22265                    } catch (AbstractMethodError e) {
22266                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22267                                " does not fully implement ViewParent", e);
22268                        parentResolvedDirection = TEXT_DIRECTION_LTR;
22269                    }
22270                    switch (parentResolvedDirection) {
22271                        case TEXT_DIRECTION_FIRST_STRONG:
22272                        case TEXT_DIRECTION_ANY_RTL:
22273                        case TEXT_DIRECTION_LTR:
22274                        case TEXT_DIRECTION_RTL:
22275                        case TEXT_DIRECTION_LOCALE:
22276                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
22277                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
22278                            mPrivateFlags2 |=
22279                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
22280                            break;
22281                        default:
22282                            // Default resolved direction is "first strong" heuristic
22283                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22284                    }
22285                    break;
22286                case TEXT_DIRECTION_FIRST_STRONG:
22287                case TEXT_DIRECTION_ANY_RTL:
22288                case TEXT_DIRECTION_LTR:
22289                case TEXT_DIRECTION_RTL:
22290                case TEXT_DIRECTION_LOCALE:
22291                case TEXT_DIRECTION_FIRST_STRONG_LTR:
22292                case TEXT_DIRECTION_FIRST_STRONG_RTL:
22293                    // Resolved direction is the same as text direction
22294                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
22295                    break;
22296                default:
22297                    // Default resolved direction is "first strong" heuristic
22298                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22299            }
22300        } else {
22301            // Default resolved direction is "first strong" heuristic
22302            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22303        }
22304
22305        // Set to resolved
22306        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
22307        return true;
22308    }
22309
22310    /**
22311     * Check if text direction resolution can be done.
22312     *
22313     * @return true if text direction resolution can be done otherwise return false.
22314     */
22315    public boolean canResolveTextDirection() {
22316        switch (getRawTextDirection()) {
22317            case TEXT_DIRECTION_INHERIT:
22318                if (mParent != null) {
22319                    try {
22320                        return mParent.canResolveTextDirection();
22321                    } catch (AbstractMethodError e) {
22322                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22323                                " does not fully implement ViewParent", e);
22324                    }
22325                }
22326                return false;
22327
22328            default:
22329                return true;
22330        }
22331    }
22332
22333    /**
22334     * Reset resolved text direction. Text direction will be resolved during a call to
22335     * {@link #onMeasure(int, int)}.
22336     *
22337     * @hide
22338     */
22339    public void resetResolvedTextDirection() {
22340        // Reset any previous text direction resolution
22341        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
22342        // Set to default value
22343        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22344    }
22345
22346    /**
22347     * @return true if text direction is inherited.
22348     *
22349     * @hide
22350     */
22351    public boolean isTextDirectionInherited() {
22352        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
22353    }
22354
22355    /**
22356     * @return true if text direction is resolved.
22357     */
22358    public boolean isTextDirectionResolved() {
22359        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
22360    }
22361
22362    /**
22363     * Return the value specifying the text alignment or policy that was set with
22364     * {@link #setTextAlignment(int)}.
22365     *
22366     * @return the defined text alignment. It can be one of:
22367     *
22368     * {@link #TEXT_ALIGNMENT_INHERIT},
22369     * {@link #TEXT_ALIGNMENT_GRAVITY},
22370     * {@link #TEXT_ALIGNMENT_CENTER},
22371     * {@link #TEXT_ALIGNMENT_TEXT_START},
22372     * {@link #TEXT_ALIGNMENT_TEXT_END},
22373     * {@link #TEXT_ALIGNMENT_VIEW_START},
22374     * {@link #TEXT_ALIGNMENT_VIEW_END}
22375     *
22376     * @attr ref android.R.styleable#View_textAlignment
22377     *
22378     * @hide
22379     */
22380    @ViewDebug.ExportedProperty(category = "text", mapping = {
22381            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
22382            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
22383            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
22384            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
22385            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
22386            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
22387            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
22388    })
22389    @TextAlignment
22390    public int getRawTextAlignment() {
22391        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
22392    }
22393
22394    /**
22395     * Set the text alignment.
22396     *
22397     * @param textAlignment The text alignment to set. Should be one of
22398     *
22399     * {@link #TEXT_ALIGNMENT_INHERIT},
22400     * {@link #TEXT_ALIGNMENT_GRAVITY},
22401     * {@link #TEXT_ALIGNMENT_CENTER},
22402     * {@link #TEXT_ALIGNMENT_TEXT_START},
22403     * {@link #TEXT_ALIGNMENT_TEXT_END},
22404     * {@link #TEXT_ALIGNMENT_VIEW_START},
22405     * {@link #TEXT_ALIGNMENT_VIEW_END}
22406     *
22407     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
22408     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
22409     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
22410     *
22411     * @attr ref android.R.styleable#View_textAlignment
22412     */
22413    public void setTextAlignment(@TextAlignment int textAlignment) {
22414        if (textAlignment != getRawTextAlignment()) {
22415            // Reset the current and resolved text alignment
22416            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
22417            resetResolvedTextAlignment();
22418            // Set the new text alignment
22419            mPrivateFlags2 |=
22420                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
22421            // Do resolution
22422            resolveTextAlignment();
22423            // Notify change
22424            onRtlPropertiesChanged(getLayoutDirection());
22425            // Refresh
22426            requestLayout();
22427            invalidate(true);
22428        }
22429    }
22430
22431    /**
22432     * Return the resolved text alignment.
22433     *
22434     * @return the resolved text alignment. Returns one of:
22435     *
22436     * {@link #TEXT_ALIGNMENT_GRAVITY},
22437     * {@link #TEXT_ALIGNMENT_CENTER},
22438     * {@link #TEXT_ALIGNMENT_TEXT_START},
22439     * {@link #TEXT_ALIGNMENT_TEXT_END},
22440     * {@link #TEXT_ALIGNMENT_VIEW_START},
22441     * {@link #TEXT_ALIGNMENT_VIEW_END}
22442     *
22443     * @attr ref android.R.styleable#View_textAlignment
22444     */
22445    @ViewDebug.ExportedProperty(category = "text", mapping = {
22446            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
22447            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
22448            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
22449            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
22450            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
22451            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
22452            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
22453    })
22454    @TextAlignment
22455    public int getTextAlignment() {
22456        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
22457                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
22458    }
22459
22460    /**
22461     * Resolve the text alignment.
22462     *
22463     * @return true if resolution has been done, false otherwise.
22464     *
22465     * @hide
22466     */
22467    public boolean resolveTextAlignment() {
22468        // Reset any previous text alignment resolution
22469        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
22470
22471        if (hasRtlSupport()) {
22472            // Set resolved text alignment flag depending on text alignment flag
22473            final int textAlignment = getRawTextAlignment();
22474            switch (textAlignment) {
22475                case TEXT_ALIGNMENT_INHERIT:
22476                    // Check if we can resolve the text alignment
22477                    if (!canResolveTextAlignment()) {
22478                        // We cannot do the resolution if there is no parent so use the default
22479                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22480                        // Resolution will need to happen again later
22481                        return false;
22482                    }
22483
22484                    // Parent has not yet resolved, so we still return the default
22485                    try {
22486                        if (!mParent.isTextAlignmentResolved()) {
22487                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22488                            // Resolution will need to happen again later
22489                            return false;
22490                        }
22491                    } catch (AbstractMethodError e) {
22492                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22493                                " does not fully implement ViewParent", e);
22494                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
22495                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22496                        return true;
22497                    }
22498
22499                    int parentResolvedTextAlignment;
22500                    try {
22501                        parentResolvedTextAlignment = mParent.getTextAlignment();
22502                    } catch (AbstractMethodError e) {
22503                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22504                                " does not fully implement ViewParent", e);
22505                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
22506                    }
22507                    switch (parentResolvedTextAlignment) {
22508                        case TEXT_ALIGNMENT_GRAVITY:
22509                        case TEXT_ALIGNMENT_TEXT_START:
22510                        case TEXT_ALIGNMENT_TEXT_END:
22511                        case TEXT_ALIGNMENT_CENTER:
22512                        case TEXT_ALIGNMENT_VIEW_START:
22513                        case TEXT_ALIGNMENT_VIEW_END:
22514                            // Resolved text alignment is the same as the parent resolved
22515                            // text alignment
22516                            mPrivateFlags2 |=
22517                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
22518                            break;
22519                        default:
22520                            // Use default resolved text alignment
22521                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22522                    }
22523                    break;
22524                case TEXT_ALIGNMENT_GRAVITY:
22525                case TEXT_ALIGNMENT_TEXT_START:
22526                case TEXT_ALIGNMENT_TEXT_END:
22527                case TEXT_ALIGNMENT_CENTER:
22528                case TEXT_ALIGNMENT_VIEW_START:
22529                case TEXT_ALIGNMENT_VIEW_END:
22530                    // Resolved text alignment is the same as text alignment
22531                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
22532                    break;
22533                default:
22534                    // Use default resolved text alignment
22535                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22536            }
22537        } else {
22538            // Use default resolved text alignment
22539            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22540        }
22541
22542        // Set the resolved
22543        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
22544        return true;
22545    }
22546
22547    /**
22548     * Check if text alignment resolution can be done.
22549     *
22550     * @return true if text alignment resolution can be done otherwise return false.
22551     */
22552    public boolean canResolveTextAlignment() {
22553        switch (getRawTextAlignment()) {
22554            case TEXT_DIRECTION_INHERIT:
22555                if (mParent != null) {
22556                    try {
22557                        return mParent.canResolveTextAlignment();
22558                    } catch (AbstractMethodError e) {
22559                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22560                                " does not fully implement ViewParent", e);
22561                    }
22562                }
22563                return false;
22564
22565            default:
22566                return true;
22567        }
22568    }
22569
22570    /**
22571     * Reset resolved text alignment. Text alignment will be resolved during a call to
22572     * {@link #onMeasure(int, int)}.
22573     *
22574     * @hide
22575     */
22576    public void resetResolvedTextAlignment() {
22577        // Reset any previous text alignment resolution
22578        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
22579        // Set to default
22580        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22581    }
22582
22583    /**
22584     * @return true if text alignment is inherited.
22585     *
22586     * @hide
22587     */
22588    public boolean isTextAlignmentInherited() {
22589        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
22590    }
22591
22592    /**
22593     * @return true if text alignment is resolved.
22594     */
22595    public boolean isTextAlignmentResolved() {
22596        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
22597    }
22598
22599    /**
22600     * Generate a value suitable for use in {@link #setId(int)}.
22601     * This value will not collide with ID values generated at build time by aapt for R.id.
22602     *
22603     * @return a generated ID value
22604     */
22605    public static int generateViewId() {
22606        for (;;) {
22607            final int result = sNextGeneratedId.get();
22608            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
22609            int newValue = result + 1;
22610            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
22611            if (sNextGeneratedId.compareAndSet(result, newValue)) {
22612                return result;
22613            }
22614        }
22615    }
22616
22617    private static boolean isViewIdGenerated(int id) {
22618        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
22619    }
22620
22621    /**
22622     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
22623     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
22624     *                           a normal View or a ViewGroup with
22625     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
22626     * @hide
22627     */
22628    public void captureTransitioningViews(List<View> transitioningViews) {
22629        if (getVisibility() == View.VISIBLE) {
22630            transitioningViews.add(this);
22631        }
22632    }
22633
22634    /**
22635     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
22636     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
22637     * @hide
22638     */
22639    public void findNamedViews(Map<String, View> namedElements) {
22640        if (getVisibility() == VISIBLE || mGhostView != null) {
22641            String transitionName = getTransitionName();
22642            if (transitionName != null) {
22643                namedElements.put(transitionName, this);
22644            }
22645        }
22646    }
22647
22648    /**
22649     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
22650     * The default implementation does not care the location or event types, but some subclasses
22651     * may use it (such as WebViews).
22652     * @param event The MotionEvent from a mouse
22653     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
22654     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
22655     * @see PointerIcon
22656     */
22657    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
22658        final float x = event.getX(pointerIndex);
22659        final float y = event.getY(pointerIndex);
22660        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
22661            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
22662        }
22663        return mPointerIcon;
22664    }
22665
22666    /**
22667     * Set the pointer icon for the current view.
22668     * Passing {@code null} will restore the pointer icon to its default value.
22669     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
22670     */
22671    public void setPointerIcon(PointerIcon pointerIcon) {
22672        mPointerIcon = pointerIcon;
22673        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
22674            return;
22675        }
22676        try {
22677            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
22678        } catch (RemoteException e) {
22679        }
22680    }
22681
22682    /**
22683     * Gets the pointer icon for the current view.
22684     */
22685    public PointerIcon getPointerIcon() {
22686        return mPointerIcon;
22687    }
22688
22689    //
22690    // Properties
22691    //
22692    /**
22693     * A Property wrapper around the <code>alpha</code> functionality handled by the
22694     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
22695     */
22696    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
22697        @Override
22698        public void setValue(View object, float value) {
22699            object.setAlpha(value);
22700        }
22701
22702        @Override
22703        public Float get(View object) {
22704            return object.getAlpha();
22705        }
22706    };
22707
22708    /**
22709     * A Property wrapper around the <code>translationX</code> functionality handled by the
22710     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
22711     */
22712    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
22713        @Override
22714        public void setValue(View object, float value) {
22715            object.setTranslationX(value);
22716        }
22717
22718                @Override
22719        public Float get(View object) {
22720            return object.getTranslationX();
22721        }
22722    };
22723
22724    /**
22725     * A Property wrapper around the <code>translationY</code> functionality handled by the
22726     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
22727     */
22728    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
22729        @Override
22730        public void setValue(View object, float value) {
22731            object.setTranslationY(value);
22732        }
22733
22734        @Override
22735        public Float get(View object) {
22736            return object.getTranslationY();
22737        }
22738    };
22739
22740    /**
22741     * A Property wrapper around the <code>translationZ</code> functionality handled by the
22742     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
22743     */
22744    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
22745        @Override
22746        public void setValue(View object, float value) {
22747            object.setTranslationZ(value);
22748        }
22749
22750        @Override
22751        public Float get(View object) {
22752            return object.getTranslationZ();
22753        }
22754    };
22755
22756    /**
22757     * A Property wrapper around the <code>x</code> functionality handled by the
22758     * {@link View#setX(float)} and {@link View#getX()} methods.
22759     */
22760    public static final Property<View, Float> X = new FloatProperty<View>("x") {
22761        @Override
22762        public void setValue(View object, float value) {
22763            object.setX(value);
22764        }
22765
22766        @Override
22767        public Float get(View object) {
22768            return object.getX();
22769        }
22770    };
22771
22772    /**
22773     * A Property wrapper around the <code>y</code> functionality handled by the
22774     * {@link View#setY(float)} and {@link View#getY()} methods.
22775     */
22776    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
22777        @Override
22778        public void setValue(View object, float value) {
22779            object.setY(value);
22780        }
22781
22782        @Override
22783        public Float get(View object) {
22784            return object.getY();
22785        }
22786    };
22787
22788    /**
22789     * A Property wrapper around the <code>z</code> functionality handled by the
22790     * {@link View#setZ(float)} and {@link View#getZ()} methods.
22791     */
22792    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
22793        @Override
22794        public void setValue(View object, float value) {
22795            object.setZ(value);
22796        }
22797
22798        @Override
22799        public Float get(View object) {
22800            return object.getZ();
22801        }
22802    };
22803
22804    /**
22805     * A Property wrapper around the <code>rotation</code> functionality handled by the
22806     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
22807     */
22808    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
22809        @Override
22810        public void setValue(View object, float value) {
22811            object.setRotation(value);
22812        }
22813
22814        @Override
22815        public Float get(View object) {
22816            return object.getRotation();
22817        }
22818    };
22819
22820    /**
22821     * A Property wrapper around the <code>rotationX</code> functionality handled by the
22822     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
22823     */
22824    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
22825        @Override
22826        public void setValue(View object, float value) {
22827            object.setRotationX(value);
22828        }
22829
22830        @Override
22831        public Float get(View object) {
22832            return object.getRotationX();
22833        }
22834    };
22835
22836    /**
22837     * A Property wrapper around the <code>rotationY</code> functionality handled by the
22838     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
22839     */
22840    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
22841        @Override
22842        public void setValue(View object, float value) {
22843            object.setRotationY(value);
22844        }
22845
22846        @Override
22847        public Float get(View object) {
22848            return object.getRotationY();
22849        }
22850    };
22851
22852    /**
22853     * A Property wrapper around the <code>scaleX</code> functionality handled by the
22854     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
22855     */
22856    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
22857        @Override
22858        public void setValue(View object, float value) {
22859            object.setScaleX(value);
22860        }
22861
22862        @Override
22863        public Float get(View object) {
22864            return object.getScaleX();
22865        }
22866    };
22867
22868    /**
22869     * A Property wrapper around the <code>scaleY</code> functionality handled by the
22870     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
22871     */
22872    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
22873        @Override
22874        public void setValue(View object, float value) {
22875            object.setScaleY(value);
22876        }
22877
22878        @Override
22879        public Float get(View object) {
22880            return object.getScaleY();
22881        }
22882    };
22883
22884    /**
22885     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
22886     * Each MeasureSpec represents a requirement for either the width or the height.
22887     * A MeasureSpec is comprised of a size and a mode. There are three possible
22888     * modes:
22889     * <dl>
22890     * <dt>UNSPECIFIED</dt>
22891     * <dd>
22892     * The parent has not imposed any constraint on the child. It can be whatever size
22893     * it wants.
22894     * </dd>
22895     *
22896     * <dt>EXACTLY</dt>
22897     * <dd>
22898     * The parent has determined an exact size for the child. The child is going to be
22899     * given those bounds regardless of how big it wants to be.
22900     * </dd>
22901     *
22902     * <dt>AT_MOST</dt>
22903     * <dd>
22904     * The child can be as large as it wants up to the specified size.
22905     * </dd>
22906     * </dl>
22907     *
22908     * MeasureSpecs are implemented as ints to reduce object allocation. This class
22909     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
22910     */
22911    public static class MeasureSpec {
22912        private static final int MODE_SHIFT = 30;
22913        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
22914
22915        /** @hide */
22916        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
22917        @Retention(RetentionPolicy.SOURCE)
22918        public @interface MeasureSpecMode {}
22919
22920        /**
22921         * Measure specification mode: The parent has not imposed any constraint
22922         * on the child. It can be whatever size it wants.
22923         */
22924        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
22925
22926        /**
22927         * Measure specification mode: The parent has determined an exact size
22928         * for the child. The child is going to be given those bounds regardless
22929         * of how big it wants to be.
22930         */
22931        public static final int EXACTLY     = 1 << MODE_SHIFT;
22932
22933        /**
22934         * Measure specification mode: The child can be as large as it wants up
22935         * to the specified size.
22936         */
22937        public static final int AT_MOST     = 2 << MODE_SHIFT;
22938
22939        /**
22940         * Creates a measure specification based on the supplied size and mode.
22941         *
22942         * The mode must always be one of the following:
22943         * <ul>
22944         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
22945         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
22946         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
22947         * </ul>
22948         *
22949         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
22950         * implementation was such that the order of arguments did not matter
22951         * and overflow in either value could impact the resulting MeasureSpec.
22952         * {@link android.widget.RelativeLayout} was affected by this bug.
22953         * Apps targeting API levels greater than 17 will get the fixed, more strict
22954         * behavior.</p>
22955         *
22956         * @param size the size of the measure specification
22957         * @param mode the mode of the measure specification
22958         * @return the measure specification based on size and mode
22959         */
22960        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
22961                                          @MeasureSpecMode int mode) {
22962            if (sUseBrokenMakeMeasureSpec) {
22963                return size + mode;
22964            } else {
22965                return (size & ~MODE_MASK) | (mode & MODE_MASK);
22966            }
22967        }
22968
22969        /**
22970         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
22971         * will automatically get a size of 0. Older apps expect this.
22972         *
22973         * @hide internal use only for compatibility with system widgets and older apps
22974         */
22975        public static int makeSafeMeasureSpec(int size, int mode) {
22976            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
22977                return 0;
22978            }
22979            return makeMeasureSpec(size, mode);
22980        }
22981
22982        /**
22983         * Extracts the mode from the supplied measure specification.
22984         *
22985         * @param measureSpec the measure specification to extract the mode from
22986         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
22987         *         {@link android.view.View.MeasureSpec#AT_MOST} or
22988         *         {@link android.view.View.MeasureSpec#EXACTLY}
22989         */
22990        @MeasureSpecMode
22991        public static int getMode(int measureSpec) {
22992            //noinspection ResourceType
22993            return (measureSpec & MODE_MASK);
22994        }
22995
22996        /**
22997         * Extracts the size from the supplied measure specification.
22998         *
22999         * @param measureSpec the measure specification to extract the size from
23000         * @return the size in pixels defined in the supplied measure specification
23001         */
23002        public static int getSize(int measureSpec) {
23003            return (measureSpec & ~MODE_MASK);
23004        }
23005
23006        static int adjust(int measureSpec, int delta) {
23007            final int mode = getMode(measureSpec);
23008            int size = getSize(measureSpec);
23009            if (mode == UNSPECIFIED) {
23010                // No need to adjust size for UNSPECIFIED mode.
23011                return makeMeasureSpec(size, UNSPECIFIED);
23012            }
23013            size += delta;
23014            if (size < 0) {
23015                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
23016                        ") spec: " + toString(measureSpec) + " delta: " + delta);
23017                size = 0;
23018            }
23019            return makeMeasureSpec(size, mode);
23020        }
23021
23022        /**
23023         * Returns a String representation of the specified measure
23024         * specification.
23025         *
23026         * @param measureSpec the measure specification to convert to a String
23027         * @return a String with the following format: "MeasureSpec: MODE SIZE"
23028         */
23029        public static String toString(int measureSpec) {
23030            int mode = getMode(measureSpec);
23031            int size = getSize(measureSpec);
23032
23033            StringBuilder sb = new StringBuilder("MeasureSpec: ");
23034
23035            if (mode == UNSPECIFIED)
23036                sb.append("UNSPECIFIED ");
23037            else if (mode == EXACTLY)
23038                sb.append("EXACTLY ");
23039            else if (mode == AT_MOST)
23040                sb.append("AT_MOST ");
23041            else
23042                sb.append(mode).append(" ");
23043
23044            sb.append(size);
23045            return sb.toString();
23046        }
23047    }
23048
23049    private final class CheckForLongPress implements Runnable {
23050        private int mOriginalWindowAttachCount;
23051        private float mX;
23052        private float mY;
23053        private boolean mOriginalPressedState;
23054
23055        @Override
23056        public void run() {
23057            if ((mOriginalPressedState == isPressed()) && (mParent != null)
23058                    && mOriginalWindowAttachCount == mWindowAttachCount) {
23059                if (performLongClick(mX, mY)) {
23060                    mHasPerformedLongPress = true;
23061                }
23062            }
23063        }
23064
23065        public void setAnchor(float x, float y) {
23066            mX = x;
23067            mY = y;
23068        }
23069
23070        public void rememberWindowAttachCount() {
23071            mOriginalWindowAttachCount = mWindowAttachCount;
23072        }
23073
23074        public void rememberPressedState() {
23075            mOriginalPressedState = isPressed();
23076        }
23077    }
23078
23079    private final class CheckForTap implements Runnable {
23080        public float x;
23081        public float y;
23082
23083        @Override
23084        public void run() {
23085            mPrivateFlags &= ~PFLAG_PREPRESSED;
23086            setPressed(true, x, y);
23087            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
23088        }
23089    }
23090
23091    private final class PerformClick implements Runnable {
23092        @Override
23093        public void run() {
23094            performClick();
23095        }
23096    }
23097
23098    /**
23099     * This method returns a ViewPropertyAnimator object, which can be used to animate
23100     * specific properties on this View.
23101     *
23102     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
23103     */
23104    public ViewPropertyAnimator animate() {
23105        if (mAnimator == null) {
23106            mAnimator = new ViewPropertyAnimator(this);
23107        }
23108        return mAnimator;
23109    }
23110
23111    /**
23112     * Sets the name of the View to be used to identify Views in Transitions.
23113     * Names should be unique in the View hierarchy.
23114     *
23115     * @param transitionName The name of the View to uniquely identify it for Transitions.
23116     */
23117    public final void setTransitionName(String transitionName) {
23118        mTransitionName = transitionName;
23119    }
23120
23121    /**
23122     * Returns the name of the View to be used to identify Views in Transitions.
23123     * Names should be unique in the View hierarchy.
23124     *
23125     * <p>This returns null if the View has not been given a name.</p>
23126     *
23127     * @return The name used of the View to be used to identify Views in Transitions or null
23128     * if no name has been given.
23129     */
23130    @ViewDebug.ExportedProperty
23131    public String getTransitionName() {
23132        return mTransitionName;
23133    }
23134
23135    /**
23136     * @hide
23137     */
23138    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
23139        // Do nothing.
23140    }
23141
23142    /**
23143     * Interface definition for a callback to be invoked when a hardware key event is
23144     * dispatched to this view. The callback will be invoked before the key event is
23145     * given to the view. This is only useful for hardware keyboards; a software input
23146     * method has no obligation to trigger this listener.
23147     */
23148    public interface OnKeyListener {
23149        /**
23150         * Called when a hardware key is dispatched to a view. This allows listeners to
23151         * get a chance to respond before the target view.
23152         * <p>Key presses in software keyboards will generally NOT trigger this method,
23153         * although some may elect to do so in some situations. Do not assume a
23154         * software input method has to be key-based; even if it is, it may use key presses
23155         * in a different way than you expect, so there is no way to reliably catch soft
23156         * input key presses.
23157         *
23158         * @param v The view the key has been dispatched to.
23159         * @param keyCode The code for the physical key that was pressed
23160         * @param event The KeyEvent object containing full information about
23161         *        the event.
23162         * @return True if the listener has consumed the event, false otherwise.
23163         */
23164        boolean onKey(View v, int keyCode, KeyEvent event);
23165    }
23166
23167    /**
23168     * Interface definition for a callback to be invoked when a touch event is
23169     * dispatched to this view. The callback will be invoked before the touch
23170     * event is given to the view.
23171     */
23172    public interface OnTouchListener {
23173        /**
23174         * Called when a touch event is dispatched to a view. This allows listeners to
23175         * get a chance to respond before the target view.
23176         *
23177         * @param v The view the touch event has been dispatched to.
23178         * @param event The MotionEvent object containing full information about
23179         *        the event.
23180         * @return True if the listener has consumed the event, false otherwise.
23181         */
23182        boolean onTouch(View v, MotionEvent event);
23183    }
23184
23185    /**
23186     * Interface definition for a callback to be invoked when a hover event is
23187     * dispatched to this view. The callback will be invoked before the hover
23188     * event is given to the view.
23189     */
23190    public interface OnHoverListener {
23191        /**
23192         * Called when a hover event is dispatched to a view. This allows listeners to
23193         * get a chance to respond before the target view.
23194         *
23195         * @param v The view the hover event has been dispatched to.
23196         * @param event The MotionEvent object containing full information about
23197         *        the event.
23198         * @return True if the listener has consumed the event, false otherwise.
23199         */
23200        boolean onHover(View v, MotionEvent event);
23201    }
23202
23203    /**
23204     * Interface definition for a callback to be invoked when a generic motion event is
23205     * dispatched to this view. The callback will be invoked before the generic motion
23206     * event is given to the view.
23207     */
23208    public interface OnGenericMotionListener {
23209        /**
23210         * Called when a generic motion event is dispatched to a view. This allows listeners to
23211         * get a chance to respond before the target view.
23212         *
23213         * @param v The view the generic motion event has been dispatched to.
23214         * @param event The MotionEvent object containing full information about
23215         *        the event.
23216         * @return True if the listener has consumed the event, false otherwise.
23217         */
23218        boolean onGenericMotion(View v, MotionEvent event);
23219    }
23220
23221    /**
23222     * Interface definition for a callback to be invoked when a view has been clicked and held.
23223     */
23224    public interface OnLongClickListener {
23225        /**
23226         * Called when a view has been clicked and held.
23227         *
23228         * @param v The view that was clicked and held.
23229         *
23230         * @return true if the callback consumed the long click, false otherwise.
23231         */
23232        boolean onLongClick(View v);
23233    }
23234
23235    /**
23236     * Interface definition for a callback to be invoked when a drag is being dispatched
23237     * to this view.  The callback will be invoked before the hosting view's own
23238     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
23239     * onDrag(event) behavior, it should return 'false' from this callback.
23240     *
23241     * <div class="special reference">
23242     * <h3>Developer Guides</h3>
23243     * <p>For a guide to implementing drag and drop features, read the
23244     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
23245     * </div>
23246     */
23247    public interface OnDragListener {
23248        /**
23249         * Called when a drag event is dispatched to a view. This allows listeners
23250         * to get a chance to override base View behavior.
23251         *
23252         * @param v The View that received the drag event.
23253         * @param event The {@link android.view.DragEvent} object for the drag event.
23254         * @return {@code true} if the drag event was handled successfully, or {@code false}
23255         * if the drag event was not handled. Note that {@code false} will trigger the View
23256         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
23257         */
23258        boolean onDrag(View v, DragEvent event);
23259    }
23260
23261    /**
23262     * Interface definition for a callback to be invoked when the focus state of
23263     * a view changed.
23264     */
23265    public interface OnFocusChangeListener {
23266        /**
23267         * Called when the focus state of a view has changed.
23268         *
23269         * @param v The view whose state has changed.
23270         * @param hasFocus The new focus state of v.
23271         */
23272        void onFocusChange(View v, boolean hasFocus);
23273    }
23274
23275    /**
23276     * Interface definition for a callback to be invoked when a view is clicked.
23277     */
23278    public interface OnClickListener {
23279        /**
23280         * Called when a view has been clicked.
23281         *
23282         * @param v The view that was clicked.
23283         */
23284        void onClick(View v);
23285    }
23286
23287    /**
23288     * Interface definition for a callback to be invoked when a view is context clicked.
23289     */
23290    public interface OnContextClickListener {
23291        /**
23292         * Called when a view is context clicked.
23293         *
23294         * @param v The view that has been context clicked.
23295         * @return true if the callback consumed the context click, false otherwise.
23296         */
23297        boolean onContextClick(View v);
23298    }
23299
23300    /**
23301     * Interface definition for a callback to be invoked when the context menu
23302     * for this view is being built.
23303     */
23304    public interface OnCreateContextMenuListener {
23305        /**
23306         * Called when the context menu for this view is being built. It is not
23307         * safe to hold onto the menu after this method returns.
23308         *
23309         * @param menu The context menu that is being built
23310         * @param v The view for which the context menu is being built
23311         * @param menuInfo Extra information about the item for which the
23312         *            context menu should be shown. This information will vary
23313         *            depending on the class of v.
23314         */
23315        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
23316    }
23317
23318    /**
23319     * Interface definition for a callback to be invoked when the status bar changes
23320     * visibility.  This reports <strong>global</strong> changes to the system UI
23321     * state, not what the application is requesting.
23322     *
23323     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
23324     */
23325    public interface OnSystemUiVisibilityChangeListener {
23326        /**
23327         * Called when the status bar changes visibility because of a call to
23328         * {@link View#setSystemUiVisibility(int)}.
23329         *
23330         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
23331         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
23332         * This tells you the <strong>global</strong> state of these UI visibility
23333         * flags, not what your app is currently applying.
23334         */
23335        public void onSystemUiVisibilityChange(int visibility);
23336    }
23337
23338    /**
23339     * Interface definition for a callback to be invoked when this view is attached
23340     * or detached from its window.
23341     */
23342    public interface OnAttachStateChangeListener {
23343        /**
23344         * Called when the view is attached to a window.
23345         * @param v The view that was attached
23346         */
23347        public void onViewAttachedToWindow(View v);
23348        /**
23349         * Called when the view is detached from a window.
23350         * @param v The view that was detached
23351         */
23352        public void onViewDetachedFromWindow(View v);
23353    }
23354
23355    /**
23356     * Listener for applying window insets on a view in a custom way.
23357     *
23358     * <p>Apps may choose to implement this interface if they want to apply custom policy
23359     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
23360     * is set, its
23361     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
23362     * method will be called instead of the View's own
23363     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
23364     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
23365     * the View's normal behavior as part of its own.</p>
23366     */
23367    public interface OnApplyWindowInsetsListener {
23368        /**
23369         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
23370         * on a View, this listener method will be called instead of the view's own
23371         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
23372         *
23373         * @param v The view applying window insets
23374         * @param insets The insets to apply
23375         * @return The insets supplied, minus any insets that were consumed
23376         */
23377        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
23378    }
23379
23380    private final class UnsetPressedState implements Runnable {
23381        @Override
23382        public void run() {
23383            setPressed(false);
23384        }
23385    }
23386
23387    /**
23388     * Base class for derived classes that want to save and restore their own
23389     * state in {@link android.view.View#onSaveInstanceState()}.
23390     */
23391    public static class BaseSavedState extends AbsSavedState {
23392        String mStartActivityRequestWhoSaved;
23393
23394        /**
23395         * Constructor used when reading from a parcel. Reads the state of the superclass.
23396         *
23397         * @param source parcel to read from
23398         */
23399        public BaseSavedState(Parcel source) {
23400            this(source, null);
23401        }
23402
23403        /**
23404         * Constructor used when reading from a parcel using a given class loader.
23405         * Reads the state of the superclass.
23406         *
23407         * @param source parcel to read from
23408         * @param loader ClassLoader to use for reading
23409         */
23410        public BaseSavedState(Parcel source, ClassLoader loader) {
23411            super(source, loader);
23412            mStartActivityRequestWhoSaved = source.readString();
23413        }
23414
23415        /**
23416         * Constructor called by derived classes when creating their SavedState objects
23417         *
23418         * @param superState The state of the superclass of this view
23419         */
23420        public BaseSavedState(Parcelable superState) {
23421            super(superState);
23422        }
23423
23424        @Override
23425        public void writeToParcel(Parcel out, int flags) {
23426            super.writeToParcel(out, flags);
23427            out.writeString(mStartActivityRequestWhoSaved);
23428        }
23429
23430        public static final Parcelable.Creator<BaseSavedState> CREATOR
23431                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
23432            @Override
23433            public BaseSavedState createFromParcel(Parcel in) {
23434                return new BaseSavedState(in);
23435            }
23436
23437            @Override
23438            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
23439                return new BaseSavedState(in, loader);
23440            }
23441
23442            @Override
23443            public BaseSavedState[] newArray(int size) {
23444                return new BaseSavedState[size];
23445            }
23446        };
23447    }
23448
23449    /**
23450     * A set of information given to a view when it is attached to its parent
23451     * window.
23452     */
23453    final static class AttachInfo {
23454        interface Callbacks {
23455            void playSoundEffect(int effectId);
23456            boolean performHapticFeedback(int effectId, boolean always);
23457        }
23458
23459        /**
23460         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
23461         * to a Handler. This class contains the target (View) to invalidate and
23462         * the coordinates of the dirty rectangle.
23463         *
23464         * For performance purposes, this class also implements a pool of up to
23465         * POOL_LIMIT objects that get reused. This reduces memory allocations
23466         * whenever possible.
23467         */
23468        static class InvalidateInfo {
23469            private static final int POOL_LIMIT = 10;
23470
23471            private static final SynchronizedPool<InvalidateInfo> sPool =
23472                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
23473
23474            View target;
23475
23476            int left;
23477            int top;
23478            int right;
23479            int bottom;
23480
23481            public static InvalidateInfo obtain() {
23482                InvalidateInfo instance = sPool.acquire();
23483                return (instance != null) ? instance : new InvalidateInfo();
23484            }
23485
23486            public void recycle() {
23487                target = null;
23488                sPool.release(this);
23489            }
23490        }
23491
23492        final IWindowSession mSession;
23493
23494        final IWindow mWindow;
23495
23496        final IBinder mWindowToken;
23497
23498        final Display mDisplay;
23499
23500        final Callbacks mRootCallbacks;
23501
23502        IWindowId mIWindowId;
23503        WindowId mWindowId;
23504
23505        /**
23506         * The top view of the hierarchy.
23507         */
23508        View mRootView;
23509
23510        IBinder mPanelParentWindowToken;
23511
23512        boolean mHardwareAccelerated;
23513        boolean mHardwareAccelerationRequested;
23514        ThreadedRenderer mThreadedRenderer;
23515        List<RenderNode> mPendingAnimatingRenderNodes;
23516
23517        /**
23518         * The state of the display to which the window is attached, as reported
23519         * by {@link Display#getState()}.  Note that the display state constants
23520         * declared by {@link Display} do not exactly line up with the screen state
23521         * constants declared by {@link View} (there are more display states than
23522         * screen states).
23523         */
23524        int mDisplayState = Display.STATE_UNKNOWN;
23525
23526        /**
23527         * Scale factor used by the compatibility mode
23528         */
23529        float mApplicationScale;
23530
23531        /**
23532         * Indicates whether the application is in compatibility mode
23533         */
23534        boolean mScalingRequired;
23535
23536        /**
23537         * Left position of this view's window
23538         */
23539        int mWindowLeft;
23540
23541        /**
23542         * Top position of this view's window
23543         */
23544        int mWindowTop;
23545
23546        /**
23547         * Indicates whether views need to use 32-bit drawing caches
23548         */
23549        boolean mUse32BitDrawingCache;
23550
23551        /**
23552         * For windows that are full-screen but using insets to layout inside
23553         * of the screen areas, these are the current insets to appear inside
23554         * the overscan area of the display.
23555         */
23556        final Rect mOverscanInsets = new Rect();
23557
23558        /**
23559         * For windows that are full-screen but using insets to layout inside
23560         * of the screen decorations, these are the current insets for the
23561         * content of the window.
23562         */
23563        final Rect mContentInsets = new Rect();
23564
23565        /**
23566         * For windows that are full-screen but using insets to layout inside
23567         * of the screen decorations, these are the current insets for the
23568         * actual visible parts of the window.
23569         */
23570        final Rect mVisibleInsets = new Rect();
23571
23572        /**
23573         * For windows that are full-screen but using insets to layout inside
23574         * of the screen decorations, these are the current insets for the
23575         * stable system windows.
23576         */
23577        final Rect mStableInsets = new Rect();
23578
23579        /**
23580         * For windows that include areas that are not covered by real surface these are the outsets
23581         * for real surface.
23582         */
23583        final Rect mOutsets = new Rect();
23584
23585        /**
23586         * In multi-window we force show the navigation bar. Because we don't want that the surface
23587         * size changes in this mode, we instead have a flag whether the navigation bar size should
23588         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
23589         */
23590        boolean mAlwaysConsumeNavBar;
23591
23592        /**
23593         * The internal insets given by this window.  This value is
23594         * supplied by the client (through
23595         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
23596         * be given to the window manager when changed to be used in laying
23597         * out windows behind it.
23598         */
23599        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
23600                = new ViewTreeObserver.InternalInsetsInfo();
23601
23602        /**
23603         * Set to true when mGivenInternalInsets is non-empty.
23604         */
23605        boolean mHasNonEmptyGivenInternalInsets;
23606
23607        /**
23608         * All views in the window's hierarchy that serve as scroll containers,
23609         * used to determine if the window can be resized or must be panned
23610         * to adjust for a soft input area.
23611         */
23612        final ArrayList<View> mScrollContainers = new ArrayList<View>();
23613
23614        final KeyEvent.DispatcherState mKeyDispatchState
23615                = new KeyEvent.DispatcherState();
23616
23617        /**
23618         * Indicates whether the view's window currently has the focus.
23619         */
23620        boolean mHasWindowFocus;
23621
23622        /**
23623         * The current visibility of the window.
23624         */
23625        int mWindowVisibility;
23626
23627        /**
23628         * Indicates the time at which drawing started to occur.
23629         */
23630        long mDrawingTime;
23631
23632        /**
23633         * Indicates whether or not ignoring the DIRTY_MASK flags.
23634         */
23635        boolean mIgnoreDirtyState;
23636
23637        /**
23638         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
23639         * to avoid clearing that flag prematurely.
23640         */
23641        boolean mSetIgnoreDirtyState = false;
23642
23643        /**
23644         * Indicates whether the view's window is currently in touch mode.
23645         */
23646        boolean mInTouchMode;
23647
23648        /**
23649         * Indicates whether the view has requested unbuffered input dispatching for the current
23650         * event stream.
23651         */
23652        boolean mUnbufferedDispatchRequested;
23653
23654        /**
23655         * Indicates that ViewAncestor should trigger a global layout change
23656         * the next time it performs a traversal
23657         */
23658        boolean mRecomputeGlobalAttributes;
23659
23660        /**
23661         * Always report new attributes at next traversal.
23662         */
23663        boolean mForceReportNewAttributes;
23664
23665        /**
23666         * Set during a traveral if any views want to keep the screen on.
23667         */
23668        boolean mKeepScreenOn;
23669
23670        /**
23671         * Set during a traveral if the light center needs to be updated.
23672         */
23673        boolean mNeedsUpdateLightCenter;
23674
23675        /**
23676         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
23677         */
23678        int mSystemUiVisibility;
23679
23680        /**
23681         * Hack to force certain system UI visibility flags to be cleared.
23682         */
23683        int mDisabledSystemUiVisibility;
23684
23685        /**
23686         * Last global system UI visibility reported by the window manager.
23687         */
23688        int mGlobalSystemUiVisibility = -1;
23689
23690        /**
23691         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
23692         * attached.
23693         */
23694        boolean mHasSystemUiListeners;
23695
23696        /**
23697         * Set if the window has requested to extend into the overscan region
23698         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
23699         */
23700        boolean mOverscanRequested;
23701
23702        /**
23703         * Set if the visibility of any views has changed.
23704         */
23705        boolean mViewVisibilityChanged;
23706
23707        /**
23708         * Set to true if a view has been scrolled.
23709         */
23710        boolean mViewScrollChanged;
23711
23712        /**
23713         * Set to true if high contrast mode enabled
23714         */
23715        boolean mHighContrastText;
23716
23717        /**
23718         * Set to true if a pointer event is currently being handled.
23719         */
23720        boolean mHandlingPointerEvent;
23721
23722        /**
23723         * Global to the view hierarchy used as a temporary for dealing with
23724         * x/y points in the transparent region computations.
23725         */
23726        final int[] mTransparentLocation = new int[2];
23727
23728        /**
23729         * Global to the view hierarchy used as a temporary for dealing with
23730         * x/y points in the ViewGroup.invalidateChild implementation.
23731         */
23732        final int[] mInvalidateChildLocation = new int[2];
23733
23734        /**
23735         * Global to the view hierarchy used as a temporary for dealing with
23736         * computing absolute on-screen location.
23737         */
23738        final int[] mTmpLocation = new int[2];
23739
23740        /**
23741         * Global to the view hierarchy used as a temporary for dealing with
23742         * x/y location when view is transformed.
23743         */
23744        final float[] mTmpTransformLocation = new float[2];
23745
23746        /**
23747         * The view tree observer used to dispatch global events like
23748         * layout, pre-draw, touch mode change, etc.
23749         */
23750        final ViewTreeObserver mTreeObserver;
23751
23752        /**
23753         * A Canvas used by the view hierarchy to perform bitmap caching.
23754         */
23755        Canvas mCanvas;
23756
23757        /**
23758         * The view root impl.
23759         */
23760        final ViewRootImpl mViewRootImpl;
23761
23762        /**
23763         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
23764         * handler can be used to pump events in the UI events queue.
23765         */
23766        final Handler mHandler;
23767
23768        /**
23769         * Temporary for use in computing invalidate rectangles while
23770         * calling up the hierarchy.
23771         */
23772        final Rect mTmpInvalRect = new Rect();
23773
23774        /**
23775         * Temporary for use in computing hit areas with transformed views
23776         */
23777        final RectF mTmpTransformRect = new RectF();
23778
23779        /**
23780         * Temporary for use in computing hit areas with transformed views
23781         */
23782        final RectF mTmpTransformRect1 = new RectF();
23783
23784        /**
23785         * Temporary list of rectanges.
23786         */
23787        final List<RectF> mTmpRectList = new ArrayList<>();
23788
23789        /**
23790         * Temporary for use in transforming invalidation rect
23791         */
23792        final Matrix mTmpMatrix = new Matrix();
23793
23794        /**
23795         * Temporary for use in transforming invalidation rect
23796         */
23797        final Transformation mTmpTransformation = new Transformation();
23798
23799        /**
23800         * Temporary for use in querying outlines from OutlineProviders
23801         */
23802        final Outline mTmpOutline = new Outline();
23803
23804        /**
23805         * Temporary list for use in collecting focusable descendents of a view.
23806         */
23807        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
23808
23809        /**
23810         * The id of the window for accessibility purposes.
23811         */
23812        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
23813
23814        /**
23815         * Flags related to accessibility processing.
23816         *
23817         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
23818         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
23819         */
23820        int mAccessibilityFetchFlags;
23821
23822        /**
23823         * The drawable for highlighting accessibility focus.
23824         */
23825        Drawable mAccessibilityFocusDrawable;
23826
23827        /**
23828         * Show where the margins, bounds and layout bounds are for each view.
23829         */
23830        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
23831
23832        /**
23833         * Point used to compute visible regions.
23834         */
23835        final Point mPoint = new Point();
23836
23837        /**
23838         * Used to track which View originated a requestLayout() call, used when
23839         * requestLayout() is called during layout.
23840         */
23841        View mViewRequestingLayout;
23842
23843        /**
23844         * Used to track views that need (at least) a partial relayout at their current size
23845         * during the next traversal.
23846         */
23847        List<View> mPartialLayoutViews = new ArrayList<>();
23848
23849        /**
23850         * Swapped with mPartialLayoutViews during layout to avoid concurrent
23851         * modification. Lazily assigned during ViewRootImpl layout.
23852         */
23853        List<View> mEmptyPartialLayoutViews;
23854
23855        /**
23856         * Used to track the identity of the current drag operation.
23857         */
23858        IBinder mDragToken;
23859
23860        /**
23861         * The drag shadow surface for the current drag operation.
23862         */
23863        public Surface mDragSurface;
23864
23865
23866        /**
23867         * The view that currently has a tooltip displayed.
23868         */
23869        View mTooltipHost;
23870
23871        /**
23872         * Creates a new set of attachment information with the specified
23873         * events handler and thread.
23874         *
23875         * @param handler the events handler the view must use
23876         */
23877        AttachInfo(IWindowSession session, IWindow window, Display display,
23878                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
23879                Context context) {
23880            mSession = session;
23881            mWindow = window;
23882            mWindowToken = window.asBinder();
23883            mDisplay = display;
23884            mViewRootImpl = viewRootImpl;
23885            mHandler = handler;
23886            mRootCallbacks = effectPlayer;
23887            mTreeObserver = new ViewTreeObserver(context);
23888        }
23889    }
23890
23891    /**
23892     * <p>ScrollabilityCache holds various fields used by a View when scrolling
23893     * is supported. This avoids keeping too many unused fields in most
23894     * instances of View.</p>
23895     */
23896    private static class ScrollabilityCache implements Runnable {
23897
23898        /**
23899         * Scrollbars are not visible
23900         */
23901        public static final int OFF = 0;
23902
23903        /**
23904         * Scrollbars are visible
23905         */
23906        public static final int ON = 1;
23907
23908        /**
23909         * Scrollbars are fading away
23910         */
23911        public static final int FADING = 2;
23912
23913        public boolean fadeScrollBars;
23914
23915        public int fadingEdgeLength;
23916        public int scrollBarDefaultDelayBeforeFade;
23917        public int scrollBarFadeDuration;
23918
23919        public int scrollBarSize;
23920        public ScrollBarDrawable scrollBar;
23921        public float[] interpolatorValues;
23922        public View host;
23923
23924        public final Paint paint;
23925        public final Matrix matrix;
23926        public Shader shader;
23927
23928        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
23929
23930        private static final float[] OPAQUE = { 255 };
23931        private static final float[] TRANSPARENT = { 0.0f };
23932
23933        /**
23934         * When fading should start. This time moves into the future every time
23935         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
23936         */
23937        public long fadeStartTime;
23938
23939
23940        /**
23941         * The current state of the scrollbars: ON, OFF, or FADING
23942         */
23943        public int state = OFF;
23944
23945        private int mLastColor;
23946
23947        public final Rect mScrollBarBounds = new Rect();
23948
23949        public static final int NOT_DRAGGING = 0;
23950        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
23951        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
23952        public int mScrollBarDraggingState = NOT_DRAGGING;
23953
23954        public float mScrollBarDraggingPos = 0;
23955
23956        public ScrollabilityCache(ViewConfiguration configuration, View host) {
23957            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
23958            scrollBarSize = configuration.getScaledScrollBarSize();
23959            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
23960            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
23961
23962            paint = new Paint();
23963            matrix = new Matrix();
23964            // use use a height of 1, and then wack the matrix each time we
23965            // actually use it.
23966            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23967            paint.setShader(shader);
23968            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23969
23970            this.host = host;
23971        }
23972
23973        public void setFadeColor(int color) {
23974            if (color != mLastColor) {
23975                mLastColor = color;
23976
23977                if (color != 0) {
23978                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
23979                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
23980                    paint.setShader(shader);
23981                    // Restore the default transfer mode (src_over)
23982                    paint.setXfermode(null);
23983                } else {
23984                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
23985                    paint.setShader(shader);
23986                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
23987                }
23988            }
23989        }
23990
23991        public void run() {
23992            long now = AnimationUtils.currentAnimationTimeMillis();
23993            if (now >= fadeStartTime) {
23994
23995                // the animation fades the scrollbars out by changing
23996                // the opacity (alpha) from fully opaque to fully
23997                // transparent
23998                int nextFrame = (int) now;
23999                int framesCount = 0;
24000
24001                Interpolator interpolator = scrollBarInterpolator;
24002
24003                // Start opaque
24004                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
24005
24006                // End transparent
24007                nextFrame += scrollBarFadeDuration;
24008                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
24009
24010                state = FADING;
24011
24012                // Kick off the fade animation
24013                host.invalidate(true);
24014            }
24015        }
24016    }
24017
24018    /**
24019     * Resuable callback for sending
24020     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
24021     */
24022    private class SendViewScrolledAccessibilityEvent implements Runnable {
24023        public volatile boolean mIsPending;
24024
24025        public void run() {
24026            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
24027            mIsPending = false;
24028        }
24029    }
24030
24031    /**
24032     * <p>
24033     * This class represents a delegate that can be registered in a {@link View}
24034     * to enhance accessibility support via composition rather via inheritance.
24035     * It is specifically targeted to widget developers that extend basic View
24036     * classes i.e. classes in package android.view, that would like their
24037     * applications to be backwards compatible.
24038     * </p>
24039     * <div class="special reference">
24040     * <h3>Developer Guides</h3>
24041     * <p>For more information about making applications accessible, read the
24042     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
24043     * developer guide.</p>
24044     * </div>
24045     * <p>
24046     * A scenario in which a developer would like to use an accessibility delegate
24047     * is overriding a method introduced in a later API version than the minimal API
24048     * version supported by the application. For example, the method
24049     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
24050     * in API version 4 when the accessibility APIs were first introduced. If a
24051     * developer would like his application to run on API version 4 devices (assuming
24052     * all other APIs used by the application are version 4 or lower) and take advantage
24053     * of this method, instead of overriding the method which would break the application's
24054     * backwards compatibility, he can override the corresponding method in this
24055     * delegate and register the delegate in the target View if the API version of
24056     * the system is high enough, i.e. the API version is the same as or higher than the API
24057     * version that introduced
24058     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
24059     * </p>
24060     * <p>
24061     * Here is an example implementation:
24062     * </p>
24063     * <code><pre><p>
24064     * if (Build.VERSION.SDK_INT >= 14) {
24065     *     // If the API version is equal of higher than the version in
24066     *     // which onInitializeAccessibilityNodeInfo was introduced we
24067     *     // register a delegate with a customized implementation.
24068     *     View view = findViewById(R.id.view_id);
24069     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
24070     *         public void onInitializeAccessibilityNodeInfo(View host,
24071     *                 AccessibilityNodeInfo info) {
24072     *             // Let the default implementation populate the info.
24073     *             super.onInitializeAccessibilityNodeInfo(host, info);
24074     *             // Set some other information.
24075     *             info.setEnabled(host.isEnabled());
24076     *         }
24077     *     });
24078     * }
24079     * </code></pre></p>
24080     * <p>
24081     * This delegate contains methods that correspond to the accessibility methods
24082     * in View. If a delegate has been specified the implementation in View hands
24083     * off handling to the corresponding method in this delegate. The default
24084     * implementation the delegate methods behaves exactly as the corresponding
24085     * method in View for the case of no accessibility delegate been set. Hence,
24086     * to customize the behavior of a View method, clients can override only the
24087     * corresponding delegate method without altering the behavior of the rest
24088     * accessibility related methods of the host view.
24089     * </p>
24090     * <p>
24091     * <strong>Note:</strong> On platform versions prior to
24092     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
24093     * views in the {@code android.widget.*} package are called <i>before</i>
24094     * host methods. This prevents certain properties such as class name from
24095     * being modified by overriding
24096     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
24097     * as any changes will be overwritten by the host class.
24098     * <p>
24099     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
24100     * methods are called <i>after</i> host methods, which all properties to be
24101     * modified without being overwritten by the host class.
24102     */
24103    public static class AccessibilityDelegate {
24104
24105        /**
24106         * Sends an accessibility event of the given type. If accessibility is not
24107         * enabled this method has no effect.
24108         * <p>
24109         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
24110         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
24111         * been set.
24112         * </p>
24113         *
24114         * @param host The View hosting the delegate.
24115         * @param eventType The type of the event to send.
24116         *
24117         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
24118         */
24119        public void sendAccessibilityEvent(View host, int eventType) {
24120            host.sendAccessibilityEventInternal(eventType);
24121        }
24122
24123        /**
24124         * Performs the specified accessibility action on the view. For
24125         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
24126         * <p>
24127         * The default implementation behaves as
24128         * {@link View#performAccessibilityAction(int, Bundle)
24129         *  View#performAccessibilityAction(int, Bundle)} for the case of
24130         *  no accessibility delegate been set.
24131         * </p>
24132         *
24133         * @param action The action to perform.
24134         * @return Whether the action was performed.
24135         *
24136         * @see View#performAccessibilityAction(int, Bundle)
24137         *      View#performAccessibilityAction(int, Bundle)
24138         */
24139        public boolean performAccessibilityAction(View host, int action, Bundle args) {
24140            return host.performAccessibilityActionInternal(action, args);
24141        }
24142
24143        /**
24144         * Sends an accessibility event. This method behaves exactly as
24145         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
24146         * empty {@link AccessibilityEvent} and does not perform a check whether
24147         * accessibility is enabled.
24148         * <p>
24149         * The default implementation behaves as
24150         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
24151         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
24152         * the case of no accessibility delegate been set.
24153         * </p>
24154         *
24155         * @param host The View hosting the delegate.
24156         * @param event The event to send.
24157         *
24158         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
24159         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
24160         */
24161        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
24162            host.sendAccessibilityEventUncheckedInternal(event);
24163        }
24164
24165        /**
24166         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
24167         * to its children for adding their text content to the event.
24168         * <p>
24169         * The default implementation behaves as
24170         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
24171         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
24172         * the case of no accessibility delegate been set.
24173         * </p>
24174         *
24175         * @param host The View hosting the delegate.
24176         * @param event The event.
24177         * @return True if the event population was completed.
24178         *
24179         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
24180         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
24181         */
24182        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
24183            return host.dispatchPopulateAccessibilityEventInternal(event);
24184        }
24185
24186        /**
24187         * Gives a chance to the host View to populate the accessibility event with its
24188         * text content.
24189         * <p>
24190         * The default implementation behaves as
24191         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
24192         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
24193         * the case of no accessibility delegate been set.
24194         * </p>
24195         *
24196         * @param host The View hosting the delegate.
24197         * @param event The accessibility event which to populate.
24198         *
24199         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
24200         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
24201         */
24202        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
24203            host.onPopulateAccessibilityEventInternal(event);
24204        }
24205
24206        /**
24207         * Initializes an {@link AccessibilityEvent} with information about the
24208         * the host View which is the event source.
24209         * <p>
24210         * The default implementation behaves as
24211         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
24212         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
24213         * the case of no accessibility delegate been set.
24214         * </p>
24215         *
24216         * @param host The View hosting the delegate.
24217         * @param event The event to initialize.
24218         *
24219         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
24220         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
24221         */
24222        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
24223            host.onInitializeAccessibilityEventInternal(event);
24224        }
24225
24226        /**
24227         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
24228         * <p>
24229         * The default implementation behaves as
24230         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
24231         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
24232         * the case of no accessibility delegate been set.
24233         * </p>
24234         *
24235         * @param host The View hosting the delegate.
24236         * @param info The instance to initialize.
24237         *
24238         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
24239         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
24240         */
24241        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
24242            host.onInitializeAccessibilityNodeInfoInternal(info);
24243        }
24244
24245        /**
24246         * Called when a child of the host View has requested sending an
24247         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
24248         * to augment the event.
24249         * <p>
24250         * The default implementation behaves as
24251         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
24252         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
24253         * the case of no accessibility delegate been set.
24254         * </p>
24255         *
24256         * @param host The View hosting the delegate.
24257         * @param child The child which requests sending the event.
24258         * @param event The event to be sent.
24259         * @return True if the event should be sent
24260         *
24261         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
24262         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
24263         */
24264        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
24265                AccessibilityEvent event) {
24266            return host.onRequestSendAccessibilityEventInternal(child, event);
24267        }
24268
24269        /**
24270         * Gets the provider for managing a virtual view hierarchy rooted at this View
24271         * and reported to {@link android.accessibilityservice.AccessibilityService}s
24272         * that explore the window content.
24273         * <p>
24274         * The default implementation behaves as
24275         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
24276         * the case of no accessibility delegate been set.
24277         * </p>
24278         *
24279         * @return The provider.
24280         *
24281         * @see AccessibilityNodeProvider
24282         */
24283        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
24284            return null;
24285        }
24286
24287        /**
24288         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
24289         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
24290         * This method is responsible for obtaining an accessibility node info from a
24291         * pool of reusable instances and calling
24292         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
24293         * view to initialize the former.
24294         * <p>
24295         * <strong>Note:</strong> The client is responsible for recycling the obtained
24296         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
24297         * creation.
24298         * </p>
24299         * <p>
24300         * The default implementation behaves as
24301         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
24302         * the case of no accessibility delegate been set.
24303         * </p>
24304         * @return A populated {@link AccessibilityNodeInfo}.
24305         *
24306         * @see AccessibilityNodeInfo
24307         *
24308         * @hide
24309         */
24310        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
24311            return host.createAccessibilityNodeInfoInternal();
24312        }
24313    }
24314
24315    private class MatchIdPredicate implements Predicate<View> {
24316        public int mId;
24317
24318        @Override
24319        public boolean apply(View view) {
24320            return (view.mID == mId);
24321        }
24322    }
24323
24324    private class MatchLabelForPredicate implements Predicate<View> {
24325        private int mLabeledId;
24326
24327        @Override
24328        public boolean apply(View view) {
24329            return (view.mLabelForId == mLabeledId);
24330        }
24331    }
24332
24333    private class SendViewStateChangedAccessibilityEvent implements Runnable {
24334        private int mChangeTypes = 0;
24335        private boolean mPosted;
24336        private boolean mPostedWithDelay;
24337        private long mLastEventTimeMillis;
24338
24339        @Override
24340        public void run() {
24341            mPosted = false;
24342            mPostedWithDelay = false;
24343            mLastEventTimeMillis = SystemClock.uptimeMillis();
24344            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
24345                final AccessibilityEvent event = AccessibilityEvent.obtain();
24346                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
24347                event.setContentChangeTypes(mChangeTypes);
24348                sendAccessibilityEventUnchecked(event);
24349            }
24350            mChangeTypes = 0;
24351        }
24352
24353        public void runOrPost(int changeType) {
24354            mChangeTypes |= changeType;
24355
24356            // If this is a live region or the child of a live region, collect
24357            // all events from this frame and send them on the next frame.
24358            if (inLiveRegion()) {
24359                // If we're already posted with a delay, remove that.
24360                if (mPostedWithDelay) {
24361                    removeCallbacks(this);
24362                    mPostedWithDelay = false;
24363                }
24364                // Only post if we're not already posted.
24365                if (!mPosted) {
24366                    post(this);
24367                    mPosted = true;
24368                }
24369                return;
24370            }
24371
24372            if (mPosted) {
24373                return;
24374            }
24375
24376            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
24377            final long minEventIntevalMillis =
24378                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
24379            if (timeSinceLastMillis >= minEventIntevalMillis) {
24380                removeCallbacks(this);
24381                run();
24382            } else {
24383                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
24384                mPostedWithDelay = true;
24385            }
24386        }
24387    }
24388
24389    private boolean inLiveRegion() {
24390        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
24391            return true;
24392        }
24393
24394        ViewParent parent = getParent();
24395        while (parent instanceof View) {
24396            if (((View) parent).getAccessibilityLiveRegion()
24397                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
24398                return true;
24399            }
24400            parent = parent.getParent();
24401        }
24402
24403        return false;
24404    }
24405
24406    /**
24407     * Dump all private flags in readable format, useful for documentation and
24408     * sanity checking.
24409     */
24410    private static void dumpFlags() {
24411        final HashMap<String, String> found = Maps.newHashMap();
24412        try {
24413            for (Field field : View.class.getDeclaredFields()) {
24414                final int modifiers = field.getModifiers();
24415                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
24416                    if (field.getType().equals(int.class)) {
24417                        final int value = field.getInt(null);
24418                        dumpFlag(found, field.getName(), value);
24419                    } else if (field.getType().equals(int[].class)) {
24420                        final int[] values = (int[]) field.get(null);
24421                        for (int i = 0; i < values.length; i++) {
24422                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
24423                        }
24424                    }
24425                }
24426            }
24427        } catch (IllegalAccessException e) {
24428            throw new RuntimeException(e);
24429        }
24430
24431        final ArrayList<String> keys = Lists.newArrayList();
24432        keys.addAll(found.keySet());
24433        Collections.sort(keys);
24434        for (String key : keys) {
24435            Log.d(VIEW_LOG_TAG, found.get(key));
24436        }
24437    }
24438
24439    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
24440        // Sort flags by prefix, then by bits, always keeping unique keys
24441        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
24442        final int prefix = name.indexOf('_');
24443        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
24444        final String output = bits + " " + name;
24445        found.put(key, output);
24446    }
24447
24448    /** {@hide} */
24449    public void encode(@NonNull ViewHierarchyEncoder stream) {
24450        stream.beginObject(this);
24451        encodeProperties(stream);
24452        stream.endObject();
24453    }
24454
24455    /** {@hide} */
24456    @CallSuper
24457    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
24458        Object resolveId = ViewDebug.resolveId(getContext(), mID);
24459        if (resolveId instanceof String) {
24460            stream.addProperty("id", (String) resolveId);
24461        } else {
24462            stream.addProperty("id", mID);
24463        }
24464
24465        stream.addProperty("misc:transformation.alpha",
24466                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
24467        stream.addProperty("misc:transitionName", getTransitionName());
24468
24469        // layout
24470        stream.addProperty("layout:left", mLeft);
24471        stream.addProperty("layout:right", mRight);
24472        stream.addProperty("layout:top", mTop);
24473        stream.addProperty("layout:bottom", mBottom);
24474        stream.addProperty("layout:width", getWidth());
24475        stream.addProperty("layout:height", getHeight());
24476        stream.addProperty("layout:layoutDirection", getLayoutDirection());
24477        stream.addProperty("layout:layoutRtl", isLayoutRtl());
24478        stream.addProperty("layout:hasTransientState", hasTransientState());
24479        stream.addProperty("layout:baseline", getBaseline());
24480
24481        // layout params
24482        ViewGroup.LayoutParams layoutParams = getLayoutParams();
24483        if (layoutParams != null) {
24484            stream.addPropertyKey("layoutParams");
24485            layoutParams.encode(stream);
24486        }
24487
24488        // scrolling
24489        stream.addProperty("scrolling:scrollX", mScrollX);
24490        stream.addProperty("scrolling:scrollY", mScrollY);
24491
24492        // padding
24493        stream.addProperty("padding:paddingLeft", mPaddingLeft);
24494        stream.addProperty("padding:paddingRight", mPaddingRight);
24495        stream.addProperty("padding:paddingTop", mPaddingTop);
24496        stream.addProperty("padding:paddingBottom", mPaddingBottom);
24497        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
24498        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
24499        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
24500        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
24501        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
24502
24503        // measurement
24504        stream.addProperty("measurement:minHeight", mMinHeight);
24505        stream.addProperty("measurement:minWidth", mMinWidth);
24506        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
24507        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
24508
24509        // drawing
24510        stream.addProperty("drawing:elevation", getElevation());
24511        stream.addProperty("drawing:translationX", getTranslationX());
24512        stream.addProperty("drawing:translationY", getTranslationY());
24513        stream.addProperty("drawing:translationZ", getTranslationZ());
24514        stream.addProperty("drawing:rotation", getRotation());
24515        stream.addProperty("drawing:rotationX", getRotationX());
24516        stream.addProperty("drawing:rotationY", getRotationY());
24517        stream.addProperty("drawing:scaleX", getScaleX());
24518        stream.addProperty("drawing:scaleY", getScaleY());
24519        stream.addProperty("drawing:pivotX", getPivotX());
24520        stream.addProperty("drawing:pivotY", getPivotY());
24521        stream.addProperty("drawing:opaque", isOpaque());
24522        stream.addProperty("drawing:alpha", getAlpha());
24523        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
24524        stream.addProperty("drawing:shadow", hasShadow());
24525        stream.addProperty("drawing:solidColor", getSolidColor());
24526        stream.addProperty("drawing:layerType", mLayerType);
24527        stream.addProperty("drawing:willNotDraw", willNotDraw());
24528        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
24529        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
24530        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
24531        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
24532
24533        // focus
24534        stream.addProperty("focus:hasFocus", hasFocus());
24535        stream.addProperty("focus:isFocused", isFocused());
24536        stream.addProperty("focus:isFocusable", isFocusable());
24537        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
24538
24539        stream.addProperty("misc:clickable", isClickable());
24540        stream.addProperty("misc:pressed", isPressed());
24541        stream.addProperty("misc:selected", isSelected());
24542        stream.addProperty("misc:touchMode", isInTouchMode());
24543        stream.addProperty("misc:hovered", isHovered());
24544        stream.addProperty("misc:activated", isActivated());
24545
24546        stream.addProperty("misc:visibility", getVisibility());
24547        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
24548        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
24549
24550        stream.addProperty("misc:enabled", isEnabled());
24551        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
24552        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
24553
24554        // theme attributes
24555        Resources.Theme theme = getContext().getTheme();
24556        if (theme != null) {
24557            stream.addPropertyKey("theme");
24558            theme.encode(stream);
24559        }
24560
24561        // view attribute information
24562        int n = mAttributes != null ? mAttributes.length : 0;
24563        stream.addProperty("meta:__attrCount__", n/2);
24564        for (int i = 0; i < n; i += 2) {
24565            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
24566        }
24567
24568        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
24569
24570        // text
24571        stream.addProperty("text:textDirection", getTextDirection());
24572        stream.addProperty("text:textAlignment", getTextAlignment());
24573
24574        // accessibility
24575        CharSequence contentDescription = getContentDescription();
24576        stream.addProperty("accessibility:contentDescription",
24577                contentDescription == null ? "" : contentDescription.toString());
24578        stream.addProperty("accessibility:labelFor", getLabelFor());
24579        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
24580    }
24581
24582    /**
24583     * Determine if this view is rendered on a round wearable device and is the main view
24584     * on the screen.
24585     */
24586    private boolean shouldDrawRoundScrollbar() {
24587        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
24588            return false;
24589        }
24590
24591        final View rootView = getRootView();
24592        final WindowInsets insets = getRootWindowInsets();
24593
24594        int height = getHeight();
24595        int width = getWidth();
24596        int displayHeight = rootView.getHeight();
24597        int displayWidth = rootView.getWidth();
24598
24599        if (height != displayHeight || width != displayWidth) {
24600            return false;
24601        }
24602
24603        getLocationOnScreen(mAttachInfo.mTmpLocation);
24604        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
24605                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
24606    }
24607
24608    /**
24609     * Sets the tooltip text which will be displayed in a small popup next to the view.
24610     * <p>
24611     * The tooltip will be displayed:
24612     * <li>On long click, unless is not handled otherwise (by OnLongClickListener or a context
24613     * menu). </li>
24614     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
24615     *
24616     * @param tooltipText the tooltip text, or null if no tooltip is required
24617     */
24618    public final void setTooltipText(@Nullable CharSequence tooltipText) {
24619        if (TextUtils.isEmpty(tooltipText)) {
24620            setFlags(0, TOOLTIP);
24621            hideTooltip();
24622            mTooltipInfo = null;
24623        } else {
24624            setFlags(TOOLTIP, TOOLTIP);
24625            if (mTooltipInfo == null) {
24626                mTooltipInfo = new TooltipInfo();
24627                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
24628                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
24629            }
24630            mTooltipInfo.mTooltipText = tooltipText;
24631            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
24632                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
24633            }
24634        }
24635    }
24636
24637    /**
24638     * To be removed once the support library has stopped using it.
24639     *
24640     * @deprecated use {@link #setTooltipText} instead
24641     */
24642    @Deprecated
24643    public final void setTooltip(@Nullable CharSequence tooltipText) {
24644        setTooltipText(tooltipText);
24645    }
24646
24647    /**
24648     * Returns the view's tooltip text.
24649     *
24650     * @return the tooltip text
24651     */
24652    @Nullable
24653    public final CharSequence getTooltipText() {
24654        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
24655    }
24656
24657    /**
24658     * To be removed once the support library has stopped using it.
24659     *
24660     * @deprecated use {@link #getTooltipText} instead
24661     */
24662    @Deprecated
24663    @Nullable
24664    public final CharSequence getTooltip() {
24665        return getTooltipText();
24666    }
24667
24668    private boolean showTooltip(int x, int y, boolean fromLongClick) {
24669        if (mAttachInfo == null) {
24670            return false;
24671        }
24672        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
24673            return false;
24674        }
24675        final CharSequence tooltipText = getTooltipText();
24676        if (TextUtils.isEmpty(tooltipText)) {
24677            return false;
24678        }
24679        hideTooltip();
24680        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
24681        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
24682        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
24683        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, tooltipText);
24684        mAttachInfo.mTooltipHost = this;
24685        return true;
24686    }
24687
24688    void hideTooltip() {
24689        if (mTooltipInfo == null) {
24690            return;
24691        }
24692        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
24693        if (mTooltipInfo.mTooltipPopup == null) {
24694            return;
24695        }
24696        mTooltipInfo.mTooltipPopup.hide();
24697        mTooltipInfo.mTooltipPopup = null;
24698        mTooltipInfo.mTooltipFromLongClick = false;
24699        if (mAttachInfo != null) {
24700            mAttachInfo.mTooltipHost = null;
24701        }
24702    }
24703
24704    private boolean showLongClickTooltip(int x, int y) {
24705        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
24706        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
24707        return showTooltip(x, y, true);
24708    }
24709
24710    private void showHoverTooltip() {
24711        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
24712    }
24713
24714    boolean dispatchTooltipHoverEvent(MotionEvent event) {
24715        if (mTooltipInfo == null) {
24716            return false;
24717        }
24718        switch(event.getAction()) {
24719            case MotionEvent.ACTION_HOVER_MOVE:
24720                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
24721                    break;
24722                }
24723                if (!mTooltipInfo.mTooltipFromLongClick) {
24724                    if (mTooltipInfo.mTooltipPopup == null) {
24725                        // Schedule showing the tooltip after a timeout.
24726                        mTooltipInfo.mAnchorX = (int) event.getX();
24727                        mTooltipInfo.mAnchorY = (int) event.getY();
24728                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
24729                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
24730                                ViewConfiguration.getHoverTooltipShowTimeout());
24731                    }
24732
24733                    // Hide hover-triggered tooltip after a period of inactivity.
24734                    // Match the timeout used by NativeInputManager to hide the mouse pointer
24735                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
24736                    final int timeout;
24737                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
24738                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
24739                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
24740                    } else {
24741                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
24742                    }
24743                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
24744                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
24745                }
24746                return true;
24747
24748            case MotionEvent.ACTION_HOVER_EXIT:
24749                if (!mTooltipInfo.mTooltipFromLongClick) {
24750                    hideTooltip();
24751                }
24752                break;
24753        }
24754        return false;
24755    }
24756
24757    void handleTooltipKey(KeyEvent event) {
24758        switch (event.getAction()) {
24759            case KeyEvent.ACTION_DOWN:
24760                if (event.getRepeatCount() == 0) {
24761                    hideTooltip();
24762                }
24763                break;
24764
24765            case KeyEvent.ACTION_UP:
24766                handleTooltipUp();
24767                break;
24768        }
24769    }
24770
24771    private void handleTooltipUp() {
24772        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
24773            return;
24774        }
24775        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
24776        postDelayed(mTooltipInfo.mHideTooltipRunnable,
24777                ViewConfiguration.getLongPressTooltipHideTimeout());
24778    }
24779
24780    private int getFocusableAttribute(TypedArray attributes) {
24781        TypedValue val = new TypedValue();
24782        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
24783            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
24784                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
24785            } else {
24786                return val.data;
24787            }
24788        } else {
24789            return FOCUSABLE_AUTO;
24790        }
24791    }
24792
24793    /**
24794     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
24795     * is not showing.
24796     * @hide
24797     */
24798    @TestApi
24799    public View getTooltipView() {
24800        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
24801            return null;
24802        }
24803        return mTooltipInfo.mTooltipPopup.getContentView();
24804    }
24805}
24806