View.java revision 3427f57e036b3e535ca40076524eb53a72df4980
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.animation.AnimatorInflater;
20import android.animation.StateListAnimator;
21import android.annotation.CallSuper;
22import android.annotation.ColorInt;
23import android.annotation.DrawableRes;
24import android.annotation.FloatRange;
25import android.annotation.IdRes;
26import android.annotation.IntDef;
27import android.annotation.LayoutRes;
28import android.annotation.NonNull;
29import android.annotation.Nullable;
30import android.annotation.Size;
31import android.annotation.UiThread;
32import android.content.ClipData;
33import android.content.Context;
34import android.content.ContextWrapper;
35import android.content.Intent;
36import android.content.res.ColorStateList;
37import android.content.res.Configuration;
38import android.content.res.Resources;
39import android.content.res.TypedArray;
40import android.graphics.Bitmap;
41import android.graphics.Canvas;
42import android.graphics.Insets;
43import android.graphics.Interpolator;
44import android.graphics.LinearGradient;
45import android.graphics.Matrix;
46import android.graphics.Outline;
47import android.graphics.Paint;
48import android.graphics.PixelFormat;
49import android.graphics.Point;
50import android.graphics.PorterDuff;
51import android.graphics.PorterDuffXfermode;
52import android.graphics.Rect;
53import android.graphics.RectF;
54import android.graphics.Region;
55import android.graphics.Shader;
56import android.graphics.drawable.ColorDrawable;
57import android.graphics.drawable.Drawable;
58import android.hardware.display.DisplayManagerGlobal;
59import android.os.Bundle;
60import android.os.Handler;
61import android.os.IBinder;
62import android.os.Parcel;
63import android.os.Parcelable;
64import android.os.RemoteException;
65import android.os.SystemClock;
66import android.os.SystemProperties;
67import android.os.Trace;
68import android.text.TextUtils;
69import android.util.AttributeSet;
70import android.util.FloatProperty;
71import android.util.LayoutDirection;
72import android.util.Log;
73import android.util.LongSparseLongArray;
74import android.util.Pools.SynchronizedPool;
75import android.util.Property;
76import android.util.SparseArray;
77import android.util.StateSet;
78import android.util.SuperNotCalledException;
79import android.util.TypedValue;
80import android.view.ContextMenu.ContextMenuInfo;
81import android.view.AccessibilityIterators.TextSegmentIterator;
82import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
83import android.view.AccessibilityIterators.WordTextSegmentIterator;
84import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
85import android.view.accessibility.AccessibilityEvent;
86import android.view.accessibility.AccessibilityEventSource;
87import android.view.accessibility.AccessibilityManager;
88import android.view.accessibility.AccessibilityNodeInfo;
89import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
90import android.view.accessibility.AccessibilityNodeProvider;
91import android.view.animation.Animation;
92import android.view.animation.AnimationUtils;
93import android.view.animation.Transformation;
94import android.view.inputmethod.EditorInfo;
95import android.view.inputmethod.InputConnection;
96import android.view.inputmethod.InputMethodManager;
97import android.widget.Checkable;
98import android.widget.ScrollBarDrawable;
99
100import static android.os.Build.VERSION_CODES.*;
101import static java.lang.Math.max;
102
103import com.android.internal.R;
104import com.android.internal.util.Predicate;
105import com.android.internal.view.menu.MenuBuilder;
106import com.google.android.collect.Lists;
107import com.google.android.collect.Maps;
108
109import java.lang.annotation.Retention;
110import java.lang.annotation.RetentionPolicy;
111import java.lang.ref.WeakReference;
112import java.lang.reflect.Field;
113import java.lang.reflect.InvocationTargetException;
114import java.lang.reflect.Method;
115import java.lang.reflect.Modifier;
116import java.util.ArrayList;
117import java.util.Arrays;
118import java.util.Collections;
119import java.util.HashMap;
120import java.util.List;
121import java.util.Locale;
122import java.util.Map;
123import java.util.concurrent.CopyOnWriteArrayList;
124import java.util.concurrent.atomic.AtomicInteger;
125
126/**
127 * <p>
128 * This class represents the basic building block for user interface components. A View
129 * occupies a rectangular area on the screen and is responsible for drawing and
130 * event handling. View is the base class for <em>widgets</em>, which are
131 * used to create interactive UI components (buttons, text fields, etc.). The
132 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
133 * are invisible containers that hold other Views (or other ViewGroups) and define
134 * their layout properties.
135 * </p>
136 *
137 * <div class="special reference">
138 * <h3>Developer Guides</h3>
139 * <p>For information about using this class to develop your application's user interface,
140 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
141 * </div>
142 *
143 * <a name="Using"></a>
144 * <h3>Using Views</h3>
145 * <p>
146 * All of the views in a window are arranged in a single tree. You can add views
147 * either from code or by specifying a tree of views in one or more XML layout
148 * files. There are many specialized subclasses of views that act as controls or
149 * are capable of displaying text, images, or other content.
150 * </p>
151 * <p>
152 * Once you have created a tree of views, there are typically a few types of
153 * common operations you may wish to perform:
154 * <ul>
155 * <li><strong>Set properties:</strong> for example setting the text of a
156 * {@link android.widget.TextView}. The available properties and the methods
157 * that set them will vary among the different subclasses of views. Note that
158 * properties that are known at build time can be set in the XML layout
159 * files.</li>
160 * <li><strong>Set focus:</strong> The framework will handled moving focus in
161 * response to user input. To force focus to a specific view, call
162 * {@link #requestFocus}.</li>
163 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
164 * that will be notified when something interesting happens to the view. For
165 * example, all views will let you set a listener to be notified when the view
166 * gains or loses focus. You can register such a listener using
167 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
168 * Other view subclasses offer more specialized listeners. For example, a Button
169 * exposes a listener to notify clients when the button is clicked.</li>
170 * <li><strong>Set visibility:</strong> You can hide or show views using
171 * {@link #setVisibility(int)}.</li>
172 * </ul>
173 * </p>
174 * <p><em>
175 * Note: The Android framework is responsible for measuring, laying out and
176 * drawing views. You should not call methods that perform these actions on
177 * views yourself unless you are actually implementing a
178 * {@link android.view.ViewGroup}.
179 * </em></p>
180 *
181 * <a name="Lifecycle"></a>
182 * <h3>Implementing a Custom View</h3>
183 *
184 * <p>
185 * To implement a custom view, you will usually begin by providing overrides for
186 * some of the standard methods that the framework calls on all views. You do
187 * not need to override all of these methods. In fact, you can start by just
188 * overriding {@link #onDraw(android.graphics.Canvas)}.
189 * <table border="2" width="85%" align="center" cellpadding="5">
190 *     <thead>
191 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
192 *     </thead>
193 *
194 *     <tbody>
195 *     <tr>
196 *         <td rowspan="2">Creation</td>
197 *         <td>Constructors</td>
198 *         <td>There is a form of the constructor that are called when the view
199 *         is created from code and a form that is called when the view is
200 *         inflated from a layout file. The second form should parse and apply
201 *         any attributes defined in the layout file.
202 *         </td>
203 *     </tr>
204 *     <tr>
205 *         <td><code>{@link #onFinishInflate()}</code></td>
206 *         <td>Called after a view and all of its children has been inflated
207 *         from XML.</td>
208 *     </tr>
209 *
210 *     <tr>
211 *         <td rowspan="3">Layout</td>
212 *         <td><code>{@link #onMeasure(int, int)}</code></td>
213 *         <td>Called to determine the size requirements for this view and all
214 *         of its children.
215 *         </td>
216 *     </tr>
217 *     <tr>
218 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
219 *         <td>Called when this view should assign a size and position to all
220 *         of its children.
221 *         </td>
222 *     </tr>
223 *     <tr>
224 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
225 *         <td>Called when the size of this view has changed.
226 *         </td>
227 *     </tr>
228 *
229 *     <tr>
230 *         <td>Drawing</td>
231 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
232 *         <td>Called when the view should render its content.
233 *         </td>
234 *     </tr>
235 *
236 *     <tr>
237 *         <td rowspan="4">Event processing</td>
238 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
239 *         <td>Called when a new hardware key event occurs.
240 *         </td>
241 *     </tr>
242 *     <tr>
243 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
244 *         <td>Called when a hardware key up event occurs.
245 *         </td>
246 *     </tr>
247 *     <tr>
248 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
249 *         <td>Called when a trackball motion event occurs.
250 *         </td>
251 *     </tr>
252 *     <tr>
253 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
254 *         <td>Called when a touch screen motion event occurs.
255 *         </td>
256 *     </tr>
257 *
258 *     <tr>
259 *         <td rowspan="2">Focus</td>
260 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
261 *         <td>Called when the view gains or loses focus.
262 *         </td>
263 *     </tr>
264 *
265 *     <tr>
266 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
267 *         <td>Called when the window containing the view gains or loses focus.
268 *         </td>
269 *     </tr>
270 *
271 *     <tr>
272 *         <td rowspan="3">Attaching</td>
273 *         <td><code>{@link #onAttachedToWindow()}</code></td>
274 *         <td>Called when the view is attached to a window.
275 *         </td>
276 *     </tr>
277 *
278 *     <tr>
279 *         <td><code>{@link #onDetachedFromWindow}</code></td>
280 *         <td>Called when the view is detached from its window.
281 *         </td>
282 *     </tr>
283 *
284 *     <tr>
285 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
286 *         <td>Called when the visibility of the window containing the view
287 *         has changed.
288 *         </td>
289 *     </tr>
290 *     </tbody>
291 *
292 * </table>
293 * </p>
294 *
295 * <a name="IDs"></a>
296 * <h3>IDs</h3>
297 * Views may have an integer id associated with them. These ids are typically
298 * assigned in the layout XML files, and are used to find specific views within
299 * the view tree. A common pattern is to:
300 * <ul>
301 * <li>Define a Button in the layout file and assign it a unique ID.
302 * <pre>
303 * &lt;Button
304 *     android:id="@+id/my_button"
305 *     android:layout_width="wrap_content"
306 *     android:layout_height="wrap_content"
307 *     android:text="@string/my_button_text"/&gt;
308 * </pre></li>
309 * <li>From the onCreate method of an Activity, find the Button
310 * <pre class="prettyprint">
311 *      Button myButton = (Button) findViewById(R.id.my_button);
312 * </pre></li>
313 * </ul>
314 * <p>
315 * View IDs need not be unique throughout the tree, but it is good practice to
316 * ensure that they are at least unique within the part of the tree you are
317 * searching.
318 * </p>
319 *
320 * <a name="Position"></a>
321 * <h3>Position</h3>
322 * <p>
323 * The geometry of a view is that of a rectangle. A view has a location,
324 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
325 * two dimensions, expressed as a width and a height. The unit for location
326 * and dimensions is the pixel.
327 * </p>
328 *
329 * <p>
330 * It is possible to retrieve the location of a view by invoking the methods
331 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
332 * coordinate of the rectangle representing the view. The latter returns the
333 * top, or Y, coordinate of the rectangle representing the view. These methods
334 * both return the location of the view relative to its parent. For instance,
335 * when getLeft() returns 20, that means the view is located 20 pixels to the
336 * right of the left edge of its direct parent.
337 * </p>
338 *
339 * <p>
340 * In addition, several convenience methods are offered to avoid unnecessary
341 * computations, namely {@link #getRight()} and {@link #getBottom()}.
342 * These methods return the coordinates of the right and bottom edges of the
343 * rectangle representing the view. For instance, calling {@link #getRight()}
344 * is similar to the following computation: <code>getLeft() + getWidth()</code>
345 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
346 * </p>
347 *
348 * <a name="SizePaddingMargins"></a>
349 * <h3>Size, padding and margins</h3>
350 * <p>
351 * The size of a view is expressed with a width and a height. A view actually
352 * possess two pairs of width and height values.
353 * </p>
354 *
355 * <p>
356 * The first pair is known as <em>measured width</em> and
357 * <em>measured height</em>. These dimensions define how big a view wants to be
358 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
359 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
360 * and {@link #getMeasuredHeight()}.
361 * </p>
362 *
363 * <p>
364 * The second pair is simply known as <em>width</em> and <em>height</em>, or
365 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
366 * dimensions define the actual size of the view on screen, at drawing time and
367 * after layout. These values may, but do not have to, be different from the
368 * measured width and height. The width and height can be obtained by calling
369 * {@link #getWidth()} and {@link #getHeight()}.
370 * </p>
371 *
372 * <p>
373 * To measure its dimensions, a view takes into account its padding. The padding
374 * is expressed in pixels for the left, top, right and bottom parts of the view.
375 * Padding can be used to offset the content of the view by a specific amount of
376 * pixels. For instance, a left padding of 2 will push the view's content by
377 * 2 pixels to the right of the left edge. Padding can be set using the
378 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
379 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
380 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
381 * {@link #getPaddingEnd()}.
382 * </p>
383 *
384 * <p>
385 * Even though a view can define a padding, it does not provide any support for
386 * margins. However, view groups provide such a support. Refer to
387 * {@link android.view.ViewGroup} and
388 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
389 * </p>
390 *
391 * <a name="Layout"></a>
392 * <h3>Layout</h3>
393 * <p>
394 * Layout is a two pass process: a measure pass and a layout pass. The measuring
395 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
396 * of the view tree. Each view pushes dimension specifications down the tree
397 * during the recursion. At the end of the measure pass, every view has stored
398 * its measurements. The second pass happens in
399 * {@link #layout(int,int,int,int)} and is also top-down. During
400 * this pass each parent is responsible for positioning all of its children
401 * using the sizes computed in the measure pass.
402 * </p>
403 *
404 * <p>
405 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
406 * {@link #getMeasuredHeight()} values must be set, along with those for all of
407 * that view's descendants. A view's measured width and measured height values
408 * must respect the constraints imposed by the view's parents. This guarantees
409 * that at the end of the measure pass, all parents accept all of their
410 * children's measurements. A parent view may call measure() more than once on
411 * its children. For example, the parent may measure each child once with
412 * unspecified dimensions to find out how big they want to be, then call
413 * measure() on them again with actual numbers if the sum of all the children's
414 * unconstrained sizes is too big or too small.
415 * </p>
416 *
417 * <p>
418 * The measure pass uses two classes to communicate dimensions. The
419 * {@link MeasureSpec} class is used by views to tell their parents how they
420 * want to be measured and positioned. The base LayoutParams class just
421 * describes how big the view wants to be for both width and height. For each
422 * dimension, it can specify one of:
423 * <ul>
424 * <li> an exact number
425 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
426 * (minus padding)
427 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
428 * enclose its content (plus padding).
429 * </ul>
430 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
431 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
432 * an X and Y value.
433 * </p>
434 *
435 * <p>
436 * MeasureSpecs are used to push requirements down the tree from parent to
437 * child. A MeasureSpec can be in one of three modes:
438 * <ul>
439 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
440 * of a child view. For example, a LinearLayout may call measure() on its child
441 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
442 * tall the child view wants to be given a width of 240 pixels.
443 * <li>EXACTLY: This is used by the parent to impose an exact size on the
444 * child. The child must use this size, and guarantee that all of its
445 * descendants will fit within this size.
446 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
447 * child. The child must guarantee that it and all of its descendants will fit
448 * within this size.
449 * </ul>
450 * </p>
451 *
452 * <p>
453 * To initiate a layout, call {@link #requestLayout}. This method is typically
454 * called by a view on itself when it believes that is can no longer fit within
455 * its current bounds.
456 * </p>
457 *
458 * <a name="Drawing"></a>
459 * <h3>Drawing</h3>
460 * <p>
461 * Drawing is handled by walking the tree and recording the drawing commands of
462 * any View that needs to update. After this, the drawing commands of the
463 * entire tree are issued to screen, clipped to the newly damaged area.
464 * </p>
465 *
466 * <p>
467 * The tree is largely recorded and drawn in order, with parents drawn before
468 * (i.e., behind) their children, with siblings drawn in the order they appear
469 * in the tree. If you set a background drawable for a View, then the View will
470 * draw it before calling back to its <code>onDraw()</code> method. The child
471 * drawing order can be overridden with
472 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
473 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
474 * </p>
475 *
476 * <p>
477 * To force a view to draw, call {@link #invalidate()}.
478 * </p>
479 *
480 * <a name="EventHandlingThreading"></a>
481 * <h3>Event Handling and Threading</h3>
482 * <p>
483 * The basic cycle of a view is as follows:
484 * <ol>
485 * <li>An event comes in and is dispatched to the appropriate view. The view
486 * handles the event and notifies any listeners.</li>
487 * <li>If in the course of processing the event, the view's bounds may need
488 * to be changed, the view will call {@link #requestLayout()}.</li>
489 * <li>Similarly, if in the course of processing the event the view's appearance
490 * may need to be changed, the view will call {@link #invalidate()}.</li>
491 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
492 * the framework will take care of measuring, laying out, and drawing the tree
493 * as appropriate.</li>
494 * </ol>
495 * </p>
496 *
497 * <p><em>Note: The entire view tree is single threaded. You must always be on
498 * the UI thread when calling any method on any view.</em>
499 * If you are doing work on other threads and want to update the state of a view
500 * from that thread, you should use a {@link Handler}.
501 * </p>
502 *
503 * <a name="FocusHandling"></a>
504 * <h3>Focus Handling</h3>
505 * <p>
506 * The framework will handle routine focus movement in response to user input.
507 * This includes changing the focus as views are removed or hidden, or as new
508 * views become available. Views indicate their willingness to take focus
509 * through the {@link #isFocusable} method. To change whether a view can take
510 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
511 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
512 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
513 * </p>
514 * <p>
515 * Focus movement is based on an algorithm which finds the nearest neighbor in a
516 * given direction. In rare cases, the default algorithm may not match the
517 * intended behavior of the developer. In these situations, you can provide
518 * explicit overrides by using these XML attributes in the layout file:
519 * <pre>
520 * nextFocusDown
521 * nextFocusLeft
522 * nextFocusRight
523 * nextFocusUp
524 * </pre>
525 * </p>
526 *
527 *
528 * <p>
529 * To get a particular view to take focus, call {@link #requestFocus()}.
530 * </p>
531 *
532 * <a name="TouchMode"></a>
533 * <h3>Touch Mode</h3>
534 * <p>
535 * When a user is navigating a user interface via directional keys such as a D-pad, it is
536 * necessary to give focus to actionable items such as buttons so the user can see
537 * what will take input.  If the device has touch capabilities, however, and the user
538 * begins interacting with the interface by touching it, it is no longer necessary to
539 * always highlight, or give focus to, a particular view.  This motivates a mode
540 * for interaction named 'touch mode'.
541 * </p>
542 * <p>
543 * For a touch capable device, once the user touches the screen, the device
544 * will enter touch mode.  From this point onward, only views for which
545 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
546 * Other views that are touchable, like buttons, will not take focus when touched; they will
547 * only fire the on click listeners.
548 * </p>
549 * <p>
550 * Any time a user hits a directional key, such as a D-pad direction, the view device will
551 * exit touch mode, and find a view to take focus, so that the user may resume interacting
552 * with the user interface without touching the screen again.
553 * </p>
554 * <p>
555 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
556 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
557 * </p>
558 *
559 * <a name="Scrolling"></a>
560 * <h3>Scrolling</h3>
561 * <p>
562 * The framework provides basic support for views that wish to internally
563 * scroll their content. This includes keeping track of the X and Y scroll
564 * offset as well as mechanisms for drawing scrollbars. See
565 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
566 * {@link #awakenScrollBars()} for more details.
567 * </p>
568 *
569 * <a name="Tags"></a>
570 * <h3>Tags</h3>
571 * <p>
572 * Unlike IDs, tags are not used to identify views. Tags are essentially an
573 * extra piece of information that can be associated with a view. They are most
574 * often used as a convenience to store data related to views in the views
575 * themselves rather than by putting them in a separate structure.
576 * </p>
577 *
578 * <a name="Properties"></a>
579 * <h3>Properties</h3>
580 * <p>
581 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
582 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
583 * available both in the {@link Property} form as well as in similarly-named setter/getter
584 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
585 * be used to set persistent state associated with these rendering-related properties on the view.
586 * The properties and methods can also be used in conjunction with
587 * {@link android.animation.Animator Animator}-based animations, described more in the
588 * <a href="#Animation">Animation</a> section.
589 * </p>
590 *
591 * <a name="Animation"></a>
592 * <h3>Animation</h3>
593 * <p>
594 * Starting with Android 3.0, the preferred way of animating views is to use the
595 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
596 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
597 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
598 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
599 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
600 * makes animating these View properties particularly easy and efficient.
601 * </p>
602 * <p>
603 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
604 * You can attach an {@link Animation} object to a view using
605 * {@link #setAnimation(Animation)} or
606 * {@link #startAnimation(Animation)}. The animation can alter the scale,
607 * rotation, translation and alpha of a view over time. If the animation is
608 * attached to a view that has children, the animation will affect the entire
609 * subtree rooted by that node. When an animation is started, the framework will
610 * take care of redrawing the appropriate views until the animation completes.
611 * </p>
612 *
613 * <a name="Security"></a>
614 * <h3>Security</h3>
615 * <p>
616 * Sometimes it is essential that an application be able to verify that an action
617 * is being performed with the full knowledge and consent of the user, such as
618 * granting a permission request, making a purchase or clicking on an advertisement.
619 * Unfortunately, a malicious application could try to spoof the user into
620 * performing these actions, unaware, by concealing the intended purpose of the view.
621 * As a remedy, the framework offers a touch filtering mechanism that can be used to
622 * improve the security of views that provide access to sensitive functionality.
623 * </p><p>
624 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
625 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
626 * will discard touches that are received whenever the view's window is obscured by
627 * another visible window.  As a result, the view will not receive touches whenever a
628 * toast, dialog or other window appears above the view's window.
629 * </p><p>
630 * For more fine-grained control over security, consider overriding the
631 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
632 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
633 * </p>
634 *
635 * @attr ref android.R.styleable#View_alpha
636 * @attr ref android.R.styleable#View_background
637 * @attr ref android.R.styleable#View_clickable
638 * @attr ref android.R.styleable#View_contentDescription
639 * @attr ref android.R.styleable#View_drawingCacheQuality
640 * @attr ref android.R.styleable#View_duplicateParentState
641 * @attr ref android.R.styleable#View_id
642 * @attr ref android.R.styleable#View_requiresFadingEdge
643 * @attr ref android.R.styleable#View_fadeScrollbars
644 * @attr ref android.R.styleable#View_fadingEdgeLength
645 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
646 * @attr ref android.R.styleable#View_fitsSystemWindows
647 * @attr ref android.R.styleable#View_isScrollContainer
648 * @attr ref android.R.styleable#View_focusable
649 * @attr ref android.R.styleable#View_focusableInTouchMode
650 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
651 * @attr ref android.R.styleable#View_keepScreenOn
652 * @attr ref android.R.styleable#View_layerType
653 * @attr ref android.R.styleable#View_layoutDirection
654 * @attr ref android.R.styleable#View_longClickable
655 * @attr ref android.R.styleable#View_minHeight
656 * @attr ref android.R.styleable#View_minWidth
657 * @attr ref android.R.styleable#View_nextFocusDown
658 * @attr ref android.R.styleable#View_nextFocusLeft
659 * @attr ref android.R.styleable#View_nextFocusRight
660 * @attr ref android.R.styleable#View_nextFocusUp
661 * @attr ref android.R.styleable#View_onClick
662 * @attr ref android.R.styleable#View_padding
663 * @attr ref android.R.styleable#View_paddingBottom
664 * @attr ref android.R.styleable#View_paddingLeft
665 * @attr ref android.R.styleable#View_paddingRight
666 * @attr ref android.R.styleable#View_paddingTop
667 * @attr ref android.R.styleable#View_paddingStart
668 * @attr ref android.R.styleable#View_paddingEnd
669 * @attr ref android.R.styleable#View_saveEnabled
670 * @attr ref android.R.styleable#View_rotation
671 * @attr ref android.R.styleable#View_rotationX
672 * @attr ref android.R.styleable#View_rotationY
673 * @attr ref android.R.styleable#View_scaleX
674 * @attr ref android.R.styleable#View_scaleY
675 * @attr ref android.R.styleable#View_scrollX
676 * @attr ref android.R.styleable#View_scrollY
677 * @attr ref android.R.styleable#View_scrollbarSize
678 * @attr ref android.R.styleable#View_scrollbarStyle
679 * @attr ref android.R.styleable#View_scrollbars
680 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
681 * @attr ref android.R.styleable#View_scrollbarFadeDuration
682 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
683 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
684 * @attr ref android.R.styleable#View_scrollbarThumbVertical
685 * @attr ref android.R.styleable#View_scrollbarTrackVertical
686 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
687 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
688 * @attr ref android.R.styleable#View_stateListAnimator
689 * @attr ref android.R.styleable#View_transitionName
690 * @attr ref android.R.styleable#View_soundEffectsEnabled
691 * @attr ref android.R.styleable#View_tag
692 * @attr ref android.R.styleable#View_textAlignment
693 * @attr ref android.R.styleable#View_textDirection
694 * @attr ref android.R.styleable#View_transformPivotX
695 * @attr ref android.R.styleable#View_transformPivotY
696 * @attr ref android.R.styleable#View_translationX
697 * @attr ref android.R.styleable#View_translationY
698 * @attr ref android.R.styleable#View_translationZ
699 * @attr ref android.R.styleable#View_visibility
700 *
701 * @see android.view.ViewGroup
702 */
703@UiThread
704public class View implements Drawable.Callback, KeyEvent.Callback,
705        AccessibilityEventSource {
706    private static final boolean DBG = false;
707
708    /**
709     * The logging tag used by this class with android.util.Log.
710     */
711    protected static final String VIEW_LOG_TAG = "View";
712
713    /**
714     * When set to true, apps will draw debugging information about their layouts.
715     *
716     * @hide
717     */
718    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
719
720    /**
721     * When set to true, this view will save its attribute data.
722     *
723     * @hide
724     */
725    public static boolean mDebugViewAttributes = false;
726
727    /**
728     * Used to mark a View that has no ID.
729     */
730    public static final int NO_ID = -1;
731
732    /**
733     * Signals that compatibility booleans have been initialized according to
734     * target SDK versions.
735     */
736    private static boolean sCompatibilityDone = false;
737
738    /**
739     * Use the old (broken) way of building MeasureSpecs.
740     */
741    private static boolean sUseBrokenMakeMeasureSpec = false;
742
743    /**
744     * Ignore any optimizations using the measure cache.
745     */
746    private static boolean sIgnoreMeasureCache = false;
747
748    /**
749     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
750     * calling setFlags.
751     */
752    private static final int NOT_FOCUSABLE = 0x00000000;
753
754    /**
755     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
756     * setFlags.
757     */
758    private static final int FOCUSABLE = 0x00000001;
759
760    /**
761     * Mask for use with setFlags indicating bits used for focus.
762     */
763    private static final int FOCUSABLE_MASK = 0x00000001;
764
765    /**
766     * This view will adjust its padding to fit sytem windows (e.g. status bar)
767     */
768    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
769
770    /** @hide */
771    @IntDef({VISIBLE, INVISIBLE, GONE})
772    @Retention(RetentionPolicy.SOURCE)
773    public @interface Visibility {}
774
775    /**
776     * This view is visible.
777     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
778     * android:visibility}.
779     */
780    public static final int VISIBLE = 0x00000000;
781
782    /**
783     * This view is invisible, but it still takes up space for layout purposes.
784     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
785     * android:visibility}.
786     */
787    public static final int INVISIBLE = 0x00000004;
788
789    /**
790     * This view is invisible, and it doesn't take any space for layout
791     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
792     * android:visibility}.
793     */
794    public static final int GONE = 0x00000008;
795
796    /**
797     * Mask for use with setFlags indicating bits used for visibility.
798     * {@hide}
799     */
800    static final int VISIBILITY_MASK = 0x0000000C;
801
802    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
803
804    /**
805     * This view is enabled. Interpretation varies by subclass.
806     * Use with ENABLED_MASK when calling setFlags.
807     * {@hide}
808     */
809    static final int ENABLED = 0x00000000;
810
811    /**
812     * This view is disabled. Interpretation varies by subclass.
813     * Use with ENABLED_MASK when calling setFlags.
814     * {@hide}
815     */
816    static final int DISABLED = 0x00000020;
817
818   /**
819    * Mask for use with setFlags indicating bits used for indicating whether
820    * this view is enabled
821    * {@hide}
822    */
823    static final int ENABLED_MASK = 0x00000020;
824
825    /**
826     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
827     * called and further optimizations will be performed. It is okay to have
828     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
829     * {@hide}
830     */
831    static final int WILL_NOT_DRAW = 0x00000080;
832
833    /**
834     * Mask for use with setFlags indicating bits used for indicating whether
835     * this view is will draw
836     * {@hide}
837     */
838    static final int DRAW_MASK = 0x00000080;
839
840    /**
841     * <p>This view doesn't show scrollbars.</p>
842     * {@hide}
843     */
844    static final int SCROLLBARS_NONE = 0x00000000;
845
846    /**
847     * <p>This view shows horizontal scrollbars.</p>
848     * {@hide}
849     */
850    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
851
852    /**
853     * <p>This view shows vertical scrollbars.</p>
854     * {@hide}
855     */
856    static final int SCROLLBARS_VERTICAL = 0x00000200;
857
858    /**
859     * <p>Mask for use with setFlags indicating bits used for indicating which
860     * scrollbars are enabled.</p>
861     * {@hide}
862     */
863    static final int SCROLLBARS_MASK = 0x00000300;
864
865    /**
866     * Indicates that the view should filter touches when its window is obscured.
867     * Refer to the class comments for more information about this security feature.
868     * {@hide}
869     */
870    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
871
872    /**
873     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
874     * that they are optional and should be skipped if the window has
875     * requested system UI flags that ignore those insets for layout.
876     */
877    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
878
879    /**
880     * <p>This view doesn't show fading edges.</p>
881     * {@hide}
882     */
883    static final int FADING_EDGE_NONE = 0x00000000;
884
885    /**
886     * <p>This view shows horizontal fading edges.</p>
887     * {@hide}
888     */
889    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
890
891    /**
892     * <p>This view shows vertical fading edges.</p>
893     * {@hide}
894     */
895    static final int FADING_EDGE_VERTICAL = 0x00002000;
896
897    /**
898     * <p>Mask for use with setFlags indicating bits used for indicating which
899     * fading edges are enabled.</p>
900     * {@hide}
901     */
902    static final int FADING_EDGE_MASK = 0x00003000;
903
904    /**
905     * <p>Indicates this view can be clicked. When clickable, a View reacts
906     * to clicks by notifying the OnClickListener.<p>
907     * {@hide}
908     */
909    static final int CLICKABLE = 0x00004000;
910
911    /**
912     * <p>Indicates this view is caching its drawing into a bitmap.</p>
913     * {@hide}
914     */
915    static final int DRAWING_CACHE_ENABLED = 0x00008000;
916
917    /**
918     * <p>Indicates that no icicle should be saved for this view.<p>
919     * {@hide}
920     */
921    static final int SAVE_DISABLED = 0x000010000;
922
923    /**
924     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
925     * property.</p>
926     * {@hide}
927     */
928    static final int SAVE_DISABLED_MASK = 0x000010000;
929
930    /**
931     * <p>Indicates that no drawing cache should ever be created for this view.<p>
932     * {@hide}
933     */
934    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
935
936    /**
937     * <p>Indicates this view can take / keep focus when int touch mode.</p>
938     * {@hide}
939     */
940    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
941
942    /** @hide */
943    @Retention(RetentionPolicy.SOURCE)
944    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
945    public @interface DrawingCacheQuality {}
946
947    /**
948     * <p>Enables low quality mode for the drawing cache.</p>
949     */
950    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
951
952    /**
953     * <p>Enables high quality mode for the drawing cache.</p>
954     */
955    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
956
957    /**
958     * <p>Enables automatic quality mode for the drawing cache.</p>
959     */
960    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
961
962    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
963            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
964    };
965
966    /**
967     * <p>Mask for use with setFlags indicating bits used for the cache
968     * quality property.</p>
969     * {@hide}
970     */
971    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
972
973    /**
974     * <p>
975     * Indicates this view can be long clicked. When long clickable, a View
976     * reacts to long clicks by notifying the OnLongClickListener or showing a
977     * context menu.
978     * </p>
979     * {@hide}
980     */
981    static final int LONG_CLICKABLE = 0x00200000;
982
983    /**
984     * <p>Indicates that this view gets its drawable states from its direct parent
985     * and ignores its original internal states.</p>
986     *
987     * @hide
988     */
989    static final int DUPLICATE_PARENT_STATE = 0x00400000;
990
991    /**
992     * <p>
993     * Indicates this view can be stylus button pressed. When stylus button
994     * pressable, a View reacts to stylus button presses by notifiying
995     * the OnStylusButtonPressListener.
996     * </p>
997     * {@hide}
998     */
999    static final int STYLUS_BUTTON_PRESSABLE = 0x00800000;
1000
1001
1002    /** @hide */
1003    @IntDef({
1004        SCROLLBARS_INSIDE_OVERLAY,
1005        SCROLLBARS_INSIDE_INSET,
1006        SCROLLBARS_OUTSIDE_OVERLAY,
1007        SCROLLBARS_OUTSIDE_INSET
1008    })
1009    @Retention(RetentionPolicy.SOURCE)
1010    public @interface ScrollBarStyle {}
1011
1012    /**
1013     * The scrollbar style to display the scrollbars inside the content area,
1014     * without increasing the padding. The scrollbars will be overlaid with
1015     * translucency on the view's content.
1016     */
1017    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1018
1019    /**
1020     * The scrollbar style to display the scrollbars inside the padded area,
1021     * increasing the padding of the view. The scrollbars will not overlap the
1022     * content area of the view.
1023     */
1024    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1025
1026    /**
1027     * The scrollbar style to display the scrollbars at the edge of the view,
1028     * without increasing the padding. The scrollbars will be overlaid with
1029     * translucency.
1030     */
1031    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1032
1033    /**
1034     * The scrollbar style to display the scrollbars at the edge of the view,
1035     * increasing the padding of the view. The scrollbars will only overlap the
1036     * background, if any.
1037     */
1038    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1039
1040    /**
1041     * Mask to check if the scrollbar style is overlay or inset.
1042     * {@hide}
1043     */
1044    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1045
1046    /**
1047     * Mask to check if the scrollbar style is inside or outside.
1048     * {@hide}
1049     */
1050    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1051
1052    /**
1053     * Mask for scrollbar style.
1054     * {@hide}
1055     */
1056    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1057
1058    /**
1059     * View flag indicating that the screen should remain on while the
1060     * window containing this view is visible to the user.  This effectively
1061     * takes care of automatically setting the WindowManager's
1062     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1063     */
1064    public static final int KEEP_SCREEN_ON = 0x04000000;
1065
1066    /**
1067     * View flag indicating whether this view should have sound effects enabled
1068     * for events such as clicking and touching.
1069     */
1070    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1071
1072    /**
1073     * View flag indicating whether this view should have haptic feedback
1074     * enabled for events such as long presses.
1075     */
1076    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1077
1078    /**
1079     * <p>Indicates that the view hierarchy should stop saving state when
1080     * it reaches this view.  If state saving is initiated immediately at
1081     * the view, it will be allowed.
1082     * {@hide}
1083     */
1084    static final int PARENT_SAVE_DISABLED = 0x20000000;
1085
1086    /**
1087     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1088     * {@hide}
1089     */
1090    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1091
1092    /** @hide */
1093    @IntDef(flag = true,
1094            value = {
1095                FOCUSABLES_ALL,
1096                FOCUSABLES_TOUCH_MODE
1097            })
1098    @Retention(RetentionPolicy.SOURCE)
1099    public @interface FocusableMode {}
1100
1101    /**
1102     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1103     * should add all focusable Views regardless if they are focusable in touch mode.
1104     */
1105    public static final int FOCUSABLES_ALL = 0x00000000;
1106
1107    /**
1108     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1109     * should add only Views focusable in touch mode.
1110     */
1111    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1112
1113    /** @hide */
1114    @IntDef({
1115            FOCUS_BACKWARD,
1116            FOCUS_FORWARD,
1117            FOCUS_LEFT,
1118            FOCUS_UP,
1119            FOCUS_RIGHT,
1120            FOCUS_DOWN
1121    })
1122    @Retention(RetentionPolicy.SOURCE)
1123    public @interface FocusDirection {}
1124
1125    /** @hide */
1126    @IntDef({
1127            FOCUS_LEFT,
1128            FOCUS_UP,
1129            FOCUS_RIGHT,
1130            FOCUS_DOWN
1131    })
1132    @Retention(RetentionPolicy.SOURCE)
1133    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1134
1135    /**
1136     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1137     * item.
1138     */
1139    public static final int FOCUS_BACKWARD = 0x00000001;
1140
1141    /**
1142     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1143     * item.
1144     */
1145    public static final int FOCUS_FORWARD = 0x00000002;
1146
1147    /**
1148     * Use with {@link #focusSearch(int)}. Move focus to the left.
1149     */
1150    public static final int FOCUS_LEFT = 0x00000011;
1151
1152    /**
1153     * Use with {@link #focusSearch(int)}. Move focus up.
1154     */
1155    public static final int FOCUS_UP = 0x00000021;
1156
1157    /**
1158     * Use with {@link #focusSearch(int)}. Move focus to the right.
1159     */
1160    public static final int FOCUS_RIGHT = 0x00000042;
1161
1162    /**
1163     * Use with {@link #focusSearch(int)}. Move focus down.
1164     */
1165    public static final int FOCUS_DOWN = 0x00000082;
1166
1167    /**
1168     * Bits of {@link #getMeasuredWidthAndState()} and
1169     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1170     */
1171    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1172
1173    /**
1174     * Bits of {@link #getMeasuredWidthAndState()} and
1175     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1176     */
1177    public static final int MEASURED_STATE_MASK = 0xff000000;
1178
1179    /**
1180     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1181     * for functions that combine both width and height into a single int,
1182     * such as {@link #getMeasuredState()} and the childState argument of
1183     * {@link #resolveSizeAndState(int, int, int)}.
1184     */
1185    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1186
1187    /**
1188     * Bit of {@link #getMeasuredWidthAndState()} and
1189     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1190     * is smaller that the space the view would like to have.
1191     */
1192    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1193
1194    /**
1195     * Base View state sets
1196     */
1197    // Singles
1198    /**
1199     * Indicates the view has no states set. States are used with
1200     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1201     * view depending on its state.
1202     *
1203     * @see android.graphics.drawable.Drawable
1204     * @see #getDrawableState()
1205     */
1206    protected static final int[] EMPTY_STATE_SET;
1207    /**
1208     * Indicates the view is enabled. States are used with
1209     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1210     * view depending on its state.
1211     *
1212     * @see android.graphics.drawable.Drawable
1213     * @see #getDrawableState()
1214     */
1215    protected static final int[] ENABLED_STATE_SET;
1216    /**
1217     * Indicates the view is focused. States are used with
1218     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1219     * view depending on its state.
1220     *
1221     * @see android.graphics.drawable.Drawable
1222     * @see #getDrawableState()
1223     */
1224    protected static final int[] FOCUSED_STATE_SET;
1225    /**
1226     * Indicates the view is selected. States are used with
1227     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1228     * view depending on its state.
1229     *
1230     * @see android.graphics.drawable.Drawable
1231     * @see #getDrawableState()
1232     */
1233    protected static final int[] SELECTED_STATE_SET;
1234    /**
1235     * Indicates the view is pressed. States are used with
1236     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1237     * view depending on its state.
1238     *
1239     * @see android.graphics.drawable.Drawable
1240     * @see #getDrawableState()
1241     */
1242    protected static final int[] PRESSED_STATE_SET;
1243    /**
1244     * Indicates the view's window has focus. States are used with
1245     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1246     * view depending on its state.
1247     *
1248     * @see android.graphics.drawable.Drawable
1249     * @see #getDrawableState()
1250     */
1251    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1252    // Doubles
1253    /**
1254     * Indicates the view is enabled and has the focus.
1255     *
1256     * @see #ENABLED_STATE_SET
1257     * @see #FOCUSED_STATE_SET
1258     */
1259    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1260    /**
1261     * Indicates the view is enabled and selected.
1262     *
1263     * @see #ENABLED_STATE_SET
1264     * @see #SELECTED_STATE_SET
1265     */
1266    protected static final int[] ENABLED_SELECTED_STATE_SET;
1267    /**
1268     * Indicates the view is enabled and that its window has focus.
1269     *
1270     * @see #ENABLED_STATE_SET
1271     * @see #WINDOW_FOCUSED_STATE_SET
1272     */
1273    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1274    /**
1275     * Indicates the view is focused and selected.
1276     *
1277     * @see #FOCUSED_STATE_SET
1278     * @see #SELECTED_STATE_SET
1279     */
1280    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1281    /**
1282     * Indicates the view has the focus and that its window has the focus.
1283     *
1284     * @see #FOCUSED_STATE_SET
1285     * @see #WINDOW_FOCUSED_STATE_SET
1286     */
1287    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1288    /**
1289     * Indicates the view is selected and that its window has the focus.
1290     *
1291     * @see #SELECTED_STATE_SET
1292     * @see #WINDOW_FOCUSED_STATE_SET
1293     */
1294    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1295    // Triples
1296    /**
1297     * Indicates the view is enabled, focused and selected.
1298     *
1299     * @see #ENABLED_STATE_SET
1300     * @see #FOCUSED_STATE_SET
1301     * @see #SELECTED_STATE_SET
1302     */
1303    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1304    /**
1305     * Indicates the view is enabled, focused and its window has the focus.
1306     *
1307     * @see #ENABLED_STATE_SET
1308     * @see #FOCUSED_STATE_SET
1309     * @see #WINDOW_FOCUSED_STATE_SET
1310     */
1311    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1312    /**
1313     * Indicates the view is enabled, selected and its window has the focus.
1314     *
1315     * @see #ENABLED_STATE_SET
1316     * @see #SELECTED_STATE_SET
1317     * @see #WINDOW_FOCUSED_STATE_SET
1318     */
1319    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1320    /**
1321     * Indicates the view is focused, selected and its window has the focus.
1322     *
1323     * @see #FOCUSED_STATE_SET
1324     * @see #SELECTED_STATE_SET
1325     * @see #WINDOW_FOCUSED_STATE_SET
1326     */
1327    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1328    /**
1329     * Indicates the view is enabled, focused, selected and its window
1330     * has the focus.
1331     *
1332     * @see #ENABLED_STATE_SET
1333     * @see #FOCUSED_STATE_SET
1334     * @see #SELECTED_STATE_SET
1335     * @see #WINDOW_FOCUSED_STATE_SET
1336     */
1337    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1338    /**
1339     * Indicates the view is pressed and its window has the focus.
1340     *
1341     * @see #PRESSED_STATE_SET
1342     * @see #WINDOW_FOCUSED_STATE_SET
1343     */
1344    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1345    /**
1346     * Indicates the view is pressed and selected.
1347     *
1348     * @see #PRESSED_STATE_SET
1349     * @see #SELECTED_STATE_SET
1350     */
1351    protected static final int[] PRESSED_SELECTED_STATE_SET;
1352    /**
1353     * Indicates the view is pressed, selected and its window has the focus.
1354     *
1355     * @see #PRESSED_STATE_SET
1356     * @see #SELECTED_STATE_SET
1357     * @see #WINDOW_FOCUSED_STATE_SET
1358     */
1359    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1360    /**
1361     * Indicates the view is pressed and focused.
1362     *
1363     * @see #PRESSED_STATE_SET
1364     * @see #FOCUSED_STATE_SET
1365     */
1366    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1367    /**
1368     * Indicates the view is pressed, focused and its window has the focus.
1369     *
1370     * @see #PRESSED_STATE_SET
1371     * @see #FOCUSED_STATE_SET
1372     * @see #WINDOW_FOCUSED_STATE_SET
1373     */
1374    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1375    /**
1376     * Indicates the view is pressed, focused and selected.
1377     *
1378     * @see #PRESSED_STATE_SET
1379     * @see #SELECTED_STATE_SET
1380     * @see #FOCUSED_STATE_SET
1381     */
1382    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1383    /**
1384     * Indicates the view is pressed, focused, selected and its window has the focus.
1385     *
1386     * @see #PRESSED_STATE_SET
1387     * @see #FOCUSED_STATE_SET
1388     * @see #SELECTED_STATE_SET
1389     * @see #WINDOW_FOCUSED_STATE_SET
1390     */
1391    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1392    /**
1393     * Indicates the view is pressed and enabled.
1394     *
1395     * @see #PRESSED_STATE_SET
1396     * @see #ENABLED_STATE_SET
1397     */
1398    protected static final int[] PRESSED_ENABLED_STATE_SET;
1399    /**
1400     * Indicates the view is pressed, enabled and its window has the focus.
1401     *
1402     * @see #PRESSED_STATE_SET
1403     * @see #ENABLED_STATE_SET
1404     * @see #WINDOW_FOCUSED_STATE_SET
1405     */
1406    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1407    /**
1408     * Indicates the view is pressed, enabled and selected.
1409     *
1410     * @see #PRESSED_STATE_SET
1411     * @see #ENABLED_STATE_SET
1412     * @see #SELECTED_STATE_SET
1413     */
1414    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1415    /**
1416     * Indicates the view is pressed, enabled, selected and its window has the
1417     * focus.
1418     *
1419     * @see #PRESSED_STATE_SET
1420     * @see #ENABLED_STATE_SET
1421     * @see #SELECTED_STATE_SET
1422     * @see #WINDOW_FOCUSED_STATE_SET
1423     */
1424    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1425    /**
1426     * Indicates the view is pressed, enabled and focused.
1427     *
1428     * @see #PRESSED_STATE_SET
1429     * @see #ENABLED_STATE_SET
1430     * @see #FOCUSED_STATE_SET
1431     */
1432    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1433    /**
1434     * Indicates the view is pressed, enabled, focused and its window has the
1435     * focus.
1436     *
1437     * @see #PRESSED_STATE_SET
1438     * @see #ENABLED_STATE_SET
1439     * @see #FOCUSED_STATE_SET
1440     * @see #WINDOW_FOCUSED_STATE_SET
1441     */
1442    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1443    /**
1444     * Indicates the view is pressed, enabled, focused and selected.
1445     *
1446     * @see #PRESSED_STATE_SET
1447     * @see #ENABLED_STATE_SET
1448     * @see #SELECTED_STATE_SET
1449     * @see #FOCUSED_STATE_SET
1450     */
1451    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1452    /**
1453     * Indicates the view is pressed, enabled, focused, selected and its window
1454     * has the focus.
1455     *
1456     * @see #PRESSED_STATE_SET
1457     * @see #ENABLED_STATE_SET
1458     * @see #SELECTED_STATE_SET
1459     * @see #FOCUSED_STATE_SET
1460     * @see #WINDOW_FOCUSED_STATE_SET
1461     */
1462    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1463
1464    static {
1465        EMPTY_STATE_SET = StateSet.get(0);
1466
1467        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1468
1469        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1470        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1471                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1472
1473        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1474        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1475                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1476        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1477                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1478        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1479                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1480                        | StateSet.VIEW_STATE_FOCUSED);
1481
1482        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1483        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1484                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1485        ENABLED_SELECTED_STATE_SET = StateSet.get(
1486                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1487        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1488                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1489                        | StateSet.VIEW_STATE_ENABLED);
1490        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1491                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1492        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1493                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1494                        | StateSet.VIEW_STATE_ENABLED);
1495        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1496                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1497                        | StateSet.VIEW_STATE_ENABLED);
1498        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1499                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1500                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1501
1502        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1503        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1504                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1505        PRESSED_SELECTED_STATE_SET = StateSet.get(
1506                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1507        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1508                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1509                        | StateSet.VIEW_STATE_PRESSED);
1510        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1511                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1512        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1513                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1514                        | StateSet.VIEW_STATE_PRESSED);
1515        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1516                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1517                        | StateSet.VIEW_STATE_PRESSED);
1518        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1519                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1520                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1521        PRESSED_ENABLED_STATE_SET = StateSet.get(
1522                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1523        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1524                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1525                        | StateSet.VIEW_STATE_PRESSED);
1526        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1527                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1528                        | StateSet.VIEW_STATE_PRESSED);
1529        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1530                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1531                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1532        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1533                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1534                        | StateSet.VIEW_STATE_PRESSED);
1535        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1536                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1537                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1538        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1539                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1540                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1541        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1542                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1543                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1544                        | StateSet.VIEW_STATE_PRESSED);
1545    }
1546
1547    /**
1548     * Accessibility event types that are dispatched for text population.
1549     */
1550    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1551            AccessibilityEvent.TYPE_VIEW_CLICKED
1552            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1553            | AccessibilityEvent.TYPE_VIEW_SELECTED
1554            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1555            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1556            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1557            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1558            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1559            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1560            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1561            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1562
1563    /**
1564     * Temporary Rect currently for use in setBackground().  This will probably
1565     * be extended in the future to hold our own class with more than just
1566     * a Rect. :)
1567     */
1568    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1569
1570    /**
1571     * Map used to store views' tags.
1572     */
1573    private SparseArray<Object> mKeyedTags;
1574
1575    /**
1576     * The next available accessibility id.
1577     */
1578    private static int sNextAccessibilityViewId;
1579
1580    /**
1581     * The animation currently associated with this view.
1582     * @hide
1583     */
1584    protected Animation mCurrentAnimation = null;
1585
1586    /**
1587     * Width as measured during measure pass.
1588     * {@hide}
1589     */
1590    @ViewDebug.ExportedProperty(category = "measurement")
1591    int mMeasuredWidth;
1592
1593    /**
1594     * Height as measured during measure pass.
1595     * {@hide}
1596     */
1597    @ViewDebug.ExportedProperty(category = "measurement")
1598    int mMeasuredHeight;
1599
1600    /**
1601     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1602     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1603     * its display list. This flag, used only when hw accelerated, allows us to clear the
1604     * flag while retaining this information until it's needed (at getDisplayList() time and
1605     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1606     *
1607     * {@hide}
1608     */
1609    boolean mRecreateDisplayList = false;
1610
1611    /**
1612     * The view's identifier.
1613     * {@hide}
1614     *
1615     * @see #setId(int)
1616     * @see #getId()
1617     */
1618    @IdRes
1619    @ViewDebug.ExportedProperty(resolveId = true)
1620    int mID = NO_ID;
1621
1622    /**
1623     * The stable ID of this view for accessibility purposes.
1624     */
1625    int mAccessibilityViewId = NO_ID;
1626
1627    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1628
1629    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1630
1631    /**
1632     * The view's tag.
1633     * {@hide}
1634     *
1635     * @see #setTag(Object)
1636     * @see #getTag()
1637     */
1638    protected Object mTag = null;
1639
1640    // for mPrivateFlags:
1641    /** {@hide} */
1642    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1643    /** {@hide} */
1644    static final int PFLAG_FOCUSED                     = 0x00000002;
1645    /** {@hide} */
1646    static final int PFLAG_SELECTED                    = 0x00000004;
1647    /** {@hide} */
1648    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1649    /** {@hide} */
1650    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1651    /** {@hide} */
1652    static final int PFLAG_DRAWN                       = 0x00000020;
1653    /**
1654     * When this flag is set, this view is running an animation on behalf of its
1655     * children and should therefore not cancel invalidate requests, even if they
1656     * lie outside of this view's bounds.
1657     *
1658     * {@hide}
1659     */
1660    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1661    /** {@hide} */
1662    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1663    /** {@hide} */
1664    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1665    /** {@hide} */
1666    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1667    /** {@hide} */
1668    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1669    /** {@hide} */
1670    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1671    /** {@hide} */
1672    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1673
1674    private static final int PFLAG_PRESSED             = 0x00004000;
1675
1676    /** {@hide} */
1677    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1678    /**
1679     * Flag used to indicate that this view should be drawn once more (and only once
1680     * more) after its animation has completed.
1681     * {@hide}
1682     */
1683    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1684
1685    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1686
1687    /**
1688     * Indicates that the View returned true when onSetAlpha() was called and that
1689     * the alpha must be restored.
1690     * {@hide}
1691     */
1692    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1693
1694    /**
1695     * Set by {@link #setScrollContainer(boolean)}.
1696     */
1697    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1698
1699    /**
1700     * Set by {@link #setScrollContainer(boolean)}.
1701     */
1702    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1703
1704    /**
1705     * View flag indicating whether this view was invalidated (fully or partially.)
1706     *
1707     * @hide
1708     */
1709    static final int PFLAG_DIRTY                       = 0x00200000;
1710
1711    /**
1712     * View flag indicating whether this view was invalidated by an opaque
1713     * invalidate request.
1714     *
1715     * @hide
1716     */
1717    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1718
1719    /**
1720     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1721     *
1722     * @hide
1723     */
1724    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1725
1726    /**
1727     * Indicates whether the background is opaque.
1728     *
1729     * @hide
1730     */
1731    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1732
1733    /**
1734     * Indicates whether the scrollbars are opaque.
1735     *
1736     * @hide
1737     */
1738    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1739
1740    /**
1741     * Indicates whether the view is opaque.
1742     *
1743     * @hide
1744     */
1745    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1746
1747    /**
1748     * Indicates a prepressed state;
1749     * the short time between ACTION_DOWN and recognizing
1750     * a 'real' press. Prepressed is used to recognize quick taps
1751     * even when they are shorter than ViewConfiguration.getTapTimeout().
1752     *
1753     * @hide
1754     */
1755    private static final int PFLAG_PREPRESSED          = 0x02000000;
1756
1757    /**
1758     * Indicates whether the view is temporarily detached.
1759     *
1760     * @hide
1761     */
1762    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1763
1764    /**
1765     * Indicates that we should awaken scroll bars once attached
1766     *
1767     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1768     * during window attachment and it is no longer needed. Feel free to repurpose it.
1769     *
1770     * @hide
1771     */
1772    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1773
1774    /**
1775     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1776     * @hide
1777     */
1778    private static final int PFLAG_HOVERED             = 0x10000000;
1779
1780    /**
1781     * no longer needed, should be reused
1782     */
1783    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1784
1785    /** {@hide} */
1786    static final int PFLAG_ACTIVATED                   = 0x40000000;
1787
1788    /**
1789     * Indicates that this view was specifically invalidated, not just dirtied because some
1790     * child view was invalidated. The flag is used to determine when we need to recreate
1791     * a view's display list (as opposed to just returning a reference to its existing
1792     * display list).
1793     *
1794     * @hide
1795     */
1796    static final int PFLAG_INVALIDATED                 = 0x80000000;
1797
1798    /**
1799     * Masks for mPrivateFlags2, as generated by dumpFlags():
1800     *
1801     * |-------|-------|-------|-------|
1802     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1803     *                                1  PFLAG2_DRAG_HOVERED
1804     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1805     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1806     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1807     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1808     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1809     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1810     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1811     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1812     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1813     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1814     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1815     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1816     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1817     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1818     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1819     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1820     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1821     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1822     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1823     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1824     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1825     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1826     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1827     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1828     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1829     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1830     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1831     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1832     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1833     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1834     *    1                              PFLAG2_PADDING_RESOLVED
1835     *   1                               PFLAG2_DRAWABLE_RESOLVED
1836     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1837     * |-------|-------|-------|-------|
1838     */
1839
1840    /**
1841     * Indicates that this view has reported that it can accept the current drag's content.
1842     * Cleared when the drag operation concludes.
1843     * @hide
1844     */
1845    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1846
1847    /**
1848     * Indicates that this view is currently directly under the drag location in a
1849     * drag-and-drop operation involving content that it can accept.  Cleared when
1850     * the drag exits the view, or when the drag operation concludes.
1851     * @hide
1852     */
1853    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1854
1855    /** @hide */
1856    @IntDef({
1857        LAYOUT_DIRECTION_LTR,
1858        LAYOUT_DIRECTION_RTL,
1859        LAYOUT_DIRECTION_INHERIT,
1860        LAYOUT_DIRECTION_LOCALE
1861    })
1862    @Retention(RetentionPolicy.SOURCE)
1863    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1864    public @interface LayoutDir {}
1865
1866    /** @hide */
1867    @IntDef({
1868        LAYOUT_DIRECTION_LTR,
1869        LAYOUT_DIRECTION_RTL
1870    })
1871    @Retention(RetentionPolicy.SOURCE)
1872    public @interface ResolvedLayoutDir {}
1873
1874    /**
1875     * Horizontal layout direction of this view is from Left to Right.
1876     * Use with {@link #setLayoutDirection}.
1877     */
1878    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1879
1880    /**
1881     * Horizontal layout direction of this view is from Right to Left.
1882     * Use with {@link #setLayoutDirection}.
1883     */
1884    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1885
1886    /**
1887     * Horizontal layout direction of this view is inherited from its parent.
1888     * Use with {@link #setLayoutDirection}.
1889     */
1890    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1891
1892    /**
1893     * Horizontal layout direction of this view is from deduced from the default language
1894     * script for the locale. Use with {@link #setLayoutDirection}.
1895     */
1896    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1897
1898    /**
1899     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1900     * @hide
1901     */
1902    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1903
1904    /**
1905     * Mask for use with private flags indicating bits used for horizontal layout direction.
1906     * @hide
1907     */
1908    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1909
1910    /**
1911     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1912     * right-to-left direction.
1913     * @hide
1914     */
1915    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1916
1917    /**
1918     * Indicates whether the view horizontal layout direction has been resolved.
1919     * @hide
1920     */
1921    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1922
1923    /**
1924     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1925     * @hide
1926     */
1927    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1928            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1929
1930    /*
1931     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1932     * flag value.
1933     * @hide
1934     */
1935    private static final int[] LAYOUT_DIRECTION_FLAGS = {
1936            LAYOUT_DIRECTION_LTR,
1937            LAYOUT_DIRECTION_RTL,
1938            LAYOUT_DIRECTION_INHERIT,
1939            LAYOUT_DIRECTION_LOCALE
1940    };
1941
1942    /**
1943     * Default horizontal layout direction.
1944     */
1945    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1946
1947    /**
1948     * Default horizontal layout direction.
1949     * @hide
1950     */
1951    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1952
1953    /**
1954     * Text direction is inherited through {@link ViewGroup}
1955     */
1956    public static final int TEXT_DIRECTION_INHERIT = 0;
1957
1958    /**
1959     * Text direction is using "first strong algorithm". The first strong directional character
1960     * determines the paragraph direction. If there is no strong directional character, the
1961     * paragraph direction is the view's resolved layout direction.
1962     */
1963    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1964
1965    /**
1966     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1967     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1968     * If there are neither, the paragraph direction is the view's resolved layout direction.
1969     */
1970    public static final int TEXT_DIRECTION_ANY_RTL = 2;
1971
1972    /**
1973     * Text direction is forced to LTR.
1974     */
1975    public static final int TEXT_DIRECTION_LTR = 3;
1976
1977    /**
1978     * Text direction is forced to RTL.
1979     */
1980    public static final int TEXT_DIRECTION_RTL = 4;
1981
1982    /**
1983     * Text direction is coming from the system Locale.
1984     */
1985    public static final int TEXT_DIRECTION_LOCALE = 5;
1986
1987    /**
1988     * Text direction is using "first strong algorithm". The first strong directional character
1989     * determines the paragraph direction. If there is no strong directional character, the
1990     * paragraph direction is LTR.
1991     */
1992    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
1993
1994    /**
1995     * Text direction is using "first strong algorithm". The first strong directional character
1996     * determines the paragraph direction. If there is no strong directional character, the
1997     * paragraph direction is RTL.
1998     */
1999    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2000
2001    /**
2002     * Default text direction is inherited
2003     */
2004    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2005
2006    /**
2007     * Default resolved text direction
2008     * @hide
2009     */
2010    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2011
2012    /**
2013     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2014     * @hide
2015     */
2016    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2017
2018    /**
2019     * Mask for use with private flags indicating bits used for text direction.
2020     * @hide
2021     */
2022    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2023            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2024
2025    /**
2026     * Array of text direction flags for mapping attribute "textDirection" to correct
2027     * flag value.
2028     * @hide
2029     */
2030    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2031            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2032            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2033            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2034            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2035            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2036            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2037            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2038            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2039    };
2040
2041    /**
2042     * Indicates whether the view text direction has been resolved.
2043     * @hide
2044     */
2045    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2046            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2047
2048    /**
2049     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2050     * @hide
2051     */
2052    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2053
2054    /**
2055     * Mask for use with private flags indicating bits used for resolved text direction.
2056     * @hide
2057     */
2058    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2059            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2060
2061    /**
2062     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2063     * @hide
2064     */
2065    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2066            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2067
2068    /** @hide */
2069    @IntDef({
2070        TEXT_ALIGNMENT_INHERIT,
2071        TEXT_ALIGNMENT_GRAVITY,
2072        TEXT_ALIGNMENT_CENTER,
2073        TEXT_ALIGNMENT_TEXT_START,
2074        TEXT_ALIGNMENT_TEXT_END,
2075        TEXT_ALIGNMENT_VIEW_START,
2076        TEXT_ALIGNMENT_VIEW_END
2077    })
2078    @Retention(RetentionPolicy.SOURCE)
2079    public @interface TextAlignment {}
2080
2081    /**
2082     * Default text alignment. The text alignment of this View is inherited from its parent.
2083     * Use with {@link #setTextAlignment(int)}
2084     */
2085    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2086
2087    /**
2088     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2089     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2090     *
2091     * Use with {@link #setTextAlignment(int)}
2092     */
2093    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2094
2095    /**
2096     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2097     *
2098     * Use with {@link #setTextAlignment(int)}
2099     */
2100    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2101
2102    /**
2103     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2104     *
2105     * Use with {@link #setTextAlignment(int)}
2106     */
2107    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2108
2109    /**
2110     * Center the paragraph, e.g. ALIGN_CENTER.
2111     *
2112     * Use with {@link #setTextAlignment(int)}
2113     */
2114    public static final int TEXT_ALIGNMENT_CENTER = 4;
2115
2116    /**
2117     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2118     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2119     *
2120     * Use with {@link #setTextAlignment(int)}
2121     */
2122    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2123
2124    /**
2125     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2126     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2127     *
2128     * Use with {@link #setTextAlignment(int)}
2129     */
2130    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2131
2132    /**
2133     * Default text alignment is inherited
2134     */
2135    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2136
2137    /**
2138     * Default resolved text alignment
2139     * @hide
2140     */
2141    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2142
2143    /**
2144      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2145      * @hide
2146      */
2147    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2148
2149    /**
2150      * Mask for use with private flags indicating bits used for text alignment.
2151      * @hide
2152      */
2153    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2154
2155    /**
2156     * Array of text direction flags for mapping attribute "textAlignment" to correct
2157     * flag value.
2158     * @hide
2159     */
2160    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2161            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2162            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2163            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2164            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2165            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2166            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2167            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2168    };
2169
2170    /**
2171     * Indicates whether the view text alignment has been resolved.
2172     * @hide
2173     */
2174    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2175
2176    /**
2177     * Bit shift to get the resolved text alignment.
2178     * @hide
2179     */
2180    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2181
2182    /**
2183     * Mask for use with private flags indicating bits used for text alignment.
2184     * @hide
2185     */
2186    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2187            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2188
2189    /**
2190     * Indicates whether if the view text alignment has been resolved to gravity
2191     */
2192    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2193            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2194
2195    // Accessiblity constants for mPrivateFlags2
2196
2197    /**
2198     * Shift for the bits in {@link #mPrivateFlags2} related to the
2199     * "importantForAccessibility" attribute.
2200     */
2201    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2202
2203    /**
2204     * Automatically determine whether a view is important for accessibility.
2205     */
2206    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2207
2208    /**
2209     * The view is important for accessibility.
2210     */
2211    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2212
2213    /**
2214     * The view is not important for accessibility.
2215     */
2216    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2217
2218    /**
2219     * The view is not important for accessibility, nor are any of its
2220     * descendant views.
2221     */
2222    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2223
2224    /**
2225     * The default whether the view is important for accessibility.
2226     */
2227    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2228
2229    /**
2230     * Mask for obtainig the bits which specify how to determine
2231     * whether a view is important for accessibility.
2232     */
2233    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2234        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2235        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2236        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2237
2238    /**
2239     * Shift for the bits in {@link #mPrivateFlags2} related to the
2240     * "accessibilityLiveRegion" attribute.
2241     */
2242    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2243
2244    /**
2245     * Live region mode specifying that accessibility services should not
2246     * automatically announce changes to this view. This is the default live
2247     * region mode for most views.
2248     * <p>
2249     * Use with {@link #setAccessibilityLiveRegion(int)}.
2250     */
2251    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2252
2253    /**
2254     * Live region mode specifying that accessibility services should announce
2255     * changes to this view.
2256     * <p>
2257     * Use with {@link #setAccessibilityLiveRegion(int)}.
2258     */
2259    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2260
2261    /**
2262     * Live region mode specifying that accessibility services should interrupt
2263     * ongoing speech to immediately announce changes to this view.
2264     * <p>
2265     * Use with {@link #setAccessibilityLiveRegion(int)}.
2266     */
2267    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2268
2269    /**
2270     * The default whether the view is important for accessibility.
2271     */
2272    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2273
2274    /**
2275     * Mask for obtaining the bits which specify a view's accessibility live
2276     * region mode.
2277     */
2278    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2279            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2280            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2281
2282    /**
2283     * Flag indicating whether a view has accessibility focus.
2284     */
2285    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2286
2287    /**
2288     * Flag whether the accessibility state of the subtree rooted at this view changed.
2289     */
2290    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2291
2292    /**
2293     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2294     * is used to check whether later changes to the view's transform should invalidate the
2295     * view to force the quickReject test to run again.
2296     */
2297    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2298
2299    /**
2300     * Flag indicating that start/end padding has been resolved into left/right padding
2301     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2302     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2303     * during measurement. In some special cases this is required such as when an adapter-based
2304     * view measures prospective children without attaching them to a window.
2305     */
2306    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2307
2308    /**
2309     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2310     */
2311    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2312
2313    /**
2314     * Indicates that the view is tracking some sort of transient state
2315     * that the app should not need to be aware of, but that the framework
2316     * should take special care to preserve.
2317     */
2318    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2319
2320    /**
2321     * Group of bits indicating that RTL properties resolution is done.
2322     */
2323    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2324            PFLAG2_TEXT_DIRECTION_RESOLVED |
2325            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2326            PFLAG2_PADDING_RESOLVED |
2327            PFLAG2_DRAWABLE_RESOLVED;
2328
2329    // There are a couple of flags left in mPrivateFlags2
2330
2331    /* End of masks for mPrivateFlags2 */
2332
2333    /**
2334     * Masks for mPrivateFlags3, as generated by dumpFlags():
2335     *
2336     * |-------|-------|-------|-------|
2337     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2338     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2339     *                               1   PFLAG3_IS_LAID_OUT
2340     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2341     *                             1     PFLAG3_CALLED_SUPER
2342     *                            1      PFLAG3_APPLYING_INSETS
2343     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2344     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2345     *                         1         PFLAG3_ASSIST_BLOCKED
2346     * |-------|-------|-------|-------|
2347     */
2348
2349    /**
2350     * Flag indicating that view has a transform animation set on it. This is used to track whether
2351     * an animation is cleared between successive frames, in order to tell the associated
2352     * DisplayList to clear its animation matrix.
2353     */
2354    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2355
2356    /**
2357     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2358     * animation is cleared between successive frames, in order to tell the associated
2359     * DisplayList to restore its alpha value.
2360     */
2361    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2362
2363    /**
2364     * Flag indicating that the view has been through at least one layout since it
2365     * was last attached to a window.
2366     */
2367    static final int PFLAG3_IS_LAID_OUT = 0x4;
2368
2369    /**
2370     * Flag indicating that a call to measure() was skipped and should be done
2371     * instead when layout() is invoked.
2372     */
2373    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2374
2375    /**
2376     * Flag indicating that an overridden method correctly called down to
2377     * the superclass implementation as required by the API spec.
2378     */
2379    static final int PFLAG3_CALLED_SUPER = 0x10;
2380
2381    /**
2382     * Flag indicating that we're in the process of applying window insets.
2383     */
2384    static final int PFLAG3_APPLYING_INSETS = 0x20;
2385
2386    /**
2387     * Flag indicating that we're in the process of fitting system windows using the old method.
2388     */
2389    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2390
2391    /**
2392     * Flag indicating that nested scrolling is enabled for this view.
2393     * The view will optionally cooperate with views up its parent chain to allow for
2394     * integrated nested scrolling along the same axis.
2395     */
2396    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2397
2398    /**
2399     * Flag indicating that the bottom scroll indicator should be displayed
2400     * when this view can scroll up.
2401     */
2402    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2403
2404    /**
2405     * Flag indicating that the bottom scroll indicator should be displayed
2406     * when this view can scroll down.
2407     */
2408    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2409
2410    /**
2411     * Flag indicating that the left scroll indicator should be displayed
2412     * when this view can scroll left.
2413     */
2414    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2415
2416    /**
2417     * Flag indicating that the right scroll indicator should be displayed
2418     * when this view can scroll right.
2419     */
2420    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2421
2422    /**
2423     * Flag indicating that the start scroll indicator should be displayed
2424     * when this view can scroll in the start direction.
2425     */
2426    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2427
2428    /**
2429     * Flag indicating that the end scroll indicator should be displayed
2430     * when this view can scroll in the end direction.
2431     */
2432    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2433
2434    /* End of masks for mPrivateFlags3 */
2435
2436    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2437
2438    static final int SCROLL_INDICATORS_NONE = 0x0000;
2439
2440    /**
2441     * Mask for use with setFlags indicating bits used for indicating which
2442     * scroll indicators are enabled.
2443     */
2444    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2445            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2446            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2447            | PFLAG3_SCROLL_INDICATOR_END;
2448
2449    /**
2450     * Left-shift required to translate between public scroll indicator flags
2451     * and internal PFLAGS3 flags. When used as a right-shift, translates
2452     * PFLAGS3 flags to public flags.
2453     */
2454    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2455
2456    /** @hide */
2457    @Retention(RetentionPolicy.SOURCE)
2458    @IntDef(flag = true,
2459            value = {
2460                    SCROLL_INDICATOR_TOP,
2461                    SCROLL_INDICATOR_BOTTOM,
2462                    SCROLL_INDICATOR_LEFT,
2463                    SCROLL_INDICATOR_RIGHT,
2464                    SCROLL_INDICATOR_START,
2465                    SCROLL_INDICATOR_END,
2466            })
2467    public @interface ScrollIndicators {}
2468
2469    /**
2470     * Scroll indicator direction for the top edge of the view.
2471     *
2472     * @see #setScrollIndicators(int)
2473     * @see #setScrollIndicators(int, int)
2474     * @see #getScrollIndicators()
2475     */
2476    public static final int SCROLL_INDICATOR_TOP =
2477            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2478
2479    /**
2480     * Scroll indicator direction for the bottom edge of the view.
2481     *
2482     * @see #setScrollIndicators(int)
2483     * @see #setScrollIndicators(int, int)
2484     * @see #getScrollIndicators()
2485     */
2486    public static final int SCROLL_INDICATOR_BOTTOM =
2487            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2488
2489    /**
2490     * Scroll indicator direction for the left edge of the view.
2491     *
2492     * @see #setScrollIndicators(int)
2493     * @see #setScrollIndicators(int, int)
2494     * @see #getScrollIndicators()
2495     */
2496    public static final int SCROLL_INDICATOR_LEFT =
2497            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2498
2499    /**
2500     * Scroll indicator direction for the right edge of the view.
2501     *
2502     * @see #setScrollIndicators(int)
2503     * @see #setScrollIndicators(int, int)
2504     * @see #getScrollIndicators()
2505     */
2506    public static final int SCROLL_INDICATOR_RIGHT =
2507            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2508
2509    /**
2510     * Scroll indicator direction for the starting edge of the view.
2511     * <p>
2512     * Resolved according to the view's layout direction, see
2513     * {@link #getLayoutDirection()} for more information.
2514     *
2515     * @see #setScrollIndicators(int)
2516     * @see #setScrollIndicators(int, int)
2517     * @see #getScrollIndicators()
2518     */
2519    public static final int SCROLL_INDICATOR_START =
2520            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2521
2522    /**
2523     * Scroll indicator direction for the ending edge of the view.
2524     * <p>
2525     * Resolved according to the view's layout direction, see
2526     * {@link #getLayoutDirection()} for more information.
2527     *
2528     * @see #setScrollIndicators(int)
2529     * @see #setScrollIndicators(int, int)
2530     * @see #getScrollIndicators()
2531     */
2532    public static final int SCROLL_INDICATOR_END =
2533            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2534
2535    /**
2536     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2537     * into this view.<p>
2538     */
2539    static final int PFLAG3_ASSIST_BLOCKED = 0x100;
2540
2541    /**
2542     * Always allow a user to over-scroll this view, provided it is a
2543     * view that can scroll.
2544     *
2545     * @see #getOverScrollMode()
2546     * @see #setOverScrollMode(int)
2547     */
2548    public static final int OVER_SCROLL_ALWAYS = 0;
2549
2550    /**
2551     * Allow a user to over-scroll this view only if the content is large
2552     * enough to meaningfully scroll, provided it is a view that can scroll.
2553     *
2554     * @see #getOverScrollMode()
2555     * @see #setOverScrollMode(int)
2556     */
2557    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2558
2559    /**
2560     * Never allow a user to over-scroll this view.
2561     *
2562     * @see #getOverScrollMode()
2563     * @see #setOverScrollMode(int)
2564     */
2565    public static final int OVER_SCROLL_NEVER = 2;
2566
2567    /**
2568     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2569     * requested the system UI (status bar) to be visible (the default).
2570     *
2571     * @see #setSystemUiVisibility(int)
2572     */
2573    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2574
2575    /**
2576     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2577     * system UI to enter an unobtrusive "low profile" mode.
2578     *
2579     * <p>This is for use in games, book readers, video players, or any other
2580     * "immersive" application where the usual system chrome is deemed too distracting.
2581     *
2582     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2583     *
2584     * @see #setSystemUiVisibility(int)
2585     */
2586    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2587
2588    /**
2589     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2590     * system navigation be temporarily hidden.
2591     *
2592     * <p>This is an even less obtrusive state than that called for by
2593     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2594     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2595     * those to disappear. This is useful (in conjunction with the
2596     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2597     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2598     * window flags) for displaying content using every last pixel on the display.
2599     *
2600     * <p>There is a limitation: because navigation controls are so important, the least user
2601     * interaction will cause them to reappear immediately.  When this happens, both
2602     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2603     * so that both elements reappear at the same time.
2604     *
2605     * @see #setSystemUiVisibility(int)
2606     */
2607    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2608
2609    /**
2610     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2611     * into the normal fullscreen mode so that its content can take over the screen
2612     * while still allowing the user to interact with the application.
2613     *
2614     * <p>This has the same visual effect as
2615     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2616     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2617     * meaning that non-critical screen decorations (such as the status bar) will be
2618     * hidden while the user is in the View's window, focusing the experience on
2619     * that content.  Unlike the window flag, if you are using ActionBar in
2620     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2621     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2622     * hide the action bar.
2623     *
2624     * <p>This approach to going fullscreen is best used over the window flag when
2625     * it is a transient state -- that is, the application does this at certain
2626     * points in its user interaction where it wants to allow the user to focus
2627     * on content, but not as a continuous state.  For situations where the application
2628     * would like to simply stay full screen the entire time (such as a game that
2629     * wants to take over the screen), the
2630     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2631     * is usually a better approach.  The state set here will be removed by the system
2632     * in various situations (such as the user moving to another application) like
2633     * the other system UI states.
2634     *
2635     * <p>When using this flag, the application should provide some easy facility
2636     * for the user to go out of it.  A common example would be in an e-book
2637     * reader, where tapping on the screen brings back whatever screen and UI
2638     * decorations that had been hidden while the user was immersed in reading
2639     * the book.
2640     *
2641     * @see #setSystemUiVisibility(int)
2642     */
2643    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2644
2645    /**
2646     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2647     * flags, we would like a stable view of the content insets given to
2648     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2649     * will always represent the worst case that the application can expect
2650     * as a continuous state.  In the stock Android UI this is the space for
2651     * the system bar, nav bar, and status bar, but not more transient elements
2652     * such as an input method.
2653     *
2654     * The stable layout your UI sees is based on the system UI modes you can
2655     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2656     * then you will get a stable layout for changes of the
2657     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2658     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2659     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2660     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2661     * with a stable layout.  (Note that you should avoid using
2662     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2663     *
2664     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2665     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2666     * then a hidden status bar will be considered a "stable" state for purposes
2667     * here.  This allows your UI to continually hide the status bar, while still
2668     * using the system UI flags to hide the action bar while still retaining
2669     * a stable layout.  Note that changing the window fullscreen flag will never
2670     * provide a stable layout for a clean transition.
2671     *
2672     * <p>If you are using ActionBar in
2673     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2674     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2675     * insets it adds to those given to the application.
2676     */
2677    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2678
2679    /**
2680     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2681     * to be laid out as if it has requested
2682     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2683     * allows it to avoid artifacts when switching in and out of that mode, at
2684     * the expense that some of its user interface may be covered by screen
2685     * decorations when they are shown.  You can perform layout of your inner
2686     * UI elements to account for the navigation system UI through the
2687     * {@link #fitSystemWindows(Rect)} method.
2688     */
2689    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2690
2691    /**
2692     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2693     * to be laid out as if it has requested
2694     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2695     * allows it to avoid artifacts when switching in and out of that mode, at
2696     * the expense that some of its user interface may be covered by screen
2697     * decorations when they are shown.  You can perform layout of your inner
2698     * UI elements to account for non-fullscreen system UI through the
2699     * {@link #fitSystemWindows(Rect)} method.
2700     */
2701    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2702
2703    /**
2704     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2705     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2706     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2707     * user interaction.
2708     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2709     * has an effect when used in combination with that flag.</p>
2710     */
2711    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2712
2713    /**
2714     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2715     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2716     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2717     * experience while also hiding the system bars.  If this flag is not set,
2718     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2719     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2720     * if the user swipes from the top of the screen.
2721     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2722     * system gestures, such as swiping from the top of the screen.  These transient system bars
2723     * will overlay app’s content, may have some degree of transparency, and will automatically
2724     * hide after a short timeout.
2725     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2726     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2727     * with one or both of those flags.</p>
2728     */
2729    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2730
2731    /**
2732     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2733     * is compatible with light status bar backgrounds.
2734     *
2735     * <p>For this to take effect, the window must request
2736     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2737     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2738     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2739     *         FLAG_TRANSLUCENT_STATUS}.
2740     *
2741     * @see android.R.attr#windowLightStatusBar
2742     */
2743    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2744
2745    /**
2746     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2747     */
2748    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2749
2750    /**
2751     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2752     */
2753    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2754
2755    /**
2756     * @hide
2757     *
2758     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2759     * out of the public fields to keep the undefined bits out of the developer's way.
2760     *
2761     * Flag to make the status bar not expandable.  Unless you also
2762     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2763     */
2764    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2765
2766    /**
2767     * @hide
2768     *
2769     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2770     * out of the public fields to keep the undefined bits out of the developer's way.
2771     *
2772     * Flag to hide notification icons and scrolling ticker text.
2773     */
2774    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2775
2776    /**
2777     * @hide
2778     *
2779     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2780     * out of the public fields to keep the undefined bits out of the developer's way.
2781     *
2782     * Flag to disable incoming notification alerts.  This will not block
2783     * icons, but it will block sound, vibrating and other visual or aural notifications.
2784     */
2785    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2786
2787    /**
2788     * @hide
2789     *
2790     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2791     * out of the public fields to keep the undefined bits out of the developer's way.
2792     *
2793     * Flag to hide only the scrolling ticker.  Note that
2794     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2795     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2796     */
2797    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2798
2799    /**
2800     * @hide
2801     *
2802     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2803     * out of the public fields to keep the undefined bits out of the developer's way.
2804     *
2805     * Flag to hide the center system info area.
2806     */
2807    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2808
2809    /**
2810     * @hide
2811     *
2812     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2813     * out of the public fields to keep the undefined bits out of the developer's way.
2814     *
2815     * Flag to hide only the home button.  Don't use this
2816     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2817     */
2818    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2819
2820    /**
2821     * @hide
2822     *
2823     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2824     * out of the public fields to keep the undefined bits out of the developer's way.
2825     *
2826     * Flag to hide only the back button. Don't use this
2827     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2828     */
2829    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2830
2831    /**
2832     * @hide
2833     *
2834     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2835     * out of the public fields to keep the undefined bits out of the developer's way.
2836     *
2837     * Flag to hide only the clock.  You might use this if your activity has
2838     * its own clock making the status bar's clock redundant.
2839     */
2840    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2841
2842    /**
2843     * @hide
2844     *
2845     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2846     * out of the public fields to keep the undefined bits out of the developer's way.
2847     *
2848     * Flag to hide only the recent apps button. Don't use this
2849     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2850     */
2851    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2852
2853    /**
2854     * @hide
2855     *
2856     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2857     * out of the public fields to keep the undefined bits out of the developer's way.
2858     *
2859     * Flag to disable the global search gesture. Don't use this
2860     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2861     */
2862    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2863
2864    /**
2865     * @hide
2866     *
2867     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2868     * out of the public fields to keep the undefined bits out of the developer's way.
2869     *
2870     * Flag to specify that the status bar is displayed in transient mode.
2871     */
2872    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2873
2874    /**
2875     * @hide
2876     *
2877     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2878     * out of the public fields to keep the undefined bits out of the developer's way.
2879     *
2880     * Flag to specify that the navigation bar is displayed in transient mode.
2881     */
2882    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2883
2884    /**
2885     * @hide
2886     *
2887     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2888     * out of the public fields to keep the undefined bits out of the developer's way.
2889     *
2890     * Flag to specify that the hidden status bar would like to be shown.
2891     */
2892    public static final int STATUS_BAR_UNHIDE = 0x10000000;
2893
2894    /**
2895     * @hide
2896     *
2897     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2898     * out of the public fields to keep the undefined bits out of the developer's way.
2899     *
2900     * Flag to specify that the hidden navigation bar would like to be shown.
2901     */
2902    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2903
2904    /**
2905     * @hide
2906     *
2907     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2908     * out of the public fields to keep the undefined bits out of the developer's way.
2909     *
2910     * Flag to specify that the status bar is displayed in translucent mode.
2911     */
2912    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2913
2914    /**
2915     * @hide
2916     *
2917     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2918     * out of the public fields to keep the undefined bits out of the developer's way.
2919     *
2920     * Flag to specify that the navigation bar is displayed in translucent mode.
2921     */
2922    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2923
2924    /**
2925     * @hide
2926     *
2927     * Whether Recents is visible or not.
2928     */
2929    public static final int RECENT_APPS_VISIBLE = 0x00004000;
2930
2931    /**
2932     * @hide
2933     *
2934     * Makes system ui transparent.
2935     */
2936    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2937
2938    /**
2939     * @hide
2940     */
2941    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2942
2943    /**
2944     * These are the system UI flags that can be cleared by events outside
2945     * of an application.  Currently this is just the ability to tap on the
2946     * screen while hiding the navigation bar to have it return.
2947     * @hide
2948     */
2949    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2950            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2951            | SYSTEM_UI_FLAG_FULLSCREEN;
2952
2953    /**
2954     * Flags that can impact the layout in relation to system UI.
2955     */
2956    public static final int SYSTEM_UI_LAYOUT_FLAGS =
2957            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2958            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2959
2960    /** @hide */
2961    @IntDef(flag = true,
2962            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2963    @Retention(RetentionPolicy.SOURCE)
2964    public @interface FindViewFlags {}
2965
2966    /**
2967     * Find views that render the specified text.
2968     *
2969     * @see #findViewsWithText(ArrayList, CharSequence, int)
2970     */
2971    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2972
2973    /**
2974     * Find find views that contain the specified content description.
2975     *
2976     * @see #findViewsWithText(ArrayList, CharSequence, int)
2977     */
2978    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2979
2980    /**
2981     * Find views that contain {@link AccessibilityNodeProvider}. Such
2982     * a View is a root of virtual view hierarchy and may contain the searched
2983     * text. If this flag is set Views with providers are automatically
2984     * added and it is a responsibility of the client to call the APIs of
2985     * the provider to determine whether the virtual tree rooted at this View
2986     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2987     * representing the virtual views with this text.
2988     *
2989     * @see #findViewsWithText(ArrayList, CharSequence, int)
2990     *
2991     * @hide
2992     */
2993    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2994
2995    /**
2996     * The undefined cursor position.
2997     *
2998     * @hide
2999     */
3000    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3001
3002    /**
3003     * Indicates that the screen has changed state and is now off.
3004     *
3005     * @see #onScreenStateChanged(int)
3006     */
3007    public static final int SCREEN_STATE_OFF = 0x0;
3008
3009    /**
3010     * Indicates that the screen has changed state and is now on.
3011     *
3012     * @see #onScreenStateChanged(int)
3013     */
3014    public static final int SCREEN_STATE_ON = 0x1;
3015
3016    /**
3017     * Indicates no axis of view scrolling.
3018     */
3019    public static final int SCROLL_AXIS_NONE = 0;
3020
3021    /**
3022     * Indicates scrolling along the horizontal axis.
3023     */
3024    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3025
3026    /**
3027     * Indicates scrolling along the vertical axis.
3028     */
3029    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3030
3031    /**
3032     * Controls the over-scroll mode for this view.
3033     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3034     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3035     * and {@link #OVER_SCROLL_NEVER}.
3036     */
3037    private int mOverScrollMode;
3038
3039    /**
3040     * The parent this view is attached to.
3041     * {@hide}
3042     *
3043     * @see #getParent()
3044     */
3045    protected ViewParent mParent;
3046
3047    /**
3048     * {@hide}
3049     */
3050    AttachInfo mAttachInfo;
3051
3052    /**
3053     * {@hide}
3054     */
3055    @ViewDebug.ExportedProperty(flagMapping = {
3056        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3057                name = "FORCE_LAYOUT"),
3058        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3059                name = "LAYOUT_REQUIRED"),
3060        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3061            name = "DRAWING_CACHE_INVALID", outputIf = false),
3062        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3063        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3064        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3065        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3066    }, formatToHexString = true)
3067    int mPrivateFlags;
3068    int mPrivateFlags2;
3069    int mPrivateFlags3;
3070
3071    /**
3072     * This view's request for the visibility of the status bar.
3073     * @hide
3074     */
3075    @ViewDebug.ExportedProperty(flagMapping = {
3076        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3077                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3078                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3079        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3080                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3081                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3082        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3083                                equals = SYSTEM_UI_FLAG_VISIBLE,
3084                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3085    }, formatToHexString = true)
3086    int mSystemUiVisibility;
3087
3088    /**
3089     * Reference count for transient state.
3090     * @see #setHasTransientState(boolean)
3091     */
3092    int mTransientStateCount = 0;
3093
3094    /**
3095     * Count of how many windows this view has been attached to.
3096     */
3097    int mWindowAttachCount;
3098
3099    /**
3100     * The layout parameters associated with this view and used by the parent
3101     * {@link android.view.ViewGroup} to determine how this view should be
3102     * laid out.
3103     * {@hide}
3104     */
3105    protected ViewGroup.LayoutParams mLayoutParams;
3106
3107    /**
3108     * The view flags hold various views states.
3109     * {@hide}
3110     */
3111    @ViewDebug.ExportedProperty(formatToHexString = true)
3112    int mViewFlags;
3113
3114    static class TransformationInfo {
3115        /**
3116         * The transform matrix for the View. This transform is calculated internally
3117         * based on the translation, rotation, and scale properties.
3118         *
3119         * Do *not* use this variable directly; instead call getMatrix(), which will
3120         * load the value from the View's RenderNode.
3121         */
3122        private final Matrix mMatrix = new Matrix();
3123
3124        /**
3125         * The inverse transform matrix for the View. This transform is calculated
3126         * internally based on the translation, rotation, and scale properties.
3127         *
3128         * Do *not* use this variable directly; instead call getInverseMatrix(),
3129         * which will load the value from the View's RenderNode.
3130         */
3131        private Matrix mInverseMatrix;
3132
3133        /**
3134         * The opacity of the View. This is a value from 0 to 1, where 0 means
3135         * completely transparent and 1 means completely opaque.
3136         */
3137        @ViewDebug.ExportedProperty
3138        float mAlpha = 1f;
3139
3140        /**
3141         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3142         * property only used by transitions, which is composited with the other alpha
3143         * values to calculate the final visual alpha value.
3144         */
3145        float mTransitionAlpha = 1f;
3146    }
3147
3148    TransformationInfo mTransformationInfo;
3149
3150    /**
3151     * Current clip bounds. to which all drawing of this view are constrained.
3152     */
3153    Rect mClipBounds = null;
3154
3155    private boolean mLastIsOpaque;
3156
3157    /**
3158     * The distance in pixels from the left edge of this view's parent
3159     * to the left edge of this view.
3160     * {@hide}
3161     */
3162    @ViewDebug.ExportedProperty(category = "layout")
3163    protected int mLeft;
3164    /**
3165     * The distance in pixels from the left edge of this view's parent
3166     * to the right edge of this view.
3167     * {@hide}
3168     */
3169    @ViewDebug.ExportedProperty(category = "layout")
3170    protected int mRight;
3171    /**
3172     * The distance in pixels from the top edge of this view's parent
3173     * to the top edge of this view.
3174     * {@hide}
3175     */
3176    @ViewDebug.ExportedProperty(category = "layout")
3177    protected int mTop;
3178    /**
3179     * The distance in pixels from the top edge of this view's parent
3180     * to the bottom edge of this view.
3181     * {@hide}
3182     */
3183    @ViewDebug.ExportedProperty(category = "layout")
3184    protected int mBottom;
3185
3186    /**
3187     * The offset, in pixels, by which the content of this view is scrolled
3188     * horizontally.
3189     * {@hide}
3190     */
3191    @ViewDebug.ExportedProperty(category = "scrolling")
3192    protected int mScrollX;
3193    /**
3194     * The offset, in pixels, by which the content of this view is scrolled
3195     * vertically.
3196     * {@hide}
3197     */
3198    @ViewDebug.ExportedProperty(category = "scrolling")
3199    protected int mScrollY;
3200
3201    /**
3202     * The left padding in pixels, that is the distance in pixels between the
3203     * left edge of this view and the left edge of its content.
3204     * {@hide}
3205     */
3206    @ViewDebug.ExportedProperty(category = "padding")
3207    protected int mPaddingLeft = 0;
3208    /**
3209     * The right padding in pixels, that is the distance in pixels between the
3210     * right edge of this view and the right edge of its content.
3211     * {@hide}
3212     */
3213    @ViewDebug.ExportedProperty(category = "padding")
3214    protected int mPaddingRight = 0;
3215    /**
3216     * The top padding in pixels, that is the distance in pixels between the
3217     * top edge of this view and the top edge of its content.
3218     * {@hide}
3219     */
3220    @ViewDebug.ExportedProperty(category = "padding")
3221    protected int mPaddingTop;
3222    /**
3223     * The bottom padding in pixels, that is the distance in pixels between the
3224     * bottom edge of this view and the bottom edge of its content.
3225     * {@hide}
3226     */
3227    @ViewDebug.ExportedProperty(category = "padding")
3228    protected int mPaddingBottom;
3229
3230    /**
3231     * The layout insets in pixels, that is the distance in pixels between the
3232     * visible edges of this view its bounds.
3233     */
3234    private Insets mLayoutInsets;
3235
3236    /**
3237     * Briefly describes the view and is primarily used for accessibility support.
3238     */
3239    private CharSequence mContentDescription;
3240
3241    /**
3242     * Specifies the id of a view for which this view serves as a label for
3243     * accessibility purposes.
3244     */
3245    private int mLabelForId = View.NO_ID;
3246
3247    /**
3248     * Predicate for matching labeled view id with its label for
3249     * accessibility purposes.
3250     */
3251    private MatchLabelForPredicate mMatchLabelForPredicate;
3252
3253    /**
3254     * Specifies a view before which this one is visited in accessibility traversal.
3255     */
3256    private int mAccessibilityTraversalBeforeId = NO_ID;
3257
3258    /**
3259     * Specifies a view after which this one is visited in accessibility traversal.
3260     */
3261    private int mAccessibilityTraversalAfterId = NO_ID;
3262
3263    /**
3264     * Predicate for matching a view by its id.
3265     */
3266    private MatchIdPredicate mMatchIdPredicate;
3267
3268    /**
3269     * Cache the paddingRight set by the user to append to the scrollbar's size.
3270     *
3271     * @hide
3272     */
3273    @ViewDebug.ExportedProperty(category = "padding")
3274    protected int mUserPaddingRight;
3275
3276    /**
3277     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3278     *
3279     * @hide
3280     */
3281    @ViewDebug.ExportedProperty(category = "padding")
3282    protected int mUserPaddingBottom;
3283
3284    /**
3285     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3286     *
3287     * @hide
3288     */
3289    @ViewDebug.ExportedProperty(category = "padding")
3290    protected int mUserPaddingLeft;
3291
3292    /**
3293     * Cache the paddingStart set by the user to append to the scrollbar's size.
3294     *
3295     */
3296    @ViewDebug.ExportedProperty(category = "padding")
3297    int mUserPaddingStart;
3298
3299    /**
3300     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3301     *
3302     */
3303    @ViewDebug.ExportedProperty(category = "padding")
3304    int mUserPaddingEnd;
3305
3306    /**
3307     * Cache initial left padding.
3308     *
3309     * @hide
3310     */
3311    int mUserPaddingLeftInitial;
3312
3313    /**
3314     * Cache initial right padding.
3315     *
3316     * @hide
3317     */
3318    int mUserPaddingRightInitial;
3319
3320    /**
3321     * Default undefined padding
3322     */
3323    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3324
3325    /**
3326     * Cache if a left padding has been defined
3327     */
3328    private boolean mLeftPaddingDefined = false;
3329
3330    /**
3331     * Cache if a right padding has been defined
3332     */
3333    private boolean mRightPaddingDefined = false;
3334
3335    /**
3336     * @hide
3337     */
3338    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3339    /**
3340     * @hide
3341     */
3342    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3343
3344    private LongSparseLongArray mMeasureCache;
3345
3346    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3347    private Drawable mBackground;
3348    private TintInfo mBackgroundTint;
3349
3350    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3351    private ForegroundInfo mForegroundInfo;
3352
3353    private Drawable mScrollIndicatorDrawable;
3354
3355    /**
3356     * RenderNode used for backgrounds.
3357     * <p>
3358     * When non-null and valid, this is expected to contain an up-to-date copy
3359     * of the background drawable. It is cleared on temporary detach, and reset
3360     * on cleanup.
3361     */
3362    private RenderNode mBackgroundRenderNode;
3363
3364    private int mBackgroundResource;
3365    private boolean mBackgroundSizeChanged;
3366
3367    private String mTransitionName;
3368
3369    static class TintInfo {
3370        ColorStateList mTintList;
3371        PorterDuff.Mode mTintMode;
3372        boolean mHasTintMode;
3373        boolean mHasTintList;
3374    }
3375
3376    private static class ForegroundInfo {
3377        private Drawable mDrawable;
3378        private TintInfo mTintInfo;
3379        private int mGravity = Gravity.FILL;
3380        private boolean mInsidePadding = true;
3381        private boolean mBoundsChanged = true;
3382        private final Rect mSelfBounds = new Rect();
3383        private final Rect mOverlayBounds = new Rect();
3384    }
3385
3386    static class ListenerInfo {
3387        /**
3388         * Listener used to dispatch focus change events.
3389         * This field should be made private, so it is hidden from the SDK.
3390         * {@hide}
3391         */
3392        protected OnFocusChangeListener mOnFocusChangeListener;
3393
3394        /**
3395         * Listeners for layout change events.
3396         */
3397        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3398
3399        protected OnScrollChangeListener mOnScrollChangeListener;
3400
3401        /**
3402         * Listeners for attach events.
3403         */
3404        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3405
3406        /**
3407         * Listener used to dispatch click events.
3408         * This field should be made private, so it is hidden from the SDK.
3409         * {@hide}
3410         */
3411        public OnClickListener mOnClickListener;
3412
3413        /**
3414         * Listener used to dispatch long click events.
3415         * This field should be made private, so it is hidden from the SDK.
3416         * {@hide}
3417         */
3418        protected OnLongClickListener mOnLongClickListener;
3419
3420        /**
3421         * Listener used to dispatch stylus touch and button press events. This field should be made
3422         * private, so it is hidden from the SDK.
3423         * {@hide}
3424         */
3425        protected OnStylusButtonPressListener mOnStylusButtonPressListener;
3426
3427        /**
3428         * Listener used to build the context menu.
3429         * This field should be made private, so it is hidden from the SDK.
3430         * {@hide}
3431         */
3432        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3433
3434        private OnKeyListener mOnKeyListener;
3435
3436        private OnTouchListener mOnTouchListener;
3437
3438        private OnHoverListener mOnHoverListener;
3439
3440        private OnGenericMotionListener mOnGenericMotionListener;
3441
3442        private OnDragListener mOnDragListener;
3443
3444        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3445
3446        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3447    }
3448
3449    ListenerInfo mListenerInfo;
3450
3451    /**
3452     * The application environment this view lives in.
3453     * This field should be made private, so it is hidden from the SDK.
3454     * {@hide}
3455     */
3456    @ViewDebug.ExportedProperty(deepExport = true)
3457    protected Context mContext;
3458
3459    private final Resources mResources;
3460
3461    private ScrollabilityCache mScrollCache;
3462
3463    private int[] mDrawableState = null;
3464
3465    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3466
3467    /**
3468     * Animator that automatically runs based on state changes.
3469     */
3470    private StateListAnimator mStateListAnimator;
3471
3472    /**
3473     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3474     * the user may specify which view to go to next.
3475     */
3476    private int mNextFocusLeftId = View.NO_ID;
3477
3478    /**
3479     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3480     * the user may specify which view to go to next.
3481     */
3482    private int mNextFocusRightId = View.NO_ID;
3483
3484    /**
3485     * When this view has focus and the next focus is {@link #FOCUS_UP},
3486     * the user may specify which view to go to next.
3487     */
3488    private int mNextFocusUpId = View.NO_ID;
3489
3490    /**
3491     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3492     * the user may specify which view to go to next.
3493     */
3494    private int mNextFocusDownId = View.NO_ID;
3495
3496    /**
3497     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3498     * the user may specify which view to go to next.
3499     */
3500    int mNextFocusForwardId = View.NO_ID;
3501
3502    private CheckForLongPress mPendingCheckForLongPress;
3503    private CheckForTap mPendingCheckForTap = null;
3504    private PerformClick mPerformClick;
3505    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3506
3507    private UnsetPressedState mUnsetPressedState;
3508
3509    /**
3510     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3511     * up event while a long press is invoked as soon as the long press duration is reached, so
3512     * a long press could be performed before the tap is checked, in which case the tap's action
3513     * should not be invoked.
3514     */
3515    private boolean mHasPerformedLongPress;
3516
3517    /**
3518     * Whether the stylus button is currently pressed down. This is true when
3519     * the stylus is touching the screen and the button has been pressed, this
3520     * is false once the stylus has been lifted.
3521     */
3522    private boolean mInStylusButtonPress = false;
3523
3524    /**
3525     * The minimum height of the view. We'll try our best to have the height
3526     * of this view to at least this amount.
3527     */
3528    @ViewDebug.ExportedProperty(category = "measurement")
3529    private int mMinHeight;
3530
3531    /**
3532     * The minimum width of the view. We'll try our best to have the width
3533     * of this view to at least this amount.
3534     */
3535    @ViewDebug.ExportedProperty(category = "measurement")
3536    private int mMinWidth;
3537
3538    /**
3539     * The delegate to handle touch events that are physically in this view
3540     * but should be handled by another view.
3541     */
3542    private TouchDelegate mTouchDelegate = null;
3543
3544    /**
3545     * Solid color to use as a background when creating the drawing cache. Enables
3546     * the cache to use 16 bit bitmaps instead of 32 bit.
3547     */
3548    private int mDrawingCacheBackgroundColor = 0;
3549
3550    /**
3551     * Special tree observer used when mAttachInfo is null.
3552     */
3553    private ViewTreeObserver mFloatingTreeObserver;
3554
3555    /**
3556     * Cache the touch slop from the context that created the view.
3557     */
3558    private int mTouchSlop;
3559
3560    /**
3561     * Object that handles automatic animation of view properties.
3562     */
3563    private ViewPropertyAnimator mAnimator = null;
3564
3565    /**
3566     * Flag indicating that a drag can cross window boundaries.  When
3567     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3568     * with this flag set, all visible applications will be able to participate
3569     * in the drag operation and receive the dragged content.
3570     *
3571     * @hide
3572     */
3573    public static final int DRAG_FLAG_GLOBAL = 1;
3574
3575    /**
3576     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3577     */
3578    private float mVerticalScrollFactor;
3579
3580    /**
3581     * Position of the vertical scroll bar.
3582     */
3583    private int mVerticalScrollbarPosition;
3584
3585    /**
3586     * Position the scroll bar at the default position as determined by the system.
3587     */
3588    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3589
3590    /**
3591     * Position the scroll bar along the left edge.
3592     */
3593    public static final int SCROLLBAR_POSITION_LEFT = 1;
3594
3595    /**
3596     * Position the scroll bar along the right edge.
3597     */
3598    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3599
3600    /**
3601     * Indicates that the view does not have a layer.
3602     *
3603     * @see #getLayerType()
3604     * @see #setLayerType(int, android.graphics.Paint)
3605     * @see #LAYER_TYPE_SOFTWARE
3606     * @see #LAYER_TYPE_HARDWARE
3607     */
3608    public static final int LAYER_TYPE_NONE = 0;
3609
3610    /**
3611     * <p>Indicates that the view has a software layer. A software layer is backed
3612     * by a bitmap and causes the view to be rendered using Android's software
3613     * rendering pipeline, even if hardware acceleration is enabled.</p>
3614     *
3615     * <p>Software layers have various usages:</p>
3616     * <p>When the application is not using hardware acceleration, a software layer
3617     * is useful to apply a specific color filter and/or blending mode and/or
3618     * translucency to a view and all its children.</p>
3619     * <p>When the application is using hardware acceleration, a software layer
3620     * is useful to render drawing primitives not supported by the hardware
3621     * accelerated pipeline. It can also be used to cache a complex view tree
3622     * into a texture and reduce the complexity of drawing operations. For instance,
3623     * when animating a complex view tree with a translation, a software layer can
3624     * be used to render the view tree only once.</p>
3625     * <p>Software layers should be avoided when the affected view tree updates
3626     * often. Every update will require to re-render the software layer, which can
3627     * potentially be slow (particularly when hardware acceleration is turned on
3628     * since the layer will have to be uploaded into a hardware texture after every
3629     * update.)</p>
3630     *
3631     * @see #getLayerType()
3632     * @see #setLayerType(int, android.graphics.Paint)
3633     * @see #LAYER_TYPE_NONE
3634     * @see #LAYER_TYPE_HARDWARE
3635     */
3636    public static final int LAYER_TYPE_SOFTWARE = 1;
3637
3638    /**
3639     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3640     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3641     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3642     * rendering pipeline, but only if hardware acceleration is turned on for the
3643     * view hierarchy. When hardware acceleration is turned off, hardware layers
3644     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3645     *
3646     * <p>A hardware layer is useful to apply a specific color filter and/or
3647     * blending mode and/or translucency to a view and all its children.</p>
3648     * <p>A hardware layer can be used to cache a complex view tree into a
3649     * texture and reduce the complexity of drawing operations. For instance,
3650     * when animating a complex view tree with a translation, a hardware layer can
3651     * be used to render the view tree only once.</p>
3652     * <p>A hardware layer can also be used to increase the rendering quality when
3653     * rotation transformations are applied on a view. It can also be used to
3654     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3655     *
3656     * @see #getLayerType()
3657     * @see #setLayerType(int, android.graphics.Paint)
3658     * @see #LAYER_TYPE_NONE
3659     * @see #LAYER_TYPE_SOFTWARE
3660     */
3661    public static final int LAYER_TYPE_HARDWARE = 2;
3662
3663    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3664            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3665            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3666            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3667    })
3668    int mLayerType = LAYER_TYPE_NONE;
3669    Paint mLayerPaint;
3670
3671    /**
3672     * Set to true when drawing cache is enabled and cannot be created.
3673     *
3674     * @hide
3675     */
3676    public boolean mCachingFailed;
3677    private Bitmap mDrawingCache;
3678    private Bitmap mUnscaledDrawingCache;
3679
3680    /**
3681     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3682     * <p>
3683     * When non-null and valid, this is expected to contain an up-to-date copy
3684     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3685     * cleanup.
3686     */
3687    final RenderNode mRenderNode;
3688
3689    /**
3690     * Set to true when the view is sending hover accessibility events because it
3691     * is the innermost hovered view.
3692     */
3693    private boolean mSendingHoverAccessibilityEvents;
3694
3695    /**
3696     * Delegate for injecting accessibility functionality.
3697     */
3698    AccessibilityDelegate mAccessibilityDelegate;
3699
3700    /**
3701     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3702     * and add/remove objects to/from the overlay directly through the Overlay methods.
3703     */
3704    ViewOverlay mOverlay;
3705
3706    /**
3707     * The currently active parent view for receiving delegated nested scrolling events.
3708     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3709     * by {@link #stopNestedScroll()} at the same point where we clear
3710     * requestDisallowInterceptTouchEvent.
3711     */
3712    private ViewParent mNestedScrollingParent;
3713
3714    /**
3715     * Consistency verifier for debugging purposes.
3716     * @hide
3717     */
3718    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3719            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3720                    new InputEventConsistencyVerifier(this, 0) : null;
3721
3722    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3723
3724    private int[] mTempNestedScrollConsumed;
3725
3726    /**
3727     * An overlay is going to draw this View instead of being drawn as part of this
3728     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3729     * when this view is invalidated.
3730     */
3731    GhostView mGhostView;
3732
3733    /**
3734     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3735     * @hide
3736     */
3737    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3738    public String[] mAttributes;
3739
3740    /**
3741     * Maps a Resource id to its name.
3742     */
3743    private static SparseArray<String> mAttributeMap;
3744
3745    /**
3746     * @hide
3747     */
3748    String mStartActivityRequestWho;
3749
3750    /**
3751     * Simple constructor to use when creating a view from code.
3752     *
3753     * @param context The Context the view is running in, through which it can
3754     *        access the current theme, resources, etc.
3755     */
3756    public View(Context context) {
3757        mContext = context;
3758        mResources = context != null ? context.getResources() : null;
3759        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3760        // Set some flags defaults
3761        mPrivateFlags2 =
3762                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3763                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3764                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3765                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3766                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3767                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3768        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3769        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3770        mUserPaddingStart = UNDEFINED_PADDING;
3771        mUserPaddingEnd = UNDEFINED_PADDING;
3772        mRenderNode = RenderNode.create(getClass().getName(), this);
3773
3774        if (!sCompatibilityDone && context != null) {
3775            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3776
3777            // Older apps may need this compatibility hack for measurement.
3778            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3779
3780            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3781            // of whether a layout was requested on that View.
3782            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3783
3784            Canvas.sCompatibilityRestore = targetSdkVersion < MNC;
3785
3786            sCompatibilityDone = true;
3787        }
3788    }
3789
3790    /**
3791     * Constructor that is called when inflating a view from XML. This is called
3792     * when a view is being constructed from an XML file, supplying attributes
3793     * that were specified in the XML file. This version uses a default style of
3794     * 0, so the only attribute values applied are those in the Context's Theme
3795     * and the given AttributeSet.
3796     *
3797     * <p>
3798     * The method onFinishInflate() will be called after all children have been
3799     * added.
3800     *
3801     * @param context The Context the view is running in, through which it can
3802     *        access the current theme, resources, etc.
3803     * @param attrs The attributes of the XML tag that is inflating the view.
3804     * @see #View(Context, AttributeSet, int)
3805     */
3806    public View(Context context, @Nullable AttributeSet attrs) {
3807        this(context, attrs, 0);
3808    }
3809
3810    /**
3811     * Perform inflation from XML and apply a class-specific base style from a
3812     * theme attribute. This constructor of View allows subclasses to use their
3813     * own base style when they are inflating. For example, a Button class's
3814     * constructor would call this version of the super class constructor and
3815     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3816     * allows the theme's button style to modify all of the base view attributes
3817     * (in particular its background) as well as the Button class's attributes.
3818     *
3819     * @param context The Context the view is running in, through which it can
3820     *        access the current theme, resources, etc.
3821     * @param attrs The attributes of the XML tag that is inflating the view.
3822     * @param defStyleAttr An attribute in the current theme that contains a
3823     *        reference to a style resource that supplies default values for
3824     *        the view. Can be 0 to not look for defaults.
3825     * @see #View(Context, AttributeSet)
3826     */
3827    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3828        this(context, attrs, defStyleAttr, 0);
3829    }
3830
3831    /**
3832     * Perform inflation from XML and apply a class-specific base style from a
3833     * theme attribute or style resource. This constructor of View allows
3834     * subclasses to use their own base style when they are inflating.
3835     * <p>
3836     * When determining the final value of a particular attribute, there are
3837     * four inputs that come into play:
3838     * <ol>
3839     * <li>Any attribute values in the given AttributeSet.
3840     * <li>The style resource specified in the AttributeSet (named "style").
3841     * <li>The default style specified by <var>defStyleAttr</var>.
3842     * <li>The default style specified by <var>defStyleRes</var>.
3843     * <li>The base values in this theme.
3844     * </ol>
3845     * <p>
3846     * Each of these inputs is considered in-order, with the first listed taking
3847     * precedence over the following ones. In other words, if in the
3848     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3849     * , then the button's text will <em>always</em> be black, regardless of
3850     * what is specified in any of the styles.
3851     *
3852     * @param context The Context the view is running in, through which it can
3853     *        access the current theme, resources, etc.
3854     * @param attrs The attributes of the XML tag that is inflating the view.
3855     * @param defStyleAttr An attribute in the current theme that contains a
3856     *        reference to a style resource that supplies default values for
3857     *        the view. Can be 0 to not look for defaults.
3858     * @param defStyleRes A resource identifier of a style resource that
3859     *        supplies default values for the view, used only if
3860     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3861     *        to not look for defaults.
3862     * @see #View(Context, AttributeSet, int)
3863     */
3864    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3865        this(context);
3866
3867        final TypedArray a = context.obtainStyledAttributes(
3868                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3869
3870        if (mDebugViewAttributes) {
3871            saveAttributeData(attrs, a);
3872        }
3873
3874        Drawable background = null;
3875
3876        int leftPadding = -1;
3877        int topPadding = -1;
3878        int rightPadding = -1;
3879        int bottomPadding = -1;
3880        int startPadding = UNDEFINED_PADDING;
3881        int endPadding = UNDEFINED_PADDING;
3882
3883        int padding = -1;
3884
3885        int viewFlagValues = 0;
3886        int viewFlagMasks = 0;
3887
3888        boolean setScrollContainer = false;
3889
3890        int x = 0;
3891        int y = 0;
3892
3893        float tx = 0;
3894        float ty = 0;
3895        float tz = 0;
3896        float elevation = 0;
3897        float rotation = 0;
3898        float rotationX = 0;
3899        float rotationY = 0;
3900        float sx = 1f;
3901        float sy = 1f;
3902        boolean transformSet = false;
3903
3904        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3905        int overScrollMode = mOverScrollMode;
3906        boolean initializeScrollbars = false;
3907        boolean initializeScrollIndicators = false;
3908
3909        boolean startPaddingDefined = false;
3910        boolean endPaddingDefined = false;
3911        boolean leftPaddingDefined = false;
3912        boolean rightPaddingDefined = false;
3913
3914        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3915
3916        final int N = a.getIndexCount();
3917        for (int i = 0; i < N; i++) {
3918            int attr = a.getIndex(i);
3919            switch (attr) {
3920                case com.android.internal.R.styleable.View_background:
3921                    background = a.getDrawable(attr);
3922                    break;
3923                case com.android.internal.R.styleable.View_padding:
3924                    padding = a.getDimensionPixelSize(attr, -1);
3925                    mUserPaddingLeftInitial = padding;
3926                    mUserPaddingRightInitial = padding;
3927                    leftPaddingDefined = true;
3928                    rightPaddingDefined = true;
3929                    break;
3930                 case com.android.internal.R.styleable.View_paddingLeft:
3931                    leftPadding = a.getDimensionPixelSize(attr, -1);
3932                    mUserPaddingLeftInitial = leftPadding;
3933                    leftPaddingDefined = true;
3934                    break;
3935                case com.android.internal.R.styleable.View_paddingTop:
3936                    topPadding = a.getDimensionPixelSize(attr, -1);
3937                    break;
3938                case com.android.internal.R.styleable.View_paddingRight:
3939                    rightPadding = a.getDimensionPixelSize(attr, -1);
3940                    mUserPaddingRightInitial = rightPadding;
3941                    rightPaddingDefined = true;
3942                    break;
3943                case com.android.internal.R.styleable.View_paddingBottom:
3944                    bottomPadding = a.getDimensionPixelSize(attr, -1);
3945                    break;
3946                case com.android.internal.R.styleable.View_paddingStart:
3947                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3948                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3949                    break;
3950                case com.android.internal.R.styleable.View_paddingEnd:
3951                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3952                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3953                    break;
3954                case com.android.internal.R.styleable.View_scrollX:
3955                    x = a.getDimensionPixelOffset(attr, 0);
3956                    break;
3957                case com.android.internal.R.styleable.View_scrollY:
3958                    y = a.getDimensionPixelOffset(attr, 0);
3959                    break;
3960                case com.android.internal.R.styleable.View_alpha:
3961                    setAlpha(a.getFloat(attr, 1f));
3962                    break;
3963                case com.android.internal.R.styleable.View_transformPivotX:
3964                    setPivotX(a.getDimensionPixelOffset(attr, 0));
3965                    break;
3966                case com.android.internal.R.styleable.View_transformPivotY:
3967                    setPivotY(a.getDimensionPixelOffset(attr, 0));
3968                    break;
3969                case com.android.internal.R.styleable.View_translationX:
3970                    tx = a.getDimensionPixelOffset(attr, 0);
3971                    transformSet = true;
3972                    break;
3973                case com.android.internal.R.styleable.View_translationY:
3974                    ty = a.getDimensionPixelOffset(attr, 0);
3975                    transformSet = true;
3976                    break;
3977                case com.android.internal.R.styleable.View_translationZ:
3978                    tz = a.getDimensionPixelOffset(attr, 0);
3979                    transformSet = true;
3980                    break;
3981                case com.android.internal.R.styleable.View_elevation:
3982                    elevation = a.getDimensionPixelOffset(attr, 0);
3983                    transformSet = true;
3984                    break;
3985                case com.android.internal.R.styleable.View_rotation:
3986                    rotation = a.getFloat(attr, 0);
3987                    transformSet = true;
3988                    break;
3989                case com.android.internal.R.styleable.View_rotationX:
3990                    rotationX = a.getFloat(attr, 0);
3991                    transformSet = true;
3992                    break;
3993                case com.android.internal.R.styleable.View_rotationY:
3994                    rotationY = a.getFloat(attr, 0);
3995                    transformSet = true;
3996                    break;
3997                case com.android.internal.R.styleable.View_scaleX:
3998                    sx = a.getFloat(attr, 1f);
3999                    transformSet = true;
4000                    break;
4001                case com.android.internal.R.styleable.View_scaleY:
4002                    sy = a.getFloat(attr, 1f);
4003                    transformSet = true;
4004                    break;
4005                case com.android.internal.R.styleable.View_id:
4006                    mID = a.getResourceId(attr, NO_ID);
4007                    break;
4008                case com.android.internal.R.styleable.View_tag:
4009                    mTag = a.getText(attr);
4010                    break;
4011                case com.android.internal.R.styleable.View_fitsSystemWindows:
4012                    if (a.getBoolean(attr, false)) {
4013                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4014                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4015                    }
4016                    break;
4017                case com.android.internal.R.styleable.View_focusable:
4018                    if (a.getBoolean(attr, false)) {
4019                        viewFlagValues |= FOCUSABLE;
4020                        viewFlagMasks |= FOCUSABLE_MASK;
4021                    }
4022                    break;
4023                case com.android.internal.R.styleable.View_focusableInTouchMode:
4024                    if (a.getBoolean(attr, false)) {
4025                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4026                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4027                    }
4028                    break;
4029                case com.android.internal.R.styleable.View_clickable:
4030                    if (a.getBoolean(attr, false)) {
4031                        viewFlagValues |= CLICKABLE;
4032                        viewFlagMasks |= CLICKABLE;
4033                    }
4034                    break;
4035                case com.android.internal.R.styleable.View_longClickable:
4036                    if (a.getBoolean(attr, false)) {
4037                        viewFlagValues |= LONG_CLICKABLE;
4038                        viewFlagMasks |= LONG_CLICKABLE;
4039                    }
4040                    break;
4041                case com.android.internal.R.styleable.View_stylusButtonPressable:
4042                    if (a.getBoolean(attr, false)) {
4043                        viewFlagValues |= STYLUS_BUTTON_PRESSABLE;
4044                        viewFlagMasks |= STYLUS_BUTTON_PRESSABLE;
4045                    }
4046                    break;
4047                case com.android.internal.R.styleable.View_saveEnabled:
4048                    if (!a.getBoolean(attr, true)) {
4049                        viewFlagValues |= SAVE_DISABLED;
4050                        viewFlagMasks |= SAVE_DISABLED_MASK;
4051                    }
4052                    break;
4053                case com.android.internal.R.styleable.View_duplicateParentState:
4054                    if (a.getBoolean(attr, false)) {
4055                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4056                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4057                    }
4058                    break;
4059                case com.android.internal.R.styleable.View_visibility:
4060                    final int visibility = a.getInt(attr, 0);
4061                    if (visibility != 0) {
4062                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4063                        viewFlagMasks |= VISIBILITY_MASK;
4064                    }
4065                    break;
4066                case com.android.internal.R.styleable.View_layoutDirection:
4067                    // Clear any layout direction flags (included resolved bits) already set
4068                    mPrivateFlags2 &=
4069                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4070                    // Set the layout direction flags depending on the value of the attribute
4071                    final int layoutDirection = a.getInt(attr, -1);
4072                    final int value = (layoutDirection != -1) ?
4073                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4074                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4075                    break;
4076                case com.android.internal.R.styleable.View_drawingCacheQuality:
4077                    final int cacheQuality = a.getInt(attr, 0);
4078                    if (cacheQuality != 0) {
4079                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4080                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4081                    }
4082                    break;
4083                case com.android.internal.R.styleable.View_contentDescription:
4084                    setContentDescription(a.getString(attr));
4085                    break;
4086                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4087                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4088                    break;
4089                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4090                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4091                    break;
4092                case com.android.internal.R.styleable.View_labelFor:
4093                    setLabelFor(a.getResourceId(attr, NO_ID));
4094                    break;
4095                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4096                    if (!a.getBoolean(attr, true)) {
4097                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4098                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4099                    }
4100                    break;
4101                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4102                    if (!a.getBoolean(attr, true)) {
4103                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4104                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4105                    }
4106                    break;
4107                case R.styleable.View_scrollbars:
4108                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4109                    if (scrollbars != SCROLLBARS_NONE) {
4110                        viewFlagValues |= scrollbars;
4111                        viewFlagMasks |= SCROLLBARS_MASK;
4112                        initializeScrollbars = true;
4113                    }
4114                    break;
4115                //noinspection deprecation
4116                case R.styleable.View_fadingEdge:
4117                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4118                        // Ignore the attribute starting with ICS
4119                        break;
4120                    }
4121                    // With builds < ICS, fall through and apply fading edges
4122                case R.styleable.View_requiresFadingEdge:
4123                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4124                    if (fadingEdge != FADING_EDGE_NONE) {
4125                        viewFlagValues |= fadingEdge;
4126                        viewFlagMasks |= FADING_EDGE_MASK;
4127                        initializeFadingEdgeInternal(a);
4128                    }
4129                    break;
4130                case R.styleable.View_scrollbarStyle:
4131                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4132                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4133                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4134                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4135                    }
4136                    break;
4137                case R.styleable.View_isScrollContainer:
4138                    setScrollContainer = true;
4139                    if (a.getBoolean(attr, false)) {
4140                        setScrollContainer(true);
4141                    }
4142                    break;
4143                case com.android.internal.R.styleable.View_keepScreenOn:
4144                    if (a.getBoolean(attr, false)) {
4145                        viewFlagValues |= KEEP_SCREEN_ON;
4146                        viewFlagMasks |= KEEP_SCREEN_ON;
4147                    }
4148                    break;
4149                case R.styleable.View_filterTouchesWhenObscured:
4150                    if (a.getBoolean(attr, false)) {
4151                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4152                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4153                    }
4154                    break;
4155                case R.styleable.View_nextFocusLeft:
4156                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4157                    break;
4158                case R.styleable.View_nextFocusRight:
4159                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4160                    break;
4161                case R.styleable.View_nextFocusUp:
4162                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4163                    break;
4164                case R.styleable.View_nextFocusDown:
4165                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4166                    break;
4167                case R.styleable.View_nextFocusForward:
4168                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4169                    break;
4170                case R.styleable.View_minWidth:
4171                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4172                    break;
4173                case R.styleable.View_minHeight:
4174                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4175                    break;
4176                case R.styleable.View_onClick:
4177                    if (context.isRestricted()) {
4178                        throw new IllegalStateException("The android:onClick attribute cannot "
4179                                + "be used within a restricted context");
4180                    }
4181
4182                    final String handlerName = a.getString(attr);
4183                    if (handlerName != null) {
4184                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4185                    }
4186                    break;
4187                case R.styleable.View_overScrollMode:
4188                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4189                    break;
4190                case R.styleable.View_verticalScrollbarPosition:
4191                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4192                    break;
4193                case R.styleable.View_layerType:
4194                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4195                    break;
4196                case R.styleable.View_textDirection:
4197                    // Clear any text direction flag already set
4198                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4199                    // Set the text direction flags depending on the value of the attribute
4200                    final int textDirection = a.getInt(attr, -1);
4201                    if (textDirection != -1) {
4202                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4203                    }
4204                    break;
4205                case R.styleable.View_textAlignment:
4206                    // Clear any text alignment flag already set
4207                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4208                    // Set the text alignment flag depending on the value of the attribute
4209                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4210                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4211                    break;
4212                case R.styleable.View_importantForAccessibility:
4213                    setImportantForAccessibility(a.getInt(attr,
4214                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4215                    break;
4216                case R.styleable.View_accessibilityLiveRegion:
4217                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4218                    break;
4219                case R.styleable.View_transitionName:
4220                    setTransitionName(a.getString(attr));
4221                    break;
4222                case R.styleable.View_nestedScrollingEnabled:
4223                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4224                    break;
4225                case R.styleable.View_stateListAnimator:
4226                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4227                            a.getResourceId(attr, 0)));
4228                    break;
4229                case R.styleable.View_backgroundTint:
4230                    // This will get applied later during setBackground().
4231                    if (mBackgroundTint == null) {
4232                        mBackgroundTint = new TintInfo();
4233                    }
4234                    mBackgroundTint.mTintList = a.getColorStateList(
4235                            R.styleable.View_backgroundTint);
4236                    mBackgroundTint.mHasTintList = true;
4237                    break;
4238                case R.styleable.View_backgroundTintMode:
4239                    // This will get applied later during setBackground().
4240                    if (mBackgroundTint == null) {
4241                        mBackgroundTint = new TintInfo();
4242                    }
4243                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4244                            R.styleable.View_backgroundTintMode, -1), null);
4245                    mBackgroundTint.mHasTintMode = true;
4246                    break;
4247                case R.styleable.View_outlineProvider:
4248                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4249                            PROVIDER_BACKGROUND));
4250                    break;
4251                case R.styleable.View_foreground:
4252                    setForeground(a.getDrawable(attr));
4253                    break;
4254                case R.styleable.View_foregroundGravity:
4255                    setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4256                    break;
4257                case R.styleable.View_foregroundTintMode:
4258                    setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4259                    break;
4260                case R.styleable.View_foregroundTint:
4261                    setForegroundTintList(a.getColorStateList(attr));
4262                    break;
4263                case R.styleable.View_foregroundInsidePadding:
4264                    if (mForegroundInfo == null) {
4265                        mForegroundInfo = new ForegroundInfo();
4266                    }
4267                    mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4268                            mForegroundInfo.mInsidePadding);
4269                    break;
4270                case R.styleable.View_scrollIndicators:
4271                    final int scrollIndicators =
4272                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4273                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4274                    if (scrollIndicators != 0) {
4275                        mPrivateFlags3 |= scrollIndicators;
4276                        initializeScrollIndicators = true;
4277                    }
4278                    break;
4279            }
4280        }
4281
4282        setOverScrollMode(overScrollMode);
4283
4284        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4285        // the resolved layout direction). Those cached values will be used later during padding
4286        // resolution.
4287        mUserPaddingStart = startPadding;
4288        mUserPaddingEnd = endPadding;
4289
4290        if (background != null) {
4291            setBackground(background);
4292        }
4293
4294        // setBackground above will record that padding is currently provided by the background.
4295        // If we have padding specified via xml, record that here instead and use it.
4296        mLeftPaddingDefined = leftPaddingDefined;
4297        mRightPaddingDefined = rightPaddingDefined;
4298
4299        if (padding >= 0) {
4300            leftPadding = padding;
4301            topPadding = padding;
4302            rightPadding = padding;
4303            bottomPadding = padding;
4304            mUserPaddingLeftInitial = padding;
4305            mUserPaddingRightInitial = padding;
4306        }
4307
4308        if (isRtlCompatibilityMode()) {
4309            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4310            // left / right padding are used if defined (meaning here nothing to do). If they are not
4311            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4312            // start / end and resolve them as left / right (layout direction is not taken into account).
4313            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4314            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4315            // defined.
4316            if (!mLeftPaddingDefined && startPaddingDefined) {
4317                leftPadding = startPadding;
4318            }
4319            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4320            if (!mRightPaddingDefined && endPaddingDefined) {
4321                rightPadding = endPadding;
4322            }
4323            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4324        } else {
4325            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4326            // values defined. Otherwise, left /right values are used.
4327            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4328            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4329            // defined.
4330            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4331
4332            if (mLeftPaddingDefined && !hasRelativePadding) {
4333                mUserPaddingLeftInitial = leftPadding;
4334            }
4335            if (mRightPaddingDefined && !hasRelativePadding) {
4336                mUserPaddingRightInitial = rightPadding;
4337            }
4338        }
4339
4340        internalSetPadding(
4341                mUserPaddingLeftInitial,
4342                topPadding >= 0 ? topPadding : mPaddingTop,
4343                mUserPaddingRightInitial,
4344                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4345
4346        if (viewFlagMasks != 0) {
4347            setFlags(viewFlagValues, viewFlagMasks);
4348        }
4349
4350        if (initializeScrollbars) {
4351            initializeScrollbarsInternal(a);
4352        }
4353
4354        if (initializeScrollIndicators) {
4355            initializeScrollIndicatorsInternal();
4356        }
4357
4358        a.recycle();
4359
4360        // Needs to be called after mViewFlags is set
4361        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4362            recomputePadding();
4363        }
4364
4365        if (x != 0 || y != 0) {
4366            scrollTo(x, y);
4367        }
4368
4369        if (transformSet) {
4370            setTranslationX(tx);
4371            setTranslationY(ty);
4372            setTranslationZ(tz);
4373            setElevation(elevation);
4374            setRotation(rotation);
4375            setRotationX(rotationX);
4376            setRotationY(rotationY);
4377            setScaleX(sx);
4378            setScaleY(sy);
4379        }
4380
4381        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4382            setScrollContainer(true);
4383        }
4384
4385        computeOpaqueFlags();
4386    }
4387
4388    /**
4389     * An implementation of OnClickListener that attempts to lazily load a
4390     * named click handling method from a parent or ancestor context.
4391     */
4392    private static class DeclaredOnClickListener implements OnClickListener {
4393        private final View mHostView;
4394        private final String mMethodName;
4395
4396        private Method mMethod;
4397
4398        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4399            mHostView = hostView;
4400            mMethodName = methodName;
4401        }
4402
4403        @Override
4404        public void onClick(@NonNull View v) {
4405            if (mMethod == null) {
4406                mMethod = resolveMethod(mHostView.getContext(), mMethodName);
4407            }
4408
4409            try {
4410                mMethod.invoke(mHostView.getContext(), v);
4411            } catch (IllegalAccessException e) {
4412                throw new IllegalStateException(
4413                        "Could not execute non-public method for android:onClick", e);
4414            } catch (InvocationTargetException e) {
4415                throw new IllegalStateException(
4416                        "Could not execute method for android:onClick", e);
4417            }
4418        }
4419
4420        @NonNull
4421        private Method resolveMethod(@Nullable Context context, @NonNull String name) {
4422            while (context != null) {
4423                try {
4424                    if (!context.isRestricted()) {
4425                        return context.getClass().getMethod(mMethodName, View.class);
4426                    }
4427                } catch (NoSuchMethodException e) {
4428                    // Failed to find method, keep searching up the hierarchy.
4429                }
4430
4431                if (context instanceof ContextWrapper) {
4432                    context = ((ContextWrapper) context).getBaseContext();
4433                } else {
4434                    // Can't search up the hierarchy, null out and fail.
4435                    context = null;
4436                }
4437            }
4438
4439            final int id = mHostView.getId();
4440            final String idText = id == NO_ID ? "" : " with id '"
4441                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4442            throw new IllegalStateException("Could not find method " + mMethodName
4443                    + "(View) in a parent or ancestor Context for android:onClick "
4444                    + "attribute defined on view " + mHostView.getClass() + idText);
4445        }
4446    }
4447
4448    /**
4449     * Non-public constructor for use in testing
4450     */
4451    View() {
4452        mResources = null;
4453        mRenderNode = RenderNode.create(getClass().getName(), this);
4454    }
4455
4456    private static SparseArray<String> getAttributeMap() {
4457        if (mAttributeMap == null) {
4458            mAttributeMap = new SparseArray<>();
4459        }
4460        return mAttributeMap;
4461    }
4462
4463    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4464        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4465        final int indexCount = t.getIndexCount();
4466        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4467
4468        int i = 0;
4469
4470        // Store raw XML attributes.
4471        for (int j = 0; j < attrsCount; ++j) {
4472            attributes[i] = attrs.getAttributeName(j);
4473            attributes[i + 1] = attrs.getAttributeValue(j);
4474            i += 2;
4475        }
4476
4477        // Store resolved styleable attributes.
4478        final Resources res = t.getResources();
4479        final SparseArray<String> attributeMap = getAttributeMap();
4480        for (int j = 0; j < indexCount; ++j) {
4481            final int index = t.getIndex(j);
4482            if (!t.hasValueOrEmpty(index)) {
4483                // Value is undefined. Skip it.
4484                continue;
4485            }
4486
4487            final int resourceId = t.getResourceId(index, 0);
4488            if (resourceId == 0) {
4489                // Value is not a reference. Skip it.
4490                continue;
4491            }
4492
4493            String resourceName = attributeMap.get(resourceId);
4494            if (resourceName == null) {
4495                try {
4496                    resourceName = res.getResourceName(resourceId);
4497                } catch (Resources.NotFoundException e) {
4498                    resourceName = "0x" + Integer.toHexString(resourceId);
4499                }
4500                attributeMap.put(resourceId, resourceName);
4501            }
4502
4503            attributes[i] = resourceName;
4504            attributes[i + 1] = t.getString(index, false);
4505            i += 2;
4506        }
4507
4508        // Trim to fit contents.
4509        final String[] trimmed = new String[i];
4510        System.arraycopy(attributes, 0, trimmed, 0, i);
4511        mAttributes = trimmed;
4512    }
4513
4514    public String toString() {
4515        StringBuilder out = new StringBuilder(128);
4516        out.append(getClass().getName());
4517        out.append('{');
4518        out.append(Integer.toHexString(System.identityHashCode(this)));
4519        out.append(' ');
4520        switch (mViewFlags&VISIBILITY_MASK) {
4521            case VISIBLE: out.append('V'); break;
4522            case INVISIBLE: out.append('I'); break;
4523            case GONE: out.append('G'); break;
4524            default: out.append('.'); break;
4525        }
4526        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4527        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4528        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4529        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4530        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4531        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4532        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4533        out.append((mViewFlags & STYLUS_BUTTON_PRESSABLE) != 0 ? 'S' : '.');
4534        out.append(' ');
4535        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4536        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4537        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4538        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4539            out.append('p');
4540        } else {
4541            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4542        }
4543        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4544        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4545        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4546        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4547        out.append(' ');
4548        out.append(mLeft);
4549        out.append(',');
4550        out.append(mTop);
4551        out.append('-');
4552        out.append(mRight);
4553        out.append(',');
4554        out.append(mBottom);
4555        final int id = getId();
4556        if (id != NO_ID) {
4557            out.append(" #");
4558            out.append(Integer.toHexString(id));
4559            final Resources r = mResources;
4560            if (Resources.resourceHasPackage(id) && r != null) {
4561                try {
4562                    String pkgname;
4563                    switch (id&0xff000000) {
4564                        case 0x7f000000:
4565                            pkgname="app";
4566                            break;
4567                        case 0x01000000:
4568                            pkgname="android";
4569                            break;
4570                        default:
4571                            pkgname = r.getResourcePackageName(id);
4572                            break;
4573                    }
4574                    String typename = r.getResourceTypeName(id);
4575                    String entryname = r.getResourceEntryName(id);
4576                    out.append(" ");
4577                    out.append(pkgname);
4578                    out.append(":");
4579                    out.append(typename);
4580                    out.append("/");
4581                    out.append(entryname);
4582                } catch (Resources.NotFoundException e) {
4583                }
4584            }
4585        }
4586        out.append("}");
4587        return out.toString();
4588    }
4589
4590    /**
4591     * <p>
4592     * Initializes the fading edges from a given set of styled attributes. This
4593     * method should be called by subclasses that need fading edges and when an
4594     * instance of these subclasses is created programmatically rather than
4595     * being inflated from XML. This method is automatically called when the XML
4596     * is inflated.
4597     * </p>
4598     *
4599     * @param a the styled attributes set to initialize the fading edges from
4600     *
4601     * @removed
4602     */
4603    protected void initializeFadingEdge(TypedArray a) {
4604        // This method probably shouldn't have been included in the SDK to begin with.
4605        // It relies on 'a' having been initialized using an attribute filter array that is
4606        // not publicly available to the SDK. The old method has been renamed
4607        // to initializeFadingEdgeInternal and hidden for framework use only;
4608        // this one initializes using defaults to make it safe to call for apps.
4609
4610        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4611
4612        initializeFadingEdgeInternal(arr);
4613
4614        arr.recycle();
4615    }
4616
4617    /**
4618     * <p>
4619     * Initializes the fading edges from a given set of styled attributes. This
4620     * method should be called by subclasses that need fading edges and when an
4621     * instance of these subclasses is created programmatically rather than
4622     * being inflated from XML. This method is automatically called when the XML
4623     * is inflated.
4624     * </p>
4625     *
4626     * @param a the styled attributes set to initialize the fading edges from
4627     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4628     */
4629    protected void initializeFadingEdgeInternal(TypedArray a) {
4630        initScrollCache();
4631
4632        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4633                R.styleable.View_fadingEdgeLength,
4634                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4635    }
4636
4637    /**
4638     * Returns the size of the vertical faded edges used to indicate that more
4639     * content in this view is visible.
4640     *
4641     * @return The size in pixels of the vertical faded edge or 0 if vertical
4642     *         faded edges are not enabled for this view.
4643     * @attr ref android.R.styleable#View_fadingEdgeLength
4644     */
4645    public int getVerticalFadingEdgeLength() {
4646        if (isVerticalFadingEdgeEnabled()) {
4647            ScrollabilityCache cache = mScrollCache;
4648            if (cache != null) {
4649                return cache.fadingEdgeLength;
4650            }
4651        }
4652        return 0;
4653    }
4654
4655    /**
4656     * Set the size of the faded edge used to indicate that more content in this
4657     * view is available.  Will not change whether the fading edge is enabled; use
4658     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4659     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4660     * for the vertical or horizontal fading edges.
4661     *
4662     * @param length The size in pixels of the faded edge used to indicate that more
4663     *        content in this view is visible.
4664     */
4665    public void setFadingEdgeLength(int length) {
4666        initScrollCache();
4667        mScrollCache.fadingEdgeLength = length;
4668    }
4669
4670    /**
4671     * Returns the size of the horizontal faded edges used to indicate that more
4672     * content in this view is visible.
4673     *
4674     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4675     *         faded edges are not enabled for this view.
4676     * @attr ref android.R.styleable#View_fadingEdgeLength
4677     */
4678    public int getHorizontalFadingEdgeLength() {
4679        if (isHorizontalFadingEdgeEnabled()) {
4680            ScrollabilityCache cache = mScrollCache;
4681            if (cache != null) {
4682                return cache.fadingEdgeLength;
4683            }
4684        }
4685        return 0;
4686    }
4687
4688    /**
4689     * Returns the width of the vertical scrollbar.
4690     *
4691     * @return The width in pixels of the vertical scrollbar or 0 if there
4692     *         is no vertical scrollbar.
4693     */
4694    public int getVerticalScrollbarWidth() {
4695        ScrollabilityCache cache = mScrollCache;
4696        if (cache != null) {
4697            ScrollBarDrawable scrollBar = cache.scrollBar;
4698            if (scrollBar != null) {
4699                int size = scrollBar.getSize(true);
4700                if (size <= 0) {
4701                    size = cache.scrollBarSize;
4702                }
4703                return size;
4704            }
4705            return 0;
4706        }
4707        return 0;
4708    }
4709
4710    /**
4711     * Returns the height of the horizontal scrollbar.
4712     *
4713     * @return The height in pixels of the horizontal scrollbar or 0 if
4714     *         there is no horizontal scrollbar.
4715     */
4716    protected int getHorizontalScrollbarHeight() {
4717        ScrollabilityCache cache = mScrollCache;
4718        if (cache != null) {
4719            ScrollBarDrawable scrollBar = cache.scrollBar;
4720            if (scrollBar != null) {
4721                int size = scrollBar.getSize(false);
4722                if (size <= 0) {
4723                    size = cache.scrollBarSize;
4724                }
4725                return size;
4726            }
4727            return 0;
4728        }
4729        return 0;
4730    }
4731
4732    /**
4733     * <p>
4734     * Initializes the scrollbars from a given set of styled attributes. This
4735     * method should be called by subclasses that need scrollbars and when an
4736     * instance of these subclasses is created programmatically rather than
4737     * being inflated from XML. This method is automatically called when the XML
4738     * is inflated.
4739     * </p>
4740     *
4741     * @param a the styled attributes set to initialize the scrollbars from
4742     *
4743     * @removed
4744     */
4745    protected void initializeScrollbars(TypedArray a) {
4746        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4747        // using the View filter array which is not available to the SDK. As such, internal
4748        // framework usage now uses initializeScrollbarsInternal and we grab a default
4749        // TypedArray with the right filter instead here.
4750        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4751
4752        initializeScrollbarsInternal(arr);
4753
4754        // We ignored the method parameter. Recycle the one we actually did use.
4755        arr.recycle();
4756    }
4757
4758    /**
4759     * <p>
4760     * Initializes the scrollbars from a given set of styled attributes. This
4761     * method should be called by subclasses that need scrollbars and when an
4762     * instance of these subclasses is created programmatically rather than
4763     * being inflated from XML. This method is automatically called when the XML
4764     * is inflated.
4765     * </p>
4766     *
4767     * @param a the styled attributes set to initialize the scrollbars from
4768     * @hide
4769     */
4770    protected void initializeScrollbarsInternal(TypedArray a) {
4771        initScrollCache();
4772
4773        final ScrollabilityCache scrollabilityCache = mScrollCache;
4774
4775        if (scrollabilityCache.scrollBar == null) {
4776            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4777            scrollabilityCache.scrollBar.setCallback(this);
4778            scrollabilityCache.scrollBar.setState(getDrawableState());
4779        }
4780
4781        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4782
4783        if (!fadeScrollbars) {
4784            scrollabilityCache.state = ScrollabilityCache.ON;
4785        }
4786        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4787
4788
4789        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4790                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4791                        .getScrollBarFadeDuration());
4792        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4793                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4794                ViewConfiguration.getScrollDefaultDelay());
4795
4796
4797        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4798                com.android.internal.R.styleable.View_scrollbarSize,
4799                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4800
4801        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4802        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4803
4804        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4805        if (thumb != null) {
4806            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4807        }
4808
4809        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4810                false);
4811        if (alwaysDraw) {
4812            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4813        }
4814
4815        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4816        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4817
4818        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4819        if (thumb != null) {
4820            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4821        }
4822
4823        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4824                false);
4825        if (alwaysDraw) {
4826            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4827        }
4828
4829        // Apply layout direction to the new Drawables if needed
4830        final int layoutDirection = getLayoutDirection();
4831        if (track != null) {
4832            track.setLayoutDirection(layoutDirection);
4833        }
4834        if (thumb != null) {
4835            thumb.setLayoutDirection(layoutDirection);
4836        }
4837
4838        // Re-apply user/background padding so that scrollbar(s) get added
4839        resolvePadding();
4840    }
4841
4842    private void initializeScrollIndicatorsInternal() {
4843        // Some day maybe we'll break this into top/left/start/etc. and let the
4844        // client control it. Until then, you can have any scroll indicator you
4845        // want as long as it's a 1dp foreground-colored rectangle.
4846        if (mScrollIndicatorDrawable == null) {
4847            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
4848        }
4849    }
4850
4851    /**
4852     * <p>
4853     * Initalizes the scrollability cache if necessary.
4854     * </p>
4855     */
4856    private void initScrollCache() {
4857        if (mScrollCache == null) {
4858            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4859        }
4860    }
4861
4862    private ScrollabilityCache getScrollCache() {
4863        initScrollCache();
4864        return mScrollCache;
4865    }
4866
4867    /**
4868     * Set the position of the vertical scroll bar. Should be one of
4869     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4870     * {@link #SCROLLBAR_POSITION_RIGHT}.
4871     *
4872     * @param position Where the vertical scroll bar should be positioned.
4873     */
4874    public void setVerticalScrollbarPosition(int position) {
4875        if (mVerticalScrollbarPosition != position) {
4876            mVerticalScrollbarPosition = position;
4877            computeOpaqueFlags();
4878            resolvePadding();
4879        }
4880    }
4881
4882    /**
4883     * @return The position where the vertical scroll bar will show, if applicable.
4884     * @see #setVerticalScrollbarPosition(int)
4885     */
4886    public int getVerticalScrollbarPosition() {
4887        return mVerticalScrollbarPosition;
4888    }
4889
4890    /**
4891     * Sets the state of all scroll indicators.
4892     * <p>
4893     * See {@link #setScrollIndicators(int, int)} for usage information.
4894     *
4895     * @param indicators a bitmask of indicators that should be enabled, or
4896     *                   {@code 0} to disable all indicators
4897     * @see #setScrollIndicators(int, int)
4898     * @see #getScrollIndicators()
4899     * @attr ref android.R.styleable#View_scrollIndicators
4900     */
4901    public void setScrollIndicators(@ScrollIndicators int indicators) {
4902        setScrollIndicators(indicators,
4903                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
4904    }
4905
4906    /**
4907     * Sets the state of the scroll indicators specified by the mask. To change
4908     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
4909     * <p>
4910     * When a scroll indicator is enabled, it will be displayed if the view
4911     * can scroll in the direction of the indicator.
4912     * <p>
4913     * Multiple indicator types may be enabled or disabled by passing the
4914     * logical OR of the desired types. If multiple types are specified, they
4915     * will all be set to the same enabled state.
4916     * <p>
4917     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
4918     *
4919     * @param indicators the indicator direction, or the logical OR of multiple
4920     *             indicator directions. One or more of:
4921     *             <ul>
4922     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
4923     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
4924     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
4925     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
4926     *               <li>{@link #SCROLL_INDICATOR_START}</li>
4927     *               <li>{@link #SCROLL_INDICATOR_END}</li>
4928     *             </ul>
4929     * @see #setScrollIndicators(int)
4930     * @see #getScrollIndicators()
4931     * @attr ref android.R.styleable#View_scrollIndicators
4932     */
4933    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
4934        // Shift and sanitize mask.
4935        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
4936        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
4937
4938        // Shift and mask indicators.
4939        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
4940        indicators &= mask;
4941
4942        // Merge with non-masked flags.
4943        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
4944
4945        if (mPrivateFlags3 != updatedFlags) {
4946            mPrivateFlags3 = updatedFlags;
4947
4948            if (indicators != 0) {
4949                initializeScrollIndicatorsInternal();
4950            }
4951            invalidate();
4952        }
4953    }
4954
4955    /**
4956     * Returns a bitmask representing the enabled scroll indicators.
4957     * <p>
4958     * For example, if the top and left scroll indicators are enabled and all
4959     * other indicators are disabled, the return value will be
4960     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
4961     * <p>
4962     * To check whether the bottom scroll indicator is enabled, use the value
4963     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
4964     *
4965     * @return a bitmask representing the enabled scroll indicators
4966     */
4967    @ScrollIndicators
4968    public int getScrollIndicators() {
4969        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
4970                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
4971    }
4972
4973    ListenerInfo getListenerInfo() {
4974        if (mListenerInfo != null) {
4975            return mListenerInfo;
4976        }
4977        mListenerInfo = new ListenerInfo();
4978        return mListenerInfo;
4979    }
4980
4981    /**
4982     * Register a callback to be invoked when the scroll X or Y positions of
4983     * this view change.
4984     * <p>
4985     * <b>Note:</b> Some views handle scrolling independently from View and may
4986     * have their own separate listeners for scroll-type events. For example,
4987     * {@link android.widget.ListView ListView} allows clients to register an
4988     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
4989     * to listen for changes in list scroll position.
4990     *
4991     * @param l The listener to notify when the scroll X or Y position changes.
4992     * @see android.view.View#getScrollX()
4993     * @see android.view.View#getScrollY()
4994     */
4995    public void setOnScrollChangeListener(OnScrollChangeListener l) {
4996        getListenerInfo().mOnScrollChangeListener = l;
4997    }
4998
4999    /**
5000     * Register a callback to be invoked when focus of this view changed.
5001     *
5002     * @param l The callback that will run.
5003     */
5004    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5005        getListenerInfo().mOnFocusChangeListener = l;
5006    }
5007
5008    /**
5009     * Add a listener that will be called when the bounds of the view change due to
5010     * layout processing.
5011     *
5012     * @param listener The listener that will be called when layout bounds change.
5013     */
5014    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5015        ListenerInfo li = getListenerInfo();
5016        if (li.mOnLayoutChangeListeners == null) {
5017            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5018        }
5019        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5020            li.mOnLayoutChangeListeners.add(listener);
5021        }
5022    }
5023
5024    /**
5025     * Remove a listener for layout changes.
5026     *
5027     * @param listener The listener for layout bounds change.
5028     */
5029    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5030        ListenerInfo li = mListenerInfo;
5031        if (li == null || li.mOnLayoutChangeListeners == null) {
5032            return;
5033        }
5034        li.mOnLayoutChangeListeners.remove(listener);
5035    }
5036
5037    /**
5038     * Add a listener for attach state changes.
5039     *
5040     * This listener will be called whenever this view is attached or detached
5041     * from a window. Remove the listener using
5042     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5043     *
5044     * @param listener Listener to attach
5045     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5046     */
5047    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5048        ListenerInfo li = getListenerInfo();
5049        if (li.mOnAttachStateChangeListeners == null) {
5050            li.mOnAttachStateChangeListeners
5051                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5052        }
5053        li.mOnAttachStateChangeListeners.add(listener);
5054    }
5055
5056    /**
5057     * Remove a listener for attach state changes. The listener will receive no further
5058     * notification of window attach/detach events.
5059     *
5060     * @param listener Listener to remove
5061     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5062     */
5063    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5064        ListenerInfo li = mListenerInfo;
5065        if (li == null || li.mOnAttachStateChangeListeners == null) {
5066            return;
5067        }
5068        li.mOnAttachStateChangeListeners.remove(listener);
5069    }
5070
5071    /**
5072     * Returns the focus-change callback registered for this view.
5073     *
5074     * @return The callback, or null if one is not registered.
5075     */
5076    public OnFocusChangeListener getOnFocusChangeListener() {
5077        ListenerInfo li = mListenerInfo;
5078        return li != null ? li.mOnFocusChangeListener : null;
5079    }
5080
5081    /**
5082     * Register a callback to be invoked when this view is clicked. If this view is not
5083     * clickable, it becomes clickable.
5084     *
5085     * @param l The callback that will run
5086     *
5087     * @see #setClickable(boolean)
5088     */
5089    public void setOnClickListener(@Nullable OnClickListener l) {
5090        if (!isClickable()) {
5091            setClickable(true);
5092        }
5093        getListenerInfo().mOnClickListener = l;
5094    }
5095
5096    /**
5097     * Return whether this view has an attached OnClickListener.  Returns
5098     * true if there is a listener, false if there is none.
5099     */
5100    public boolean hasOnClickListeners() {
5101        ListenerInfo li = mListenerInfo;
5102        return (li != null && li.mOnClickListener != null);
5103    }
5104
5105    /**
5106     * Register a callback to be invoked when this view is clicked and held. If this view is not
5107     * long clickable, it becomes long clickable.
5108     *
5109     * @param l The callback that will run
5110     *
5111     * @see #setLongClickable(boolean)
5112     */
5113    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5114        if (!isLongClickable()) {
5115            setLongClickable(true);
5116        }
5117        getListenerInfo().mOnLongClickListener = l;
5118    }
5119
5120    /**
5121     * Register a callback to be invoked when this view is touched with a stylus and the button is
5122     * pressed.
5123     *
5124     * @param l The callback that will run
5125     * @see #setStylusButtonPressable(boolean)
5126     */
5127    public void setOnStylusButtonPressListener(@Nullable OnStylusButtonPressListener l) {
5128        if (!isStylusButtonPressable()) {
5129            setStylusButtonPressable(true);
5130        }
5131        getListenerInfo().mOnStylusButtonPressListener = l;
5132    }
5133
5134    /**
5135     * Register a callback to be invoked when the context menu for this view is
5136     * being built. If this view is not long clickable, it becomes long clickable.
5137     *
5138     * @param l The callback that will run
5139     *
5140     */
5141    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5142        if (!isLongClickable()) {
5143            setLongClickable(true);
5144        }
5145        getListenerInfo().mOnCreateContextMenuListener = l;
5146    }
5147
5148    /**
5149     * Call this view's OnClickListener, if it is defined.  Performs all normal
5150     * actions associated with clicking: reporting accessibility event, playing
5151     * a sound, etc.
5152     *
5153     * @return True there was an assigned OnClickListener that was called, false
5154     *         otherwise is returned.
5155     */
5156    public boolean performClick() {
5157        final boolean result;
5158        final ListenerInfo li = mListenerInfo;
5159        if (li != null && li.mOnClickListener != null) {
5160            playSoundEffect(SoundEffectConstants.CLICK);
5161            li.mOnClickListener.onClick(this);
5162            result = true;
5163        } else {
5164            result = false;
5165        }
5166
5167        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5168        return result;
5169    }
5170
5171    /**
5172     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5173     * this only calls the listener, and does not do any associated clicking
5174     * actions like reporting an accessibility event.
5175     *
5176     * @return True there was an assigned OnClickListener that was called, false
5177     *         otherwise is returned.
5178     */
5179    public boolean callOnClick() {
5180        ListenerInfo li = mListenerInfo;
5181        if (li != null && li.mOnClickListener != null) {
5182            li.mOnClickListener.onClick(this);
5183            return true;
5184        }
5185        return false;
5186    }
5187
5188    /**
5189     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
5190     * OnLongClickListener did not consume the event.
5191     *
5192     * @return True if one of the above receivers consumed the event, false otherwise.
5193     */
5194    public boolean performLongClick() {
5195        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5196
5197        boolean handled = false;
5198        ListenerInfo li = mListenerInfo;
5199        if (li != null && li.mOnLongClickListener != null) {
5200            handled = li.mOnLongClickListener.onLongClick(View.this);
5201        }
5202        if (!handled) {
5203            handled = showContextMenu();
5204        }
5205        if (handled) {
5206            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5207        }
5208        return handled;
5209    }
5210
5211    /**
5212     * Call this view's OnStylusButtonPressListener, if it is defined.
5213     *
5214     * @return True if there was an assigned OnStylusButtonPressListener that consumed the event,
5215     *         false otherwise.
5216     */
5217    public boolean performStylusButtonPress() {
5218        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_STYLUS_BUTTON_PRESSED);
5219
5220        boolean handled = false;
5221        ListenerInfo li = mListenerInfo;
5222        if (li != null && li.mOnStylusButtonPressListener != null) {
5223            handled = li.mOnStylusButtonPressListener.onStylusButtonPress(View.this);
5224        }
5225        if (handled) {
5226            performHapticFeedback(HapticFeedbackConstants.STYLUS_BUTTON_PRESS);
5227        }
5228        return handled;
5229    }
5230
5231    /**
5232     * Checks for a stylus button press and calls the listener.
5233     *
5234     * @param event The event.
5235     * @return True if the event was consumed.
5236     */
5237    private boolean performStylusActionOnButtonPress(MotionEvent event) {
5238        if (isStylusButtonPressable() && !mInStylusButtonPress && !mHasPerformedLongPress
5239                && event.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY)) {
5240            if (performStylusButtonPress()) {
5241                mInStylusButtonPress = true;
5242                setPressed(true, event.getX(), event.getY());
5243                removeTapCallback();
5244                removeLongPressCallback();
5245                return true;
5246            }
5247        }
5248        return false;
5249    }
5250
5251    /**
5252     * Performs button-related actions during a touch down event.
5253     *
5254     * @param event The event.
5255     * @return True if the down was consumed.
5256     *
5257     * @hide
5258     */
5259    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5260        if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
5261            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5262            showContextMenu(event.getX(), event.getY(), event.getMetaState());
5263            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5264            return true;
5265        }
5266        return false;
5267    }
5268
5269    /**
5270     * Bring up the context menu for this view.
5271     *
5272     * @return Whether a context menu was displayed.
5273     */
5274    public boolean showContextMenu() {
5275        return getParent().showContextMenuForChild(this);
5276    }
5277
5278    /**
5279     * Bring up the context menu for this view, referring to the item under the specified point.
5280     *
5281     * @param x The referenced x coordinate.
5282     * @param y The referenced y coordinate.
5283     * @param metaState The keyboard modifiers that were pressed.
5284     * @return Whether a context menu was displayed.
5285     *
5286     * @hide
5287     */
5288    public boolean showContextMenu(float x, float y, int metaState) {
5289        return showContextMenu();
5290    }
5291
5292    /**
5293     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5294     *
5295     * @param callback Callback that will control the lifecycle of the action mode
5296     * @return The new action mode if it is started, null otherwise
5297     *
5298     * @see ActionMode
5299     * @see #startActionMode(android.view.ActionMode.Callback, int)
5300     */
5301    public ActionMode startActionMode(ActionMode.Callback callback) {
5302        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5303    }
5304
5305    /**
5306     * Start an action mode with the given type.
5307     *
5308     * @param callback Callback that will control the lifecycle of the action mode
5309     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5310     * @return The new action mode if it is started, null otherwise
5311     *
5312     * @see ActionMode
5313     */
5314    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5315        ViewParent parent = getParent();
5316        if (parent == null) return null;
5317        try {
5318            return parent.startActionModeForChild(this, callback, type);
5319        } catch (AbstractMethodError ame) {
5320            // Older implementations of custom views might not implement this.
5321            return parent.startActionModeForChild(this, callback);
5322        }
5323    }
5324
5325    /**
5326     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5327     * Context, creating a unique View identifier to retrieve the result.
5328     *
5329     * @param intent The Intent to be started.
5330     * @param requestCode The request code to use.
5331     * @hide
5332     */
5333    public void startActivityForResult(Intent intent, int requestCode) {
5334        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5335        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5336    }
5337
5338    /**
5339     * If this View corresponds to the calling who, dispatches the activity result.
5340     * @param who The identifier for the targeted View to receive the result.
5341     * @param requestCode The integer request code originally supplied to
5342     *                    startActivityForResult(), allowing you to identify who this
5343     *                    result came from.
5344     * @param resultCode The integer result code returned by the child activity
5345     *                   through its setResult().
5346     * @param data An Intent, which can return result data to the caller
5347     *               (various data can be attached to Intent "extras").
5348     * @return {@code true} if the activity result was dispatched.
5349     * @hide
5350     */
5351    public boolean dispatchActivityResult(
5352            String who, int requestCode, int resultCode, Intent data) {
5353        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5354            onActivityResult(requestCode, resultCode, data);
5355            mStartActivityRequestWho = null;
5356            return true;
5357        }
5358        return false;
5359    }
5360
5361    /**
5362     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5363     *
5364     * @param requestCode The integer request code originally supplied to
5365     *                    startActivityForResult(), allowing you to identify who this
5366     *                    result came from.
5367     * @param resultCode The integer result code returned by the child activity
5368     *                   through its setResult().
5369     * @param data An Intent, which can return result data to the caller
5370     *               (various data can be attached to Intent "extras").
5371     * @hide
5372     */
5373    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5374        // Do nothing.
5375    }
5376
5377    /**
5378     * Register a callback to be invoked when a hardware key is pressed in this view.
5379     * Key presses in software input methods will generally not trigger the methods of
5380     * this listener.
5381     * @param l the key listener to attach to this view
5382     */
5383    public void setOnKeyListener(OnKeyListener l) {
5384        getListenerInfo().mOnKeyListener = l;
5385    }
5386
5387    /**
5388     * Register a callback to be invoked when a touch event is sent to this view.
5389     * @param l the touch listener to attach to this view
5390     */
5391    public void setOnTouchListener(OnTouchListener l) {
5392        getListenerInfo().mOnTouchListener = l;
5393    }
5394
5395    /**
5396     * Register a callback to be invoked when a generic motion event is sent to this view.
5397     * @param l the generic motion listener to attach to this view
5398     */
5399    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5400        getListenerInfo().mOnGenericMotionListener = l;
5401    }
5402
5403    /**
5404     * Register a callback to be invoked when a hover event is sent to this view.
5405     * @param l the hover listener to attach to this view
5406     */
5407    public void setOnHoverListener(OnHoverListener l) {
5408        getListenerInfo().mOnHoverListener = l;
5409    }
5410
5411    /**
5412     * Register a drag event listener callback object for this View. The parameter is
5413     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5414     * View, the system calls the
5415     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5416     * @param l An implementation of {@link android.view.View.OnDragListener}.
5417     */
5418    public void setOnDragListener(OnDragListener l) {
5419        getListenerInfo().mOnDragListener = l;
5420    }
5421
5422    /**
5423     * Give this view focus. This will cause
5424     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5425     *
5426     * Note: this does not check whether this {@link View} should get focus, it just
5427     * gives it focus no matter what.  It should only be called internally by framework
5428     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5429     *
5430     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5431     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5432     *        focus moved when requestFocus() is called. It may not always
5433     *        apply, in which case use the default View.FOCUS_DOWN.
5434     * @param previouslyFocusedRect The rectangle of the view that had focus
5435     *        prior in this View's coordinate system.
5436     */
5437    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5438        if (DBG) {
5439            System.out.println(this + " requestFocus()");
5440        }
5441
5442        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5443            mPrivateFlags |= PFLAG_FOCUSED;
5444
5445            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5446
5447            if (mParent != null) {
5448                mParent.requestChildFocus(this, this);
5449            }
5450
5451            if (mAttachInfo != null) {
5452                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5453            }
5454
5455            onFocusChanged(true, direction, previouslyFocusedRect);
5456            refreshDrawableState();
5457        }
5458    }
5459
5460    /**
5461     * Populates <code>outRect</code> with the hotspot bounds. By default,
5462     * the hotspot bounds are identical to the screen bounds.
5463     *
5464     * @param outRect rect to populate with hotspot bounds
5465     * @hide Only for internal use by views and widgets.
5466     */
5467    public void getHotspotBounds(Rect outRect) {
5468        final Drawable background = getBackground();
5469        if (background != null) {
5470            background.getHotspotBounds(outRect);
5471        } else {
5472            getBoundsOnScreen(outRect);
5473        }
5474    }
5475
5476    /**
5477     * Request that a rectangle of this view be visible on the screen,
5478     * scrolling if necessary just enough.
5479     *
5480     * <p>A View should call this if it maintains some notion of which part
5481     * of its content is interesting.  For example, a text editing view
5482     * should call this when its cursor moves.
5483     *
5484     * @param rectangle The rectangle.
5485     * @return Whether any parent scrolled.
5486     */
5487    public boolean requestRectangleOnScreen(Rect rectangle) {
5488        return requestRectangleOnScreen(rectangle, false);
5489    }
5490
5491    /**
5492     * Request that a rectangle of this view be visible on the screen,
5493     * scrolling if necessary just enough.
5494     *
5495     * <p>A View should call this if it maintains some notion of which part
5496     * of its content is interesting.  For example, a text editing view
5497     * should call this when its cursor moves.
5498     *
5499     * <p>When <code>immediate</code> is set to true, scrolling will not be
5500     * animated.
5501     *
5502     * @param rectangle The rectangle.
5503     * @param immediate True to forbid animated scrolling, false otherwise
5504     * @return Whether any parent scrolled.
5505     */
5506    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5507        if (mParent == null) {
5508            return false;
5509        }
5510
5511        View child = this;
5512
5513        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5514        position.set(rectangle);
5515
5516        ViewParent parent = mParent;
5517        boolean scrolled = false;
5518        while (parent != null) {
5519            rectangle.set((int) position.left, (int) position.top,
5520                    (int) position.right, (int) position.bottom);
5521
5522            scrolled |= parent.requestChildRectangleOnScreen(child,
5523                    rectangle, immediate);
5524
5525            if (!child.hasIdentityMatrix()) {
5526                child.getMatrix().mapRect(position);
5527            }
5528
5529            position.offset(child.mLeft, child.mTop);
5530
5531            if (!(parent instanceof View)) {
5532                break;
5533            }
5534
5535            View parentView = (View) parent;
5536
5537            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5538
5539            child = parentView;
5540            parent = child.getParent();
5541        }
5542
5543        return scrolled;
5544    }
5545
5546    /**
5547     * Called when this view wants to give up focus. If focus is cleared
5548     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5549     * <p>
5550     * <strong>Note:</strong> When a View clears focus the framework is trying
5551     * to give focus to the first focusable View from the top. Hence, if this
5552     * View is the first from the top that can take focus, then all callbacks
5553     * related to clearing focus will be invoked after which the framework will
5554     * give focus to this view.
5555     * </p>
5556     */
5557    public void clearFocus() {
5558        if (DBG) {
5559            System.out.println(this + " clearFocus()");
5560        }
5561
5562        clearFocusInternal(null, true, true);
5563    }
5564
5565    /**
5566     * Clears focus from the view, optionally propagating the change up through
5567     * the parent hierarchy and requesting that the root view place new focus.
5568     *
5569     * @param propagate whether to propagate the change up through the parent
5570     *            hierarchy
5571     * @param refocus when propagate is true, specifies whether to request the
5572     *            root view place new focus
5573     */
5574    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5575        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5576            mPrivateFlags &= ~PFLAG_FOCUSED;
5577
5578            if (propagate && mParent != null) {
5579                mParent.clearChildFocus(this);
5580            }
5581
5582            onFocusChanged(false, 0, null);
5583            refreshDrawableState();
5584
5585            if (propagate && (!refocus || !rootViewRequestFocus())) {
5586                notifyGlobalFocusCleared(this);
5587            }
5588        }
5589    }
5590
5591    void notifyGlobalFocusCleared(View oldFocus) {
5592        if (oldFocus != null && mAttachInfo != null) {
5593            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5594        }
5595    }
5596
5597    boolean rootViewRequestFocus() {
5598        final View root = getRootView();
5599        return root != null && root.requestFocus();
5600    }
5601
5602    /**
5603     * Called internally by the view system when a new view is getting focus.
5604     * This is what clears the old focus.
5605     * <p>
5606     * <b>NOTE:</b> The parent view's focused child must be updated manually
5607     * after calling this method. Otherwise, the view hierarchy may be left in
5608     * an inconstent state.
5609     */
5610    void unFocus(View focused) {
5611        if (DBG) {
5612            System.out.println(this + " unFocus()");
5613        }
5614
5615        clearFocusInternal(focused, false, false);
5616    }
5617
5618    /**
5619     * Returns true if this view has focus itself, or is the ancestor of the
5620     * view that has focus.
5621     *
5622     * @return True if this view has or contains focus, false otherwise.
5623     */
5624    @ViewDebug.ExportedProperty(category = "focus")
5625    public boolean hasFocus() {
5626        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5627    }
5628
5629    /**
5630     * Returns true if this view is focusable or if it contains a reachable View
5631     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5632     * is a View whose parents do not block descendants focus.
5633     *
5634     * Only {@link #VISIBLE} views are considered focusable.
5635     *
5636     * @return True if the view is focusable or if the view contains a focusable
5637     *         View, false otherwise.
5638     *
5639     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5640     * @see ViewGroup#getTouchscreenBlocksFocus()
5641     */
5642    public boolean hasFocusable() {
5643        if (!isFocusableInTouchMode()) {
5644            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5645                final ViewGroup g = (ViewGroup) p;
5646                if (g.shouldBlockFocusForTouchscreen()) {
5647                    return false;
5648                }
5649            }
5650        }
5651        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5652    }
5653
5654    /**
5655     * Called by the view system when the focus state of this view changes.
5656     * When the focus change event is caused by directional navigation, direction
5657     * and previouslyFocusedRect provide insight into where the focus is coming from.
5658     * When overriding, be sure to call up through to the super class so that
5659     * the standard focus handling will occur.
5660     *
5661     * @param gainFocus True if the View has focus; false otherwise.
5662     * @param direction The direction focus has moved when requestFocus()
5663     *                  is called to give this view focus. Values are
5664     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5665     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5666     *                  It may not always apply, in which case use the default.
5667     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5668     *        system, of the previously focused view.  If applicable, this will be
5669     *        passed in as finer grained information about where the focus is coming
5670     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5671     */
5672    @CallSuper
5673    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5674            @Nullable Rect previouslyFocusedRect) {
5675        if (gainFocus) {
5676            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5677        } else {
5678            notifyViewAccessibilityStateChangedIfNeeded(
5679                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5680        }
5681
5682        InputMethodManager imm = InputMethodManager.peekInstance();
5683        if (!gainFocus) {
5684            if (isPressed()) {
5685                setPressed(false);
5686            }
5687            if (imm != null && mAttachInfo != null
5688                    && mAttachInfo.mHasWindowFocus) {
5689                imm.focusOut(this);
5690            }
5691            onFocusLost();
5692        } else if (imm != null && mAttachInfo != null
5693                && mAttachInfo.mHasWindowFocus) {
5694            imm.focusIn(this);
5695        }
5696
5697        invalidate(true);
5698        ListenerInfo li = mListenerInfo;
5699        if (li != null && li.mOnFocusChangeListener != null) {
5700            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5701        }
5702
5703        if (mAttachInfo != null) {
5704            mAttachInfo.mKeyDispatchState.reset(this);
5705        }
5706    }
5707
5708    /**
5709     * Sends an accessibility event of the given type. If accessibility is
5710     * not enabled this method has no effect. The default implementation calls
5711     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5712     * to populate information about the event source (this View), then calls
5713     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5714     * populate the text content of the event source including its descendants,
5715     * and last calls
5716     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5717     * on its parent to request sending of the event to interested parties.
5718     * <p>
5719     * If an {@link AccessibilityDelegate} has been specified via calling
5720     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5721     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5722     * responsible for handling this call.
5723     * </p>
5724     *
5725     * @param eventType The type of the event to send, as defined by several types from
5726     * {@link android.view.accessibility.AccessibilityEvent}, such as
5727     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5728     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5729     *
5730     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5731     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5732     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5733     * @see AccessibilityDelegate
5734     */
5735    public void sendAccessibilityEvent(int eventType) {
5736        if (mAccessibilityDelegate != null) {
5737            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5738        } else {
5739            sendAccessibilityEventInternal(eventType);
5740        }
5741    }
5742
5743    /**
5744     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5745     * {@link AccessibilityEvent} to make an announcement which is related to some
5746     * sort of a context change for which none of the events representing UI transitions
5747     * is a good fit. For example, announcing a new page in a book. If accessibility
5748     * is not enabled this method does nothing.
5749     *
5750     * @param text The announcement text.
5751     */
5752    public void announceForAccessibility(CharSequence text) {
5753        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5754            AccessibilityEvent event = AccessibilityEvent.obtain(
5755                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5756            onInitializeAccessibilityEvent(event);
5757            event.getText().add(text);
5758            event.setContentDescription(null);
5759            mParent.requestSendAccessibilityEvent(this, event);
5760        }
5761    }
5762
5763    /**
5764     * @see #sendAccessibilityEvent(int)
5765     *
5766     * Note: Called from the default {@link AccessibilityDelegate}.
5767     *
5768     * @hide
5769     */
5770    public void sendAccessibilityEventInternal(int eventType) {
5771        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5772            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5773        }
5774    }
5775
5776    /**
5777     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5778     * takes as an argument an empty {@link AccessibilityEvent} and does not
5779     * perform a check whether accessibility is enabled.
5780     * <p>
5781     * If an {@link AccessibilityDelegate} has been specified via calling
5782     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5783     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5784     * is responsible for handling this call.
5785     * </p>
5786     *
5787     * @param event The event to send.
5788     *
5789     * @see #sendAccessibilityEvent(int)
5790     */
5791    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5792        if (mAccessibilityDelegate != null) {
5793            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5794        } else {
5795            sendAccessibilityEventUncheckedInternal(event);
5796        }
5797    }
5798
5799    /**
5800     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5801     *
5802     * Note: Called from the default {@link AccessibilityDelegate}.
5803     *
5804     * @hide
5805     */
5806    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5807        if (!isShown()) {
5808            return;
5809        }
5810        onInitializeAccessibilityEvent(event);
5811        // Only a subset of accessibility events populates text content.
5812        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5813            dispatchPopulateAccessibilityEvent(event);
5814        }
5815        // In the beginning we called #isShown(), so we know that getParent() is not null.
5816        getParent().requestSendAccessibilityEvent(this, event);
5817    }
5818
5819    /**
5820     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5821     * to its children for adding their text content to the event. Note that the
5822     * event text is populated in a separate dispatch path since we add to the
5823     * event not only the text of the source but also the text of all its descendants.
5824     * A typical implementation will call
5825     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5826     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5827     * on each child. Override this method if custom population of the event text
5828     * content is required.
5829     * <p>
5830     * If an {@link AccessibilityDelegate} has been specified via calling
5831     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5832     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5833     * is responsible for handling this call.
5834     * </p>
5835     * <p>
5836     * <em>Note:</em> Accessibility events of certain types are not dispatched for
5837     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5838     * </p>
5839     *
5840     * @param event The event.
5841     *
5842     * @return True if the event population was completed.
5843     */
5844    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5845        if (mAccessibilityDelegate != null) {
5846            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5847        } else {
5848            return dispatchPopulateAccessibilityEventInternal(event);
5849        }
5850    }
5851
5852    /**
5853     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5854     *
5855     * Note: Called from the default {@link AccessibilityDelegate}.
5856     *
5857     * @hide
5858     */
5859    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5860        onPopulateAccessibilityEvent(event);
5861        return false;
5862    }
5863
5864    /**
5865     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5866     * giving a chance to this View to populate the accessibility event with its
5867     * text content. While this method is free to modify event
5868     * attributes other than text content, doing so should normally be performed in
5869     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5870     * <p>
5871     * Example: Adding formatted date string to an accessibility event in addition
5872     *          to the text added by the super implementation:
5873     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5874     *     super.onPopulateAccessibilityEvent(event);
5875     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5876     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5877     *         mCurrentDate.getTimeInMillis(), flags);
5878     *     event.getText().add(selectedDateUtterance);
5879     * }</pre>
5880     * <p>
5881     * If an {@link AccessibilityDelegate} has been specified via calling
5882     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5883     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5884     * is responsible for handling this call.
5885     * </p>
5886     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5887     * information to the event, in case the default implementation has basic information to add.
5888     * </p>
5889     *
5890     * @param event The accessibility event which to populate.
5891     *
5892     * @see #sendAccessibilityEvent(int)
5893     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5894     */
5895    @CallSuper
5896    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5897        if (mAccessibilityDelegate != null) {
5898            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5899        } else {
5900            onPopulateAccessibilityEventInternal(event);
5901        }
5902    }
5903
5904    /**
5905     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5906     *
5907     * Note: Called from the default {@link AccessibilityDelegate}.
5908     *
5909     * @hide
5910     */
5911    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5912    }
5913
5914    /**
5915     * Initializes an {@link AccessibilityEvent} with information about
5916     * this View which is the event source. In other words, the source of
5917     * an accessibility event is the view whose state change triggered firing
5918     * the event.
5919     * <p>
5920     * Example: Setting the password property of an event in addition
5921     *          to properties set by the super implementation:
5922     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5923     *     super.onInitializeAccessibilityEvent(event);
5924     *     event.setPassword(true);
5925     * }</pre>
5926     * <p>
5927     * If an {@link AccessibilityDelegate} has been specified via calling
5928     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5929     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5930     * is responsible for handling this call.
5931     * </p>
5932     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5933     * information to the event, in case the default implementation has basic information to add.
5934     * </p>
5935     * @param event The event to initialize.
5936     *
5937     * @see #sendAccessibilityEvent(int)
5938     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5939     */
5940    @CallSuper
5941    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5942        if (mAccessibilityDelegate != null) {
5943            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5944        } else {
5945            onInitializeAccessibilityEventInternal(event);
5946        }
5947    }
5948
5949    /**
5950     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5951     *
5952     * Note: Called from the default {@link AccessibilityDelegate}.
5953     *
5954     * @hide
5955     */
5956    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5957        event.setSource(this);
5958        event.setClassName(getAccessibilityClassName());
5959        event.setPackageName(getContext().getPackageName());
5960        event.setEnabled(isEnabled());
5961        event.setContentDescription(mContentDescription);
5962
5963        switch (event.getEventType()) {
5964            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5965                ArrayList<View> focusablesTempList = (mAttachInfo != null)
5966                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5967                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5968                event.setItemCount(focusablesTempList.size());
5969                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5970                if (mAttachInfo != null) {
5971                    focusablesTempList.clear();
5972                }
5973            } break;
5974            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5975                CharSequence text = getIterableTextForAccessibility();
5976                if (text != null && text.length() > 0) {
5977                    event.setFromIndex(getAccessibilitySelectionStart());
5978                    event.setToIndex(getAccessibilitySelectionEnd());
5979                    event.setItemCount(text.length());
5980                }
5981            } break;
5982        }
5983    }
5984
5985    /**
5986     * Returns an {@link AccessibilityNodeInfo} representing this view from the
5987     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
5988     * This method is responsible for obtaining an accessibility node info from a
5989     * pool of reusable instances and calling
5990     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
5991     * initialize the former.
5992     * <p>
5993     * Note: The client is responsible for recycling the obtained instance by calling
5994     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
5995     * </p>
5996     *
5997     * @return A populated {@link AccessibilityNodeInfo}.
5998     *
5999     * @see AccessibilityNodeInfo
6000     */
6001    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6002        if (mAccessibilityDelegate != null) {
6003            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6004        } else {
6005            return createAccessibilityNodeInfoInternal();
6006        }
6007    }
6008
6009    /**
6010     * @see #createAccessibilityNodeInfo()
6011     *
6012     * @hide
6013     */
6014    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6015        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6016        if (provider != null) {
6017            return provider.createAccessibilityNodeInfo(View.NO_ID);
6018        } else {
6019            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6020            onInitializeAccessibilityNodeInfo(info);
6021            return info;
6022        }
6023    }
6024
6025    /**
6026     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6027     * The base implementation sets:
6028     * <ul>
6029     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6030     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6031     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6032     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6033     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6034     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6035     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6036     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6037     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6038     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6039     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6040     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6041     *   <li>{@link AccessibilityNodeInfo#setStylusButtonPressable(boolean)}</li>
6042     * </ul>
6043     * <p>
6044     * Subclasses should override this method, call the super implementation,
6045     * and set additional attributes.
6046     * </p>
6047     * <p>
6048     * If an {@link AccessibilityDelegate} has been specified via calling
6049     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6050     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6051     * is responsible for handling this call.
6052     * </p>
6053     *
6054     * @param info The instance to initialize.
6055     */
6056    @CallSuper
6057    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6058        if (mAccessibilityDelegate != null) {
6059            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6060        } else {
6061            onInitializeAccessibilityNodeInfoInternal(info);
6062        }
6063    }
6064
6065    /**
6066     * Gets the location of this view in screen coordinates.
6067     *
6068     * @param outRect The output location
6069     * @hide
6070     */
6071    public void getBoundsOnScreen(Rect outRect) {
6072        getBoundsOnScreen(outRect, false);
6073    }
6074
6075    /**
6076     * Gets the location of this view in screen coordinates.
6077     *
6078     * @param outRect The output location
6079     * @param clipToParent Whether to clip child bounds to the parent ones.
6080     * @hide
6081     */
6082    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6083        if (mAttachInfo == null) {
6084            return;
6085        }
6086
6087        RectF position = mAttachInfo.mTmpTransformRect;
6088        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6089
6090        if (!hasIdentityMatrix()) {
6091            getMatrix().mapRect(position);
6092        }
6093
6094        position.offset(mLeft, mTop);
6095
6096        ViewParent parent = mParent;
6097        while (parent instanceof View) {
6098            View parentView = (View) parent;
6099
6100            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6101
6102            if (clipToParent) {
6103                position.left = Math.max(position.left, 0);
6104                position.top = Math.max(position.top, 0);
6105                position.right = Math.min(position.right, parentView.getWidth());
6106                position.bottom = Math.min(position.bottom, parentView.getHeight());
6107            }
6108
6109            if (!parentView.hasIdentityMatrix()) {
6110                parentView.getMatrix().mapRect(position);
6111            }
6112
6113            position.offset(parentView.mLeft, parentView.mTop);
6114
6115            parent = parentView.mParent;
6116        }
6117
6118        if (parent instanceof ViewRootImpl) {
6119            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6120            position.offset(0, -viewRootImpl.mCurScrollY);
6121        }
6122
6123        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6124
6125        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
6126                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
6127    }
6128
6129    /**
6130     * Return the class name of this object to be used for accessibility purposes.
6131     * Subclasses should only override this if they are implementing something that
6132     * should be seen as a completely new class of view when used by accessibility,
6133     * unrelated to the class it is deriving from.  This is used to fill in
6134     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6135     */
6136    public CharSequence getAccessibilityClassName() {
6137        return View.class.getName();
6138    }
6139
6140    /**
6141     * Called when assist structure is being retrieved from a view as part of
6142     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6143     * @param structure Fill in with structured view data.  The default implementation
6144     * fills in all data that can be inferred from the view itself.
6145     */
6146    public void onProvideStructure(ViewStructure structure) {
6147        final int id = mID;
6148        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6149                && (id&0x0000ffff) != 0) {
6150            String pkg, type, entry;
6151            try {
6152                final Resources res = getResources();
6153                entry = res.getResourceEntryName(id);
6154                type = res.getResourceTypeName(id);
6155                pkg = res.getResourcePackageName(id);
6156            } catch (Resources.NotFoundException e) {
6157                entry = type = pkg = null;
6158            }
6159            structure.setId(id, pkg, type, entry);
6160        } else {
6161            structure.setId(id, null, null, null);
6162        }
6163        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6164        structure.setVisibility(getVisibility());
6165        structure.setEnabled(isEnabled());
6166        if (isClickable()) {
6167            structure.setClickable(true);
6168        }
6169        if (isFocusable()) {
6170            structure.setFocusable(true);
6171        }
6172        if (isFocused()) {
6173            structure.setFocused(true);
6174        }
6175        if (isAccessibilityFocused()) {
6176            structure.setAccessibilityFocused(true);
6177        }
6178        if (isSelected()) {
6179            structure.setSelected(true);
6180        }
6181        if (isActivated()) {
6182            structure.setActivated(true);
6183        }
6184        if (isLongClickable()) {
6185            structure.setLongClickable(true);
6186        }
6187        if (this instanceof Checkable) {
6188            structure.setCheckable(true);
6189            if (((Checkable)this).isChecked()) {
6190                structure.setChecked(true);
6191            }
6192        }
6193        if (isStylusButtonPressable()) {
6194            structure.setStylusButtonPressable(true);
6195        }
6196        structure.setClassName(getAccessibilityClassName().toString());
6197        structure.setContentDescription(getContentDescription());
6198    }
6199
6200    /** @hide */
6201    public void onProvideAssistStructure(ViewStructure structure) {
6202        onProvideStructure(structure);
6203    }
6204
6205    /**
6206     * Called when assist structure is being retrieved from a view as part of
6207     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6208     * generate additional virtual structure under this view.  The defaullt implementation
6209     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6210     * view's virtual accessibility nodes, if any.  You can override this for a more
6211     * optimal implementation providing this data.
6212     */
6213    public void onProvideVirtualStructure(ViewStructure structure) {
6214        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6215        if (provider != null) {
6216            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6217            Log.i("View", "Provider of " + this + ": children=" + info.getChildCount());
6218            structure.setChildCount(1);
6219            ViewStructure root = structure.newChild(0);
6220            populateVirtualStructure(root, provider, info);
6221            info.recycle();
6222        }
6223    }
6224
6225    /** @hide */
6226    public void onProvideVirtualAssistStructure(ViewStructure structure) {
6227        onProvideVirtualStructure(structure);
6228    }
6229
6230    private void populateVirtualStructure(ViewStructure structure,
6231            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6232        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6233                null, null, null);
6234        Rect rect = structure.getTempRect();
6235        info.getBoundsInParent(rect);
6236        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6237        structure.setVisibility(VISIBLE);
6238        structure.setEnabled(info.isEnabled());
6239        if (info.isClickable()) {
6240            structure.setClickable(true);
6241        }
6242        if (info.isFocusable()) {
6243            structure.setFocusable(true);
6244        }
6245        if (info.isFocused()) {
6246            structure.setFocused(true);
6247        }
6248        if (info.isAccessibilityFocused()) {
6249            structure.setAccessibilityFocused(true);
6250        }
6251        if (info.isSelected()) {
6252            structure.setSelected(true);
6253        }
6254        if (info.isLongClickable()) {
6255            structure.setLongClickable(true);
6256        }
6257        if (info.isCheckable()) {
6258            structure.setCheckable(true);
6259            if (info.isChecked()) {
6260                structure.setChecked(true);
6261            }
6262        }
6263        if (info.isStylusButtonPressable()) {
6264            structure.setStylusButtonPressable(true);
6265        }
6266        CharSequence cname = info.getClassName();
6267        structure.setClassName(cname != null ? cname.toString() : null);
6268        structure.setContentDescription(info.getContentDescription());
6269        Log.i("View", "vassist " + cname + " @ " + rect.toShortString()
6270                + " text=" + info.getText() + " cd=" + info.getContentDescription());
6271        if (info.getText() != null || info.getError() != null) {
6272            structure.setText(info.getText(), info.getTextSelectionStart(),
6273                    info.getTextSelectionEnd());
6274        }
6275        final int NCHILDREN = info.getChildCount();
6276        if (NCHILDREN > 0) {
6277            structure.setChildCount(NCHILDREN);
6278            for (int i=0; i<NCHILDREN; i++) {
6279                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6280                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6281                ViewStructure child = structure.newChild(i);
6282                populateVirtualStructure(child, provider, cinfo);
6283                cinfo.recycle();
6284            }
6285        }
6286    }
6287
6288    /**
6289     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6290     * implementation calls {@link #onProvideStructure} and
6291     * {@link #onProvideVirtualStructure}.
6292     */
6293    public void dispatchProvideStructure(ViewStructure structure) {
6294        if (!isAssistBlocked()) {
6295            onProvideAssistStructure(structure);
6296            onProvideVirtualAssistStructure(structure);
6297        } else {
6298            structure.setClassName(getAccessibilityClassName().toString());
6299            structure.setAssistBlocked(true);
6300        }
6301    }
6302
6303    /**
6304     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6305     *
6306     * Note: Called from the default {@link AccessibilityDelegate}.
6307     *
6308     * @hide
6309     */
6310    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6311        Rect bounds = mAttachInfo.mTmpInvalRect;
6312
6313        getDrawingRect(bounds);
6314        info.setBoundsInParent(bounds);
6315
6316        getBoundsOnScreen(bounds, true);
6317        info.setBoundsInScreen(bounds);
6318
6319        ViewParent parent = getParentForAccessibility();
6320        if (parent instanceof View) {
6321            info.setParent((View) parent);
6322        }
6323
6324        if (mID != View.NO_ID) {
6325            View rootView = getRootView();
6326            if (rootView == null) {
6327                rootView = this;
6328            }
6329
6330            View label = rootView.findLabelForView(this, mID);
6331            if (label != null) {
6332                info.setLabeledBy(label);
6333            }
6334
6335            if ((mAttachInfo.mAccessibilityFetchFlags
6336                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6337                    && Resources.resourceHasPackage(mID)) {
6338                try {
6339                    String viewId = getResources().getResourceName(mID);
6340                    info.setViewIdResourceName(viewId);
6341                } catch (Resources.NotFoundException nfe) {
6342                    /* ignore */
6343                }
6344            }
6345        }
6346
6347        if (mLabelForId != View.NO_ID) {
6348            View rootView = getRootView();
6349            if (rootView == null) {
6350                rootView = this;
6351            }
6352            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6353            if (labeled != null) {
6354                info.setLabelFor(labeled);
6355            }
6356        }
6357
6358        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6359            View rootView = getRootView();
6360            if (rootView == null) {
6361                rootView = this;
6362            }
6363            View next = rootView.findViewInsideOutShouldExist(this,
6364                    mAccessibilityTraversalBeforeId);
6365            if (next != null) {
6366                info.setTraversalBefore(next);
6367            }
6368        }
6369
6370        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6371            View rootView = getRootView();
6372            if (rootView == null) {
6373                rootView = this;
6374            }
6375            View next = rootView.findViewInsideOutShouldExist(this,
6376                    mAccessibilityTraversalAfterId);
6377            if (next != null) {
6378                info.setTraversalAfter(next);
6379            }
6380        }
6381
6382        info.setVisibleToUser(isVisibleToUser());
6383
6384        info.setPackageName(mContext.getPackageName());
6385        info.setClassName(getAccessibilityClassName());
6386        info.setContentDescription(getContentDescription());
6387
6388        info.setEnabled(isEnabled());
6389        info.setClickable(isClickable());
6390        info.setFocusable(isFocusable());
6391        info.setFocused(isFocused());
6392        info.setAccessibilityFocused(isAccessibilityFocused());
6393        info.setSelected(isSelected());
6394        info.setLongClickable(isLongClickable());
6395        info.setStylusButtonPressable(isStylusButtonPressable());
6396        info.setLiveRegion(getAccessibilityLiveRegion());
6397
6398        // TODO: These make sense only if we are in an AdapterView but all
6399        // views can be selected. Maybe from accessibility perspective
6400        // we should report as selectable view in an AdapterView.
6401        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6402        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6403
6404        if (isFocusable()) {
6405            if (isFocused()) {
6406                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6407            } else {
6408                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6409            }
6410        }
6411
6412        if (!isAccessibilityFocused()) {
6413            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6414        } else {
6415            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6416        }
6417
6418        if (isClickable() && isEnabled()) {
6419            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6420        }
6421
6422        if (isLongClickable() && isEnabled()) {
6423            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6424        }
6425
6426        if (isStylusButtonPressable() && isEnabled()) {
6427            info.addAction(AccessibilityAction.ACTION_STYLUS_BUTTON_PRESS);
6428        }
6429
6430        CharSequence text = getIterableTextForAccessibility();
6431        if (text != null && text.length() > 0) {
6432            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6433
6434            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6435            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6436            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6437            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6438                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6439                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6440        }
6441
6442        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6443    }
6444
6445    private View findLabelForView(View view, int labeledId) {
6446        if (mMatchLabelForPredicate == null) {
6447            mMatchLabelForPredicate = new MatchLabelForPredicate();
6448        }
6449        mMatchLabelForPredicate.mLabeledId = labeledId;
6450        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6451    }
6452
6453    /**
6454     * Computes whether this view is visible to the user. Such a view is
6455     * attached, visible, all its predecessors are visible, it is not clipped
6456     * entirely by its predecessors, and has an alpha greater than zero.
6457     *
6458     * @return Whether the view is visible on the screen.
6459     *
6460     * @hide
6461     */
6462    protected boolean isVisibleToUser() {
6463        return isVisibleToUser(null);
6464    }
6465
6466    /**
6467     * Computes whether the given portion of this view is visible to the user.
6468     * Such a view is attached, visible, all its predecessors are visible,
6469     * has an alpha greater than zero, and the specified portion is not
6470     * clipped entirely by its predecessors.
6471     *
6472     * @param boundInView the portion of the view to test; coordinates should be relative; may be
6473     *                    <code>null</code>, and the entire view will be tested in this case.
6474     *                    When <code>true</code> is returned by the function, the actual visible
6475     *                    region will be stored in this parameter; that is, if boundInView is fully
6476     *                    contained within the view, no modification will be made, otherwise regions
6477     *                    outside of the visible area of the view will be clipped.
6478     *
6479     * @return Whether the specified portion of the view is visible on the screen.
6480     *
6481     * @hide
6482     */
6483    protected boolean isVisibleToUser(Rect boundInView) {
6484        if (mAttachInfo != null) {
6485            // Attached to invisible window means this view is not visible.
6486            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6487                return false;
6488            }
6489            // An invisible predecessor or one with alpha zero means
6490            // that this view is not visible to the user.
6491            Object current = this;
6492            while (current instanceof View) {
6493                View view = (View) current;
6494                // We have attach info so this view is attached and there is no
6495                // need to check whether we reach to ViewRootImpl on the way up.
6496                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6497                        view.getVisibility() != VISIBLE) {
6498                    return false;
6499                }
6500                current = view.mParent;
6501            }
6502            // Check if the view is entirely covered by its predecessors.
6503            Rect visibleRect = mAttachInfo.mTmpInvalRect;
6504            Point offset = mAttachInfo.mPoint;
6505            if (!getGlobalVisibleRect(visibleRect, offset)) {
6506                return false;
6507            }
6508            // Check if the visible portion intersects the rectangle of interest.
6509            if (boundInView != null) {
6510                visibleRect.offset(-offset.x, -offset.y);
6511                return boundInView.intersect(visibleRect);
6512            }
6513            return true;
6514        }
6515        return false;
6516    }
6517
6518    /**
6519     * Returns the delegate for implementing accessibility support via
6520     * composition. For more details see {@link AccessibilityDelegate}.
6521     *
6522     * @return The delegate, or null if none set.
6523     *
6524     * @hide
6525     */
6526    public AccessibilityDelegate getAccessibilityDelegate() {
6527        return mAccessibilityDelegate;
6528    }
6529
6530    /**
6531     * Sets a delegate for implementing accessibility support via composition as
6532     * opposed to inheritance. The delegate's primary use is for implementing
6533     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
6534     *
6535     * @param delegate The delegate instance.
6536     *
6537     * @see AccessibilityDelegate
6538     */
6539    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6540        mAccessibilityDelegate = delegate;
6541    }
6542
6543    /**
6544     * Gets the provider for managing a virtual view hierarchy rooted at this View
6545     * and reported to {@link android.accessibilityservice.AccessibilityService}s
6546     * that explore the window content.
6547     * <p>
6548     * If this method returns an instance, this instance is responsible for managing
6549     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6550     * View including the one representing the View itself. Similarly the returned
6551     * instance is responsible for performing accessibility actions on any virtual
6552     * view or the root view itself.
6553     * </p>
6554     * <p>
6555     * If an {@link AccessibilityDelegate} has been specified via calling
6556     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6557     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6558     * is responsible for handling this call.
6559     * </p>
6560     *
6561     * @return The provider.
6562     *
6563     * @see AccessibilityNodeProvider
6564     */
6565    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6566        if (mAccessibilityDelegate != null) {
6567            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6568        } else {
6569            return null;
6570        }
6571    }
6572
6573    /**
6574     * Gets the unique identifier of this view on the screen for accessibility purposes.
6575     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6576     *
6577     * @return The view accessibility id.
6578     *
6579     * @hide
6580     */
6581    public int getAccessibilityViewId() {
6582        if (mAccessibilityViewId == NO_ID) {
6583            mAccessibilityViewId = sNextAccessibilityViewId++;
6584        }
6585        return mAccessibilityViewId;
6586    }
6587
6588    /**
6589     * Gets the unique identifier of the window in which this View reseides.
6590     *
6591     * @return The window accessibility id.
6592     *
6593     * @hide
6594     */
6595    public int getAccessibilityWindowId() {
6596        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6597                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6598    }
6599
6600    /**
6601     * Gets the {@link View} description. It briefly describes the view and is
6602     * primarily used for accessibility support. Set this property to enable
6603     * better accessibility support for your application. This is especially
6604     * true for views that do not have textual representation (For example,
6605     * ImageButton).
6606     *
6607     * @return The content description.
6608     *
6609     * @attr ref android.R.styleable#View_contentDescription
6610     */
6611    @ViewDebug.ExportedProperty(category = "accessibility")
6612    public CharSequence getContentDescription() {
6613        return mContentDescription;
6614    }
6615
6616    /**
6617     * Sets the {@link View} description. It briefly describes the view and is
6618     * primarily used for accessibility support. Set this property to enable
6619     * better accessibility support for your application. This is especially
6620     * true for views that do not have textual representation (For example,
6621     * ImageButton).
6622     *
6623     * @param contentDescription The content description.
6624     *
6625     * @attr ref android.R.styleable#View_contentDescription
6626     */
6627    @RemotableViewMethod
6628    public void setContentDescription(CharSequence contentDescription) {
6629        if (mContentDescription == null) {
6630            if (contentDescription == null) {
6631                return;
6632            }
6633        } else if (mContentDescription.equals(contentDescription)) {
6634            return;
6635        }
6636        mContentDescription = contentDescription;
6637        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6638        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6639            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6640            notifySubtreeAccessibilityStateChangedIfNeeded();
6641        } else {
6642            notifyViewAccessibilityStateChangedIfNeeded(
6643                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6644        }
6645    }
6646
6647    /**
6648     * Sets the id of a view before which this one is visited in accessibility traversal.
6649     * A screen-reader must visit the content of this view before the content of the one
6650     * it precedes. For example, if view B is set to be before view A, then a screen-reader
6651     * will traverse the entire content of B before traversing the entire content of A,
6652     * regardles of what traversal strategy it is using.
6653     * <p>
6654     * Views that do not have specified before/after relationships are traversed in order
6655     * determined by the screen-reader.
6656     * </p>
6657     * <p>
6658     * Setting that this view is before a view that is not important for accessibility
6659     * or if this view is not important for accessibility will have no effect as the
6660     * screen-reader is not aware of unimportant views.
6661     * </p>
6662     *
6663     * @param beforeId The id of a view this one precedes in accessibility traversal.
6664     *
6665     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6666     *
6667     * @see #setImportantForAccessibility(int)
6668     */
6669    @RemotableViewMethod
6670    public void setAccessibilityTraversalBefore(int beforeId) {
6671        if (mAccessibilityTraversalBeforeId == beforeId) {
6672            return;
6673        }
6674        mAccessibilityTraversalBeforeId = beforeId;
6675        notifyViewAccessibilityStateChangedIfNeeded(
6676                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6677    }
6678
6679    /**
6680     * Gets the id of a view before which this one is visited in accessibility traversal.
6681     *
6682     * @return The id of a view this one precedes in accessibility traversal if
6683     *         specified, otherwise {@link #NO_ID}.
6684     *
6685     * @see #setAccessibilityTraversalBefore(int)
6686     */
6687    public int getAccessibilityTraversalBefore() {
6688        return mAccessibilityTraversalBeforeId;
6689    }
6690
6691    /**
6692     * Sets the id of a view after which this one is visited in accessibility traversal.
6693     * A screen-reader must visit the content of the other view before the content of this
6694     * one. For example, if view B is set to be after view A, then a screen-reader
6695     * will traverse the entire content of A before traversing the entire content of B,
6696     * regardles of what traversal strategy it is using.
6697     * <p>
6698     * Views that do not have specified before/after relationships are traversed in order
6699     * determined by the screen-reader.
6700     * </p>
6701     * <p>
6702     * Setting that this view is after a view that is not important for accessibility
6703     * or if this view is not important for accessibility will have no effect as the
6704     * screen-reader is not aware of unimportant views.
6705     * </p>
6706     *
6707     * @param afterId The id of a view this one succedees in accessibility traversal.
6708     *
6709     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6710     *
6711     * @see #setImportantForAccessibility(int)
6712     */
6713    @RemotableViewMethod
6714    public void setAccessibilityTraversalAfter(int afterId) {
6715        if (mAccessibilityTraversalAfterId == afterId) {
6716            return;
6717        }
6718        mAccessibilityTraversalAfterId = afterId;
6719        notifyViewAccessibilityStateChangedIfNeeded(
6720                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6721    }
6722
6723    /**
6724     * Gets the id of a view after which this one is visited in accessibility traversal.
6725     *
6726     * @return The id of a view this one succeedes in accessibility traversal if
6727     *         specified, otherwise {@link #NO_ID}.
6728     *
6729     * @see #setAccessibilityTraversalAfter(int)
6730     */
6731    public int getAccessibilityTraversalAfter() {
6732        return mAccessibilityTraversalAfterId;
6733    }
6734
6735    /**
6736     * Gets the id of a view for which this view serves as a label for
6737     * accessibility purposes.
6738     *
6739     * @return The labeled view id.
6740     */
6741    @ViewDebug.ExportedProperty(category = "accessibility")
6742    public int getLabelFor() {
6743        return mLabelForId;
6744    }
6745
6746    /**
6747     * Sets the id of a view for which this view serves as a label for
6748     * accessibility purposes.
6749     *
6750     * @param id The labeled view id.
6751     */
6752    @RemotableViewMethod
6753    public void setLabelFor(@IdRes int id) {
6754        if (mLabelForId == id) {
6755            return;
6756        }
6757        mLabelForId = id;
6758        if (mLabelForId != View.NO_ID
6759                && mID == View.NO_ID) {
6760            mID = generateViewId();
6761        }
6762        notifyViewAccessibilityStateChangedIfNeeded(
6763                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6764    }
6765
6766    /**
6767     * Invoked whenever this view loses focus, either by losing window focus or by losing
6768     * focus within its window. This method can be used to clear any state tied to the
6769     * focus. For instance, if a button is held pressed with the trackball and the window
6770     * loses focus, this method can be used to cancel the press.
6771     *
6772     * Subclasses of View overriding this method should always call super.onFocusLost().
6773     *
6774     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6775     * @see #onWindowFocusChanged(boolean)
6776     *
6777     * @hide pending API council approval
6778     */
6779    @CallSuper
6780    protected void onFocusLost() {
6781        resetPressedState();
6782    }
6783
6784    private void resetPressedState() {
6785        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6786            return;
6787        }
6788
6789        if (isPressed()) {
6790            setPressed(false);
6791
6792            if (!mHasPerformedLongPress) {
6793                removeLongPressCallback();
6794            }
6795        }
6796    }
6797
6798    /**
6799     * Returns true if this view has focus
6800     *
6801     * @return True if this view has focus, false otherwise.
6802     */
6803    @ViewDebug.ExportedProperty(category = "focus")
6804    public boolean isFocused() {
6805        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6806    }
6807
6808    /**
6809     * Find the view in the hierarchy rooted at this view that currently has
6810     * focus.
6811     *
6812     * @return The view that currently has focus, or null if no focused view can
6813     *         be found.
6814     */
6815    public View findFocus() {
6816        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6817    }
6818
6819    /**
6820     * Indicates whether this view is one of the set of scrollable containers in
6821     * its window.
6822     *
6823     * @return whether this view is one of the set of scrollable containers in
6824     * its window
6825     *
6826     * @attr ref android.R.styleable#View_isScrollContainer
6827     */
6828    public boolean isScrollContainer() {
6829        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6830    }
6831
6832    /**
6833     * Change whether this view is one of the set of scrollable containers in
6834     * its window.  This will be used to determine whether the window can
6835     * resize or must pan when a soft input area is open -- scrollable
6836     * containers allow the window to use resize mode since the container
6837     * will appropriately shrink.
6838     *
6839     * @attr ref android.R.styleable#View_isScrollContainer
6840     */
6841    public void setScrollContainer(boolean isScrollContainer) {
6842        if (isScrollContainer) {
6843            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6844                mAttachInfo.mScrollContainers.add(this);
6845                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6846            }
6847            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6848        } else {
6849            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6850                mAttachInfo.mScrollContainers.remove(this);
6851            }
6852            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6853        }
6854    }
6855
6856    /**
6857     * Returns the quality of the drawing cache.
6858     *
6859     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6860     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6861     *
6862     * @see #setDrawingCacheQuality(int)
6863     * @see #setDrawingCacheEnabled(boolean)
6864     * @see #isDrawingCacheEnabled()
6865     *
6866     * @attr ref android.R.styleable#View_drawingCacheQuality
6867     */
6868    @DrawingCacheQuality
6869    public int getDrawingCacheQuality() {
6870        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6871    }
6872
6873    /**
6874     * Set the drawing cache quality of this view. This value is used only when the
6875     * drawing cache is enabled
6876     *
6877     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6878     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6879     *
6880     * @see #getDrawingCacheQuality()
6881     * @see #setDrawingCacheEnabled(boolean)
6882     * @see #isDrawingCacheEnabled()
6883     *
6884     * @attr ref android.R.styleable#View_drawingCacheQuality
6885     */
6886    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6887        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6888    }
6889
6890    /**
6891     * Returns whether the screen should remain on, corresponding to the current
6892     * value of {@link #KEEP_SCREEN_ON}.
6893     *
6894     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6895     *
6896     * @see #setKeepScreenOn(boolean)
6897     *
6898     * @attr ref android.R.styleable#View_keepScreenOn
6899     */
6900    public boolean getKeepScreenOn() {
6901        return (mViewFlags & KEEP_SCREEN_ON) != 0;
6902    }
6903
6904    /**
6905     * Controls whether the screen should remain on, modifying the
6906     * value of {@link #KEEP_SCREEN_ON}.
6907     *
6908     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6909     *
6910     * @see #getKeepScreenOn()
6911     *
6912     * @attr ref android.R.styleable#View_keepScreenOn
6913     */
6914    public void setKeepScreenOn(boolean keepScreenOn) {
6915        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6916    }
6917
6918    /**
6919     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6920     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6921     *
6922     * @attr ref android.R.styleable#View_nextFocusLeft
6923     */
6924    public int getNextFocusLeftId() {
6925        return mNextFocusLeftId;
6926    }
6927
6928    /**
6929     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6930     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6931     * decide automatically.
6932     *
6933     * @attr ref android.R.styleable#View_nextFocusLeft
6934     */
6935    public void setNextFocusLeftId(int nextFocusLeftId) {
6936        mNextFocusLeftId = nextFocusLeftId;
6937    }
6938
6939    /**
6940     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6941     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6942     *
6943     * @attr ref android.R.styleable#View_nextFocusRight
6944     */
6945    public int getNextFocusRightId() {
6946        return mNextFocusRightId;
6947    }
6948
6949    /**
6950     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6951     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6952     * decide automatically.
6953     *
6954     * @attr ref android.R.styleable#View_nextFocusRight
6955     */
6956    public void setNextFocusRightId(int nextFocusRightId) {
6957        mNextFocusRightId = nextFocusRightId;
6958    }
6959
6960    /**
6961     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6962     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6963     *
6964     * @attr ref android.R.styleable#View_nextFocusUp
6965     */
6966    public int getNextFocusUpId() {
6967        return mNextFocusUpId;
6968    }
6969
6970    /**
6971     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6972     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6973     * decide automatically.
6974     *
6975     * @attr ref android.R.styleable#View_nextFocusUp
6976     */
6977    public void setNextFocusUpId(int nextFocusUpId) {
6978        mNextFocusUpId = nextFocusUpId;
6979    }
6980
6981    /**
6982     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6983     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6984     *
6985     * @attr ref android.R.styleable#View_nextFocusDown
6986     */
6987    public int getNextFocusDownId() {
6988        return mNextFocusDownId;
6989    }
6990
6991    /**
6992     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6993     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
6994     * decide automatically.
6995     *
6996     * @attr ref android.R.styleable#View_nextFocusDown
6997     */
6998    public void setNextFocusDownId(int nextFocusDownId) {
6999        mNextFocusDownId = nextFocusDownId;
7000    }
7001
7002    /**
7003     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7004     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7005     *
7006     * @attr ref android.R.styleable#View_nextFocusForward
7007     */
7008    public int getNextFocusForwardId() {
7009        return mNextFocusForwardId;
7010    }
7011
7012    /**
7013     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7014     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7015     * decide automatically.
7016     *
7017     * @attr ref android.R.styleable#View_nextFocusForward
7018     */
7019    public void setNextFocusForwardId(int nextFocusForwardId) {
7020        mNextFocusForwardId = nextFocusForwardId;
7021    }
7022
7023    /**
7024     * Returns the visibility of this view and all of its ancestors
7025     *
7026     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7027     */
7028    public boolean isShown() {
7029        View current = this;
7030        //noinspection ConstantConditions
7031        do {
7032            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7033                return false;
7034            }
7035            ViewParent parent = current.mParent;
7036            if (parent == null) {
7037                return false; // We are not attached to the view root
7038            }
7039            if (!(parent instanceof View)) {
7040                return true;
7041            }
7042            current = (View) parent;
7043        } while (current != null);
7044
7045        return false;
7046    }
7047
7048    /**
7049     * Called by the view hierarchy when the content insets for a window have
7050     * changed, to allow it to adjust its content to fit within those windows.
7051     * The content insets tell you the space that the status bar, input method,
7052     * and other system windows infringe on the application's window.
7053     *
7054     * <p>You do not normally need to deal with this function, since the default
7055     * window decoration given to applications takes care of applying it to the
7056     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7057     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7058     * and your content can be placed under those system elements.  You can then
7059     * use this method within your view hierarchy if you have parts of your UI
7060     * which you would like to ensure are not being covered.
7061     *
7062     * <p>The default implementation of this method simply applies the content
7063     * insets to the view's padding, consuming that content (modifying the
7064     * insets to be 0), and returning true.  This behavior is off by default, but can
7065     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7066     *
7067     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7068     * insets object is propagated down the hierarchy, so any changes made to it will
7069     * be seen by all following views (including potentially ones above in
7070     * the hierarchy since this is a depth-first traversal).  The first view
7071     * that returns true will abort the entire traversal.
7072     *
7073     * <p>The default implementation works well for a situation where it is
7074     * used with a container that covers the entire window, allowing it to
7075     * apply the appropriate insets to its content on all edges.  If you need
7076     * a more complicated layout (such as two different views fitting system
7077     * windows, one on the top of the window, and one on the bottom),
7078     * you can override the method and handle the insets however you would like.
7079     * Note that the insets provided by the framework are always relative to the
7080     * far edges of the window, not accounting for the location of the called view
7081     * within that window.  (In fact when this method is called you do not yet know
7082     * where the layout will place the view, as it is done before layout happens.)
7083     *
7084     * <p>Note: unlike many View methods, there is no dispatch phase to this
7085     * call.  If you are overriding it in a ViewGroup and want to allow the
7086     * call to continue to your children, you must be sure to call the super
7087     * implementation.
7088     *
7089     * <p>Here is a sample layout that makes use of fitting system windows
7090     * to have controls for a video view placed inside of the window decorations
7091     * that it hides and shows.  This can be used with code like the second
7092     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7093     *
7094     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7095     *
7096     * @param insets Current content insets of the window.  Prior to
7097     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7098     * the insets or else you and Android will be unhappy.
7099     *
7100     * @return {@code true} if this view applied the insets and it should not
7101     * continue propagating further down the hierarchy, {@code false} otherwise.
7102     * @see #getFitsSystemWindows()
7103     * @see #setFitsSystemWindows(boolean)
7104     * @see #setSystemUiVisibility(int)
7105     *
7106     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7107     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7108     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7109     * to implement handling their own insets.
7110     */
7111    protected boolean fitSystemWindows(Rect insets) {
7112        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7113            if (insets == null) {
7114                // Null insets by definition have already been consumed.
7115                // This call cannot apply insets since there are none to apply,
7116                // so return false.
7117                return false;
7118            }
7119            // If we're not in the process of dispatching the newer apply insets call,
7120            // that means we're not in the compatibility path. Dispatch into the newer
7121            // apply insets path and take things from there.
7122            try {
7123                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7124                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7125            } finally {
7126                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7127            }
7128        } else {
7129            // We're being called from the newer apply insets path.
7130            // Perform the standard fallback behavior.
7131            return fitSystemWindowsInt(insets);
7132        }
7133    }
7134
7135    private boolean fitSystemWindowsInt(Rect insets) {
7136        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7137            mUserPaddingStart = UNDEFINED_PADDING;
7138            mUserPaddingEnd = UNDEFINED_PADDING;
7139            Rect localInsets = sThreadLocal.get();
7140            if (localInsets == null) {
7141                localInsets = new Rect();
7142                sThreadLocal.set(localInsets);
7143            }
7144            boolean res = computeFitSystemWindows(insets, localInsets);
7145            mUserPaddingLeftInitial = localInsets.left;
7146            mUserPaddingRightInitial = localInsets.right;
7147            internalSetPadding(localInsets.left, localInsets.top,
7148                    localInsets.right, localInsets.bottom);
7149            return res;
7150        }
7151        return false;
7152    }
7153
7154    /**
7155     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7156     *
7157     * <p>This method should be overridden by views that wish to apply a policy different from or
7158     * in addition to the default behavior. Clients that wish to force a view subtree
7159     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7160     *
7161     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7162     * it will be called during dispatch instead of this method. The listener may optionally
7163     * call this method from its own implementation if it wishes to apply the view's default
7164     * insets policy in addition to its own.</p>
7165     *
7166     * <p>Implementations of this method should either return the insets parameter unchanged
7167     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7168     * that this view applied itself. This allows new inset types added in future platform
7169     * versions to pass through existing implementations unchanged without being erroneously
7170     * consumed.</p>
7171     *
7172     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7173     * property is set then the view will consume the system window insets and apply them
7174     * as padding for the view.</p>
7175     *
7176     * @param insets Insets to apply
7177     * @return The supplied insets with any applied insets consumed
7178     */
7179    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7180        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7181            // We weren't called from within a direct call to fitSystemWindows,
7182            // call into it as a fallback in case we're in a class that overrides it
7183            // and has logic to perform.
7184            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7185                return insets.consumeSystemWindowInsets();
7186            }
7187        } else {
7188            // We were called from within a direct call to fitSystemWindows.
7189            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7190                return insets.consumeSystemWindowInsets();
7191            }
7192        }
7193        return insets;
7194    }
7195
7196    /**
7197     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7198     * window insets to this view. The listener's
7199     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7200     * method will be called instead of the view's
7201     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7202     *
7203     * @param listener Listener to set
7204     *
7205     * @see #onApplyWindowInsets(WindowInsets)
7206     */
7207    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7208        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7209    }
7210
7211    /**
7212     * Request to apply the given window insets to this view or another view in its subtree.
7213     *
7214     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7215     * obscured by window decorations or overlays. This can include the status and navigation bars,
7216     * action bars, input methods and more. New inset categories may be added in the future.
7217     * The method returns the insets provided minus any that were applied by this view or its
7218     * children.</p>
7219     *
7220     * <p>Clients wishing to provide custom behavior should override the
7221     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7222     * {@link OnApplyWindowInsetsListener} via the
7223     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7224     * method.</p>
7225     *
7226     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7227     * </p>
7228     *
7229     * @param insets Insets to apply
7230     * @return The provided insets minus the insets that were consumed
7231     */
7232    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7233        try {
7234            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7235            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7236                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7237            } else {
7238                return onApplyWindowInsets(insets);
7239            }
7240        } finally {
7241            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7242        }
7243    }
7244
7245    /**
7246     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7247     * only available if the view is attached.
7248     *
7249     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7250     */
7251    public WindowInsets getRootWindowInsets() {
7252        if (mAttachInfo != null) {
7253            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7254        }
7255        return null;
7256    }
7257
7258    /**
7259     * @hide Compute the insets that should be consumed by this view and the ones
7260     * that should propagate to those under it.
7261     */
7262    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7263        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7264                || mAttachInfo == null
7265                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7266                        && !mAttachInfo.mOverscanRequested)) {
7267            outLocalInsets.set(inoutInsets);
7268            inoutInsets.set(0, 0, 0, 0);
7269            return true;
7270        } else {
7271            // The application wants to take care of fitting system window for
7272            // the content...  however we still need to take care of any overscan here.
7273            final Rect overscan = mAttachInfo.mOverscanInsets;
7274            outLocalInsets.set(overscan);
7275            inoutInsets.left -= overscan.left;
7276            inoutInsets.top -= overscan.top;
7277            inoutInsets.right -= overscan.right;
7278            inoutInsets.bottom -= overscan.bottom;
7279            return false;
7280        }
7281    }
7282
7283    /**
7284     * Compute insets that should be consumed by this view and the ones that should propagate
7285     * to those under it.
7286     *
7287     * @param in Insets currently being processed by this View, likely received as a parameter
7288     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7289     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7290     *                       by this view
7291     * @return Insets that should be passed along to views under this one
7292     */
7293    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7294        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7295                || mAttachInfo == null
7296                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7297            outLocalInsets.set(in.getSystemWindowInsets());
7298            return in.consumeSystemWindowInsets();
7299        } else {
7300            outLocalInsets.set(0, 0, 0, 0);
7301            return in;
7302        }
7303    }
7304
7305    /**
7306     * Sets whether or not this view should account for system screen decorations
7307     * such as the status bar and inset its content; that is, controlling whether
7308     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7309     * executed.  See that method for more details.
7310     *
7311     * <p>Note that if you are providing your own implementation of
7312     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7313     * flag to true -- your implementation will be overriding the default
7314     * implementation that checks this flag.
7315     *
7316     * @param fitSystemWindows If true, then the default implementation of
7317     * {@link #fitSystemWindows(Rect)} will be executed.
7318     *
7319     * @attr ref android.R.styleable#View_fitsSystemWindows
7320     * @see #getFitsSystemWindows()
7321     * @see #fitSystemWindows(Rect)
7322     * @see #setSystemUiVisibility(int)
7323     */
7324    public void setFitsSystemWindows(boolean fitSystemWindows) {
7325        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7326    }
7327
7328    /**
7329     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7330     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7331     * will be executed.
7332     *
7333     * @return {@code true} if the default implementation of
7334     * {@link #fitSystemWindows(Rect)} will be executed.
7335     *
7336     * @attr ref android.R.styleable#View_fitsSystemWindows
7337     * @see #setFitsSystemWindows(boolean)
7338     * @see #fitSystemWindows(Rect)
7339     * @see #setSystemUiVisibility(int)
7340     */
7341    @ViewDebug.ExportedProperty
7342    public boolean getFitsSystemWindows() {
7343        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7344    }
7345
7346    /** @hide */
7347    public boolean fitsSystemWindows() {
7348        return getFitsSystemWindows();
7349    }
7350
7351    /**
7352     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7353     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7354     */
7355    public void requestFitSystemWindows() {
7356        if (mParent != null) {
7357            mParent.requestFitSystemWindows();
7358        }
7359    }
7360
7361    /**
7362     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7363     */
7364    public void requestApplyInsets() {
7365        requestFitSystemWindows();
7366    }
7367
7368    /**
7369     * For use by PhoneWindow to make its own system window fitting optional.
7370     * @hide
7371     */
7372    public void makeOptionalFitsSystemWindows() {
7373        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7374    }
7375
7376    /**
7377     * Returns the visibility status for this view.
7378     *
7379     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7380     * @attr ref android.R.styleable#View_visibility
7381     */
7382    @ViewDebug.ExportedProperty(mapping = {
7383        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
7384        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7385        @ViewDebug.IntToString(from = GONE,      to = "GONE")
7386    })
7387    @Visibility
7388    public int getVisibility() {
7389        return mViewFlags & VISIBILITY_MASK;
7390    }
7391
7392    /**
7393     * Set the enabled state of this view.
7394     *
7395     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7396     * @attr ref android.R.styleable#View_visibility
7397     */
7398    @RemotableViewMethod
7399    public void setVisibility(@Visibility int visibility) {
7400        setFlags(visibility, VISIBILITY_MASK);
7401    }
7402
7403    /**
7404     * Returns the enabled status for this view. The interpretation of the
7405     * enabled state varies by subclass.
7406     *
7407     * @return True if this view is enabled, false otherwise.
7408     */
7409    @ViewDebug.ExportedProperty
7410    public boolean isEnabled() {
7411        return (mViewFlags & ENABLED_MASK) == ENABLED;
7412    }
7413
7414    /**
7415     * Set the enabled state of this view. The interpretation of the enabled
7416     * state varies by subclass.
7417     *
7418     * @param enabled True if this view is enabled, false otherwise.
7419     */
7420    @RemotableViewMethod
7421    public void setEnabled(boolean enabled) {
7422        if (enabled == isEnabled()) return;
7423
7424        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7425
7426        /*
7427         * The View most likely has to change its appearance, so refresh
7428         * the drawable state.
7429         */
7430        refreshDrawableState();
7431
7432        // Invalidate too, since the default behavior for views is to be
7433        // be drawn at 50% alpha rather than to change the drawable.
7434        invalidate(true);
7435
7436        if (!enabled) {
7437            cancelPendingInputEvents();
7438        }
7439    }
7440
7441    /**
7442     * Set whether this view can receive the focus.
7443     *
7444     * Setting this to false will also ensure that this view is not focusable
7445     * in touch mode.
7446     *
7447     * @param focusable If true, this view can receive the focus.
7448     *
7449     * @see #setFocusableInTouchMode(boolean)
7450     * @attr ref android.R.styleable#View_focusable
7451     */
7452    public void setFocusable(boolean focusable) {
7453        if (!focusable) {
7454            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7455        }
7456        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7457    }
7458
7459    /**
7460     * Set whether this view can receive focus while in touch mode.
7461     *
7462     * Setting this to true will also ensure that this view is focusable.
7463     *
7464     * @param focusableInTouchMode If true, this view can receive the focus while
7465     *   in touch mode.
7466     *
7467     * @see #setFocusable(boolean)
7468     * @attr ref android.R.styleable#View_focusableInTouchMode
7469     */
7470    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7471        // Focusable in touch mode should always be set before the focusable flag
7472        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7473        // which, in touch mode, will not successfully request focus on this view
7474        // because the focusable in touch mode flag is not set
7475        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7476        if (focusableInTouchMode) {
7477            setFlags(FOCUSABLE, FOCUSABLE_MASK);
7478        }
7479    }
7480
7481    /**
7482     * Set whether this view should have sound effects enabled for events such as
7483     * clicking and touching.
7484     *
7485     * <p>You may wish to disable sound effects for a view if you already play sounds,
7486     * for instance, a dial key that plays dtmf tones.
7487     *
7488     * @param soundEffectsEnabled whether sound effects are enabled for this view.
7489     * @see #isSoundEffectsEnabled()
7490     * @see #playSoundEffect(int)
7491     * @attr ref android.R.styleable#View_soundEffectsEnabled
7492     */
7493    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7494        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7495    }
7496
7497    /**
7498     * @return whether this view should have sound effects enabled for events such as
7499     *     clicking and touching.
7500     *
7501     * @see #setSoundEffectsEnabled(boolean)
7502     * @see #playSoundEffect(int)
7503     * @attr ref android.R.styleable#View_soundEffectsEnabled
7504     */
7505    @ViewDebug.ExportedProperty
7506    public boolean isSoundEffectsEnabled() {
7507        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7508    }
7509
7510    /**
7511     * Set whether this view should have haptic feedback for events such as
7512     * long presses.
7513     *
7514     * <p>You may wish to disable haptic feedback if your view already controls
7515     * its own haptic feedback.
7516     *
7517     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7518     * @see #isHapticFeedbackEnabled()
7519     * @see #performHapticFeedback(int)
7520     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7521     */
7522    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7523        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7524    }
7525
7526    /**
7527     * @return whether this view should have haptic feedback enabled for events
7528     * long presses.
7529     *
7530     * @see #setHapticFeedbackEnabled(boolean)
7531     * @see #performHapticFeedback(int)
7532     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7533     */
7534    @ViewDebug.ExportedProperty
7535    public boolean isHapticFeedbackEnabled() {
7536        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7537    }
7538
7539    /**
7540     * Returns the layout direction for this view.
7541     *
7542     * @return One of {@link #LAYOUT_DIRECTION_LTR},
7543     *   {@link #LAYOUT_DIRECTION_RTL},
7544     *   {@link #LAYOUT_DIRECTION_INHERIT} or
7545     *   {@link #LAYOUT_DIRECTION_LOCALE}.
7546     *
7547     * @attr ref android.R.styleable#View_layoutDirection
7548     *
7549     * @hide
7550     */
7551    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7552        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7553        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7554        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7555        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7556    })
7557    @LayoutDir
7558    public int getRawLayoutDirection() {
7559        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7560    }
7561
7562    /**
7563     * Set the layout direction for this view. This will propagate a reset of layout direction
7564     * resolution to the view's children and resolve layout direction for this view.
7565     *
7566     * @param layoutDirection the layout direction to set. Should be one of:
7567     *
7568     * {@link #LAYOUT_DIRECTION_LTR},
7569     * {@link #LAYOUT_DIRECTION_RTL},
7570     * {@link #LAYOUT_DIRECTION_INHERIT},
7571     * {@link #LAYOUT_DIRECTION_LOCALE}.
7572     *
7573     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7574     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7575     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7576     *
7577     * @attr ref android.R.styleable#View_layoutDirection
7578     */
7579    @RemotableViewMethod
7580    public void setLayoutDirection(@LayoutDir int layoutDirection) {
7581        if (getRawLayoutDirection() != layoutDirection) {
7582            // Reset the current layout direction and the resolved one
7583            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7584            resetRtlProperties();
7585            // Set the new layout direction (filtered)
7586            mPrivateFlags2 |=
7587                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7588            // We need to resolve all RTL properties as they all depend on layout direction
7589            resolveRtlPropertiesIfNeeded();
7590            requestLayout();
7591            invalidate(true);
7592        }
7593    }
7594
7595    /**
7596     * Returns the resolved layout direction for this view.
7597     *
7598     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7599     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7600     *
7601     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7602     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7603     *
7604     * @attr ref android.R.styleable#View_layoutDirection
7605     */
7606    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7607        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7608        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7609    })
7610    @ResolvedLayoutDir
7611    public int getLayoutDirection() {
7612        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7613        if (targetSdkVersion < JELLY_BEAN_MR1) {
7614            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7615            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7616        }
7617        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7618                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7619    }
7620
7621    /**
7622     * Indicates whether or not this view's layout is right-to-left. This is resolved from
7623     * layout attribute and/or the inherited value from the parent
7624     *
7625     * @return true if the layout is right-to-left.
7626     *
7627     * @hide
7628     */
7629    @ViewDebug.ExportedProperty(category = "layout")
7630    public boolean isLayoutRtl() {
7631        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7632    }
7633
7634    /**
7635     * Indicates whether the view is currently tracking transient state that the
7636     * app should not need to concern itself with saving and restoring, but that
7637     * the framework should take special note to preserve when possible.
7638     *
7639     * <p>A view with transient state cannot be trivially rebound from an external
7640     * data source, such as an adapter binding item views in a list. This may be
7641     * because the view is performing an animation, tracking user selection
7642     * of content, or similar.</p>
7643     *
7644     * @return true if the view has transient state
7645     */
7646    @ViewDebug.ExportedProperty(category = "layout")
7647    public boolean hasTransientState() {
7648        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7649    }
7650
7651    /**
7652     * Set whether this view is currently tracking transient state that the
7653     * framework should attempt to preserve when possible. This flag is reference counted,
7654     * so every call to setHasTransientState(true) should be paired with a later call
7655     * to setHasTransientState(false).
7656     *
7657     * <p>A view with transient state cannot be trivially rebound from an external
7658     * data source, such as an adapter binding item views in a list. This may be
7659     * because the view is performing an animation, tracking user selection
7660     * of content, or similar.</p>
7661     *
7662     * @param hasTransientState true if this view has transient state
7663     */
7664    public void setHasTransientState(boolean hasTransientState) {
7665        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7666                mTransientStateCount - 1;
7667        if (mTransientStateCount < 0) {
7668            mTransientStateCount = 0;
7669            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7670                    "unmatched pair of setHasTransientState calls");
7671        } else if ((hasTransientState && mTransientStateCount == 1) ||
7672                (!hasTransientState && mTransientStateCount == 0)) {
7673            // update flag if we've just incremented up from 0 or decremented down to 0
7674            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7675                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7676            if (mParent != null) {
7677                try {
7678                    mParent.childHasTransientStateChanged(this, hasTransientState);
7679                } catch (AbstractMethodError e) {
7680                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7681                            " does not fully implement ViewParent", e);
7682                }
7683            }
7684        }
7685    }
7686
7687    /**
7688     * Returns true if this view is currently attached to a window.
7689     */
7690    public boolean isAttachedToWindow() {
7691        return mAttachInfo != null;
7692    }
7693
7694    /**
7695     * Returns true if this view has been through at least one layout since it
7696     * was last attached to or detached from a window.
7697     */
7698    public boolean isLaidOut() {
7699        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7700    }
7701
7702    /**
7703     * If this view doesn't do any drawing on its own, set this flag to
7704     * allow further optimizations. By default, this flag is not set on
7705     * View, but could be set on some View subclasses such as ViewGroup.
7706     *
7707     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7708     * you should clear this flag.
7709     *
7710     * @param willNotDraw whether or not this View draw on its own
7711     */
7712    public void setWillNotDraw(boolean willNotDraw) {
7713        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7714    }
7715
7716    /**
7717     * Returns whether or not this View draws on its own.
7718     *
7719     * @return true if this view has nothing to draw, false otherwise
7720     */
7721    @ViewDebug.ExportedProperty(category = "drawing")
7722    public boolean willNotDraw() {
7723        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7724    }
7725
7726    /**
7727     * When a View's drawing cache is enabled, drawing is redirected to an
7728     * offscreen bitmap. Some views, like an ImageView, must be able to
7729     * bypass this mechanism if they already draw a single bitmap, to avoid
7730     * unnecessary usage of the memory.
7731     *
7732     * @param willNotCacheDrawing true if this view does not cache its
7733     *        drawing, false otherwise
7734     */
7735    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7736        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7737    }
7738
7739    /**
7740     * Returns whether or not this View can cache its drawing or not.
7741     *
7742     * @return true if this view does not cache its drawing, false otherwise
7743     */
7744    @ViewDebug.ExportedProperty(category = "drawing")
7745    public boolean willNotCacheDrawing() {
7746        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7747    }
7748
7749    /**
7750     * Indicates whether this view reacts to click events or not.
7751     *
7752     * @return true if the view is clickable, false otherwise
7753     *
7754     * @see #setClickable(boolean)
7755     * @attr ref android.R.styleable#View_clickable
7756     */
7757    @ViewDebug.ExportedProperty
7758    public boolean isClickable() {
7759        return (mViewFlags & CLICKABLE) == CLICKABLE;
7760    }
7761
7762    /**
7763     * Enables or disables click events for this view. When a view
7764     * is clickable it will change its state to "pressed" on every click.
7765     * Subclasses should set the view clickable to visually react to
7766     * user's clicks.
7767     *
7768     * @param clickable true to make the view clickable, false otherwise
7769     *
7770     * @see #isClickable()
7771     * @attr ref android.R.styleable#View_clickable
7772     */
7773    public void setClickable(boolean clickable) {
7774        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7775    }
7776
7777    /**
7778     * Indicates whether this view reacts to long click events or not.
7779     *
7780     * @return true if the view is long clickable, false otherwise
7781     *
7782     * @see #setLongClickable(boolean)
7783     * @attr ref android.R.styleable#View_longClickable
7784     */
7785    public boolean isLongClickable() {
7786        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7787    }
7788
7789    /**
7790     * Enables or disables long click events for this view. When a view is long
7791     * clickable it reacts to the user holding down the button for a longer
7792     * duration than a tap. This event can either launch the listener or a
7793     * context menu.
7794     *
7795     * @param longClickable true to make the view long clickable, false otherwise
7796     * @see #isLongClickable()
7797     * @attr ref android.R.styleable#View_longClickable
7798     */
7799    public void setLongClickable(boolean longClickable) {
7800        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7801    }
7802
7803    /**
7804     * Indicates whether this view reacts to stylus button press events or not.
7805     *
7806     * @return true if the view is stylus button pressable, false otherwise
7807     * @see #setStylusButtonPressable(boolean)
7808     * @attr ref android.R.styleable#View_stylusButtonPressable
7809     */
7810    public boolean isStylusButtonPressable() {
7811        return (mViewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE;
7812    }
7813
7814    /**
7815     * Enables or disables stylus button press events for this view. When a view is stylus button
7816     * pressable it reacts to the user touching the screen with a stylus and pressing the first
7817     * stylus button. This event can launch the listener.
7818     *
7819     * @param stylusButtonPressable true to make the view react to a stylus button press, false
7820     *            otherwise
7821     * @see #isStylusButtonPressable()
7822     * @attr ref android.R.styleable#View_stylusButtonPressable
7823     */
7824    public void setStylusButtonPressable(boolean stylusButtonPressable) {
7825        setFlags(stylusButtonPressable ? STYLUS_BUTTON_PRESSABLE : 0, STYLUS_BUTTON_PRESSABLE);
7826    }
7827
7828    /**
7829     * Sets the pressed state for this view and provides a touch coordinate for
7830     * animation hinting.
7831     *
7832     * @param pressed Pass true to set the View's internal state to "pressed",
7833     *            or false to reverts the View's internal state from a
7834     *            previously set "pressed" state.
7835     * @param x The x coordinate of the touch that caused the press
7836     * @param y The y coordinate of the touch that caused the press
7837     */
7838    private void setPressed(boolean pressed, float x, float y) {
7839        if (pressed) {
7840            drawableHotspotChanged(x, y);
7841        }
7842
7843        setPressed(pressed);
7844    }
7845
7846    /**
7847     * Sets the pressed state for this view.
7848     *
7849     * @see #isClickable()
7850     * @see #setClickable(boolean)
7851     *
7852     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7853     *        the View's internal state from a previously set "pressed" state.
7854     */
7855    public void setPressed(boolean pressed) {
7856        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7857
7858        if (pressed) {
7859            mPrivateFlags |= PFLAG_PRESSED;
7860        } else {
7861            mPrivateFlags &= ~PFLAG_PRESSED;
7862        }
7863
7864        if (needsRefresh) {
7865            refreshDrawableState();
7866        }
7867        dispatchSetPressed(pressed);
7868    }
7869
7870    /**
7871     * Dispatch setPressed to all of this View's children.
7872     *
7873     * @see #setPressed(boolean)
7874     *
7875     * @param pressed The new pressed state
7876     */
7877    protected void dispatchSetPressed(boolean pressed) {
7878    }
7879
7880    /**
7881     * Indicates whether the view is currently in pressed state. Unless
7882     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7883     * the pressed state.
7884     *
7885     * @see #setPressed(boolean)
7886     * @see #isClickable()
7887     * @see #setClickable(boolean)
7888     *
7889     * @return true if the view is currently pressed, false otherwise
7890     */
7891    @ViewDebug.ExportedProperty
7892    public boolean isPressed() {
7893        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7894    }
7895
7896    /**
7897     * @hide
7898     * Indicates whether this view will participate in data collection through
7899     * {@link ViewStructure}.  If true, it will not provide any data
7900     * for itself or its children.  If false, the normal data collection will be allowed.
7901     *
7902     * @return Returns false if assist data collection is not blocked, else true.
7903     *
7904     * @see #setAssistBlocked(boolean)
7905     * @attr ref android.R.styleable#View_assistBlocked
7906     */
7907    public boolean isAssistBlocked() {
7908        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
7909    }
7910
7911    /**
7912     * @hide
7913     * Controls whether assist data collection from this view and its children is enabled
7914     * (that is, whether {@link #onProvideStructure} and
7915     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
7916     * allowing normal assist collection.  Setting this to false will disable assist collection.
7917     *
7918     * @param enabled Set to true to <em>disable</em> assist data collection, or false
7919     * (the default) to allow it.
7920     *
7921     * @see #isAssistBlocked()
7922     * @see #onProvideStructure
7923     * @see #onProvideVirtualStructure
7924     * @attr ref android.R.styleable#View_assistBlocked
7925     */
7926    public void setAssistBlocked(boolean enabled) {
7927        if (enabled) {
7928            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
7929        } else {
7930            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
7931        }
7932    }
7933
7934    /**
7935     * Indicates whether this view will save its state (that is,
7936     * whether its {@link #onSaveInstanceState} method will be called).
7937     *
7938     * @return Returns true if the view state saving is enabled, else false.
7939     *
7940     * @see #setSaveEnabled(boolean)
7941     * @attr ref android.R.styleable#View_saveEnabled
7942     */
7943    public boolean isSaveEnabled() {
7944        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7945    }
7946
7947    /**
7948     * Controls whether the saving of this view's state is
7949     * enabled (that is, whether its {@link #onSaveInstanceState} method
7950     * will be called).  Note that even if freezing is enabled, the
7951     * view still must have an id assigned to it (via {@link #setId(int)})
7952     * for its state to be saved.  This flag can only disable the
7953     * saving of this view; any child views may still have their state saved.
7954     *
7955     * @param enabled Set to false to <em>disable</em> state saving, or true
7956     * (the default) to allow it.
7957     *
7958     * @see #isSaveEnabled()
7959     * @see #setId(int)
7960     * @see #onSaveInstanceState()
7961     * @attr ref android.R.styleable#View_saveEnabled
7962     */
7963    public void setSaveEnabled(boolean enabled) {
7964        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
7965    }
7966
7967    /**
7968     * Gets whether the framework should discard touches when the view's
7969     * window is obscured by another visible window.
7970     * Refer to the {@link View} security documentation for more details.
7971     *
7972     * @return True if touch filtering is enabled.
7973     *
7974     * @see #setFilterTouchesWhenObscured(boolean)
7975     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7976     */
7977    @ViewDebug.ExportedProperty
7978    public boolean getFilterTouchesWhenObscured() {
7979        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
7980    }
7981
7982    /**
7983     * Sets whether the framework should discard touches when the view's
7984     * window is obscured by another visible window.
7985     * Refer to the {@link View} security documentation for more details.
7986     *
7987     * @param enabled True if touch filtering should be enabled.
7988     *
7989     * @see #getFilterTouchesWhenObscured
7990     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7991     */
7992    public void setFilterTouchesWhenObscured(boolean enabled) {
7993        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
7994                FILTER_TOUCHES_WHEN_OBSCURED);
7995    }
7996
7997    /**
7998     * Indicates whether the entire hierarchy under this view will save its
7999     * state when a state saving traversal occurs from its parent.  The default
8000     * is true; if false, these views will not be saved unless
8001     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8002     *
8003     * @return Returns true if the view state saving from parent is enabled, else false.
8004     *
8005     * @see #setSaveFromParentEnabled(boolean)
8006     */
8007    public boolean isSaveFromParentEnabled() {
8008        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8009    }
8010
8011    /**
8012     * Controls whether the entire hierarchy under this view will save its
8013     * state when a state saving traversal occurs from its parent.  The default
8014     * is true; if false, these views will not be saved unless
8015     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8016     *
8017     * @param enabled Set to false to <em>disable</em> state saving, or true
8018     * (the default) to allow it.
8019     *
8020     * @see #isSaveFromParentEnabled()
8021     * @see #setId(int)
8022     * @see #onSaveInstanceState()
8023     */
8024    public void setSaveFromParentEnabled(boolean enabled) {
8025        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8026    }
8027
8028
8029    /**
8030     * Returns whether this View is able to take focus.
8031     *
8032     * @return True if this view can take focus, or false otherwise.
8033     * @attr ref android.R.styleable#View_focusable
8034     */
8035    @ViewDebug.ExportedProperty(category = "focus")
8036    public final boolean isFocusable() {
8037        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8038    }
8039
8040    /**
8041     * When a view is focusable, it may not want to take focus when in touch mode.
8042     * For example, a button would like focus when the user is navigating via a D-pad
8043     * so that the user can click on it, but once the user starts touching the screen,
8044     * the button shouldn't take focus
8045     * @return Whether the view is focusable in touch mode.
8046     * @attr ref android.R.styleable#View_focusableInTouchMode
8047     */
8048    @ViewDebug.ExportedProperty
8049    public final boolean isFocusableInTouchMode() {
8050        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8051    }
8052
8053    /**
8054     * Find the nearest view in the specified direction that can take focus.
8055     * This does not actually give focus to that view.
8056     *
8057     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8058     *
8059     * @return The nearest focusable in the specified direction, or null if none
8060     *         can be found.
8061     */
8062    public View focusSearch(@FocusRealDirection int direction) {
8063        if (mParent != null) {
8064            return mParent.focusSearch(this, direction);
8065        } else {
8066            return null;
8067        }
8068    }
8069
8070    /**
8071     * This method is the last chance for the focused view and its ancestors to
8072     * respond to an arrow key. This is called when the focused view did not
8073     * consume the key internally, nor could the view system find a new view in
8074     * the requested direction to give focus to.
8075     *
8076     * @param focused The currently focused view.
8077     * @param direction The direction focus wants to move. One of FOCUS_UP,
8078     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8079     * @return True if the this view consumed this unhandled move.
8080     */
8081    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8082        return false;
8083    }
8084
8085    /**
8086     * If a user manually specified the next view id for a particular direction,
8087     * use the root to look up the view.
8088     * @param root The root view of the hierarchy containing this view.
8089     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8090     * or FOCUS_BACKWARD.
8091     * @return The user specified next view, or null if there is none.
8092     */
8093    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8094        switch (direction) {
8095            case FOCUS_LEFT:
8096                if (mNextFocusLeftId == View.NO_ID) return null;
8097                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8098            case FOCUS_RIGHT:
8099                if (mNextFocusRightId == View.NO_ID) return null;
8100                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8101            case FOCUS_UP:
8102                if (mNextFocusUpId == View.NO_ID) return null;
8103                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8104            case FOCUS_DOWN:
8105                if (mNextFocusDownId == View.NO_ID) return null;
8106                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8107            case FOCUS_FORWARD:
8108                if (mNextFocusForwardId == View.NO_ID) return null;
8109                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8110            case FOCUS_BACKWARD: {
8111                if (mID == View.NO_ID) return null;
8112                final int id = mID;
8113                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8114                    @Override
8115                    public boolean apply(View t) {
8116                        return t.mNextFocusForwardId == id;
8117                    }
8118                });
8119            }
8120        }
8121        return null;
8122    }
8123
8124    private View findViewInsideOutShouldExist(View root, int id) {
8125        if (mMatchIdPredicate == null) {
8126            mMatchIdPredicate = new MatchIdPredicate();
8127        }
8128        mMatchIdPredicate.mId = id;
8129        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8130        if (result == null) {
8131            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8132        }
8133        return result;
8134    }
8135
8136    /**
8137     * Find and return all focusable views that are descendants of this view,
8138     * possibly including this view if it is focusable itself.
8139     *
8140     * @param direction The direction of the focus
8141     * @return A list of focusable views
8142     */
8143    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8144        ArrayList<View> result = new ArrayList<View>(24);
8145        addFocusables(result, direction);
8146        return result;
8147    }
8148
8149    /**
8150     * Add any focusable views that are descendants of this view (possibly
8151     * including this view if it is focusable itself) to views.  If we are in touch mode,
8152     * only add views that are also focusable in touch mode.
8153     *
8154     * @param views Focusable views found so far
8155     * @param direction The direction of the focus
8156     */
8157    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8158        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
8159    }
8160
8161    /**
8162     * Adds any focusable views that are descendants of this view (possibly
8163     * including this view if it is focusable itself) to views. This method
8164     * adds all focusable views regardless if we are in touch mode or
8165     * only views focusable in touch mode if we are in touch mode or
8166     * only views that can take accessibility focus if accessibility is enabled
8167     * depending on the focusable mode parameter.
8168     *
8169     * @param views Focusable views found so far or null if all we are interested is
8170     *        the number of focusables.
8171     * @param direction The direction of the focus.
8172     * @param focusableMode The type of focusables to be added.
8173     *
8174     * @see #FOCUSABLES_ALL
8175     * @see #FOCUSABLES_TOUCH_MODE
8176     */
8177    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8178            @FocusableMode int focusableMode) {
8179        if (views == null) {
8180            return;
8181        }
8182        if (!isFocusable()) {
8183            return;
8184        }
8185        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8186                && isInTouchMode() && !isFocusableInTouchMode()) {
8187            return;
8188        }
8189        views.add(this);
8190    }
8191
8192    /**
8193     * Finds the Views that contain given text. The containment is case insensitive.
8194     * The search is performed by either the text that the View renders or the content
8195     * description that describes the view for accessibility purposes and the view does
8196     * not render or both. Clients can specify how the search is to be performed via
8197     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8198     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8199     *
8200     * @param outViews The output list of matching Views.
8201     * @param searched The text to match against.
8202     *
8203     * @see #FIND_VIEWS_WITH_TEXT
8204     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8205     * @see #setContentDescription(CharSequence)
8206     */
8207    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8208            @FindViewFlags int flags) {
8209        if (getAccessibilityNodeProvider() != null) {
8210            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8211                outViews.add(this);
8212            }
8213        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8214                && (searched != null && searched.length() > 0)
8215                && (mContentDescription != null && mContentDescription.length() > 0)) {
8216            String searchedLowerCase = searched.toString().toLowerCase();
8217            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8218            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8219                outViews.add(this);
8220            }
8221        }
8222    }
8223
8224    /**
8225     * Find and return all touchable views that are descendants of this view,
8226     * possibly including this view if it is touchable itself.
8227     *
8228     * @return A list of touchable views
8229     */
8230    public ArrayList<View> getTouchables() {
8231        ArrayList<View> result = new ArrayList<View>();
8232        addTouchables(result);
8233        return result;
8234    }
8235
8236    /**
8237     * Add any touchable views that are descendants of this view (possibly
8238     * including this view if it is touchable itself) to views.
8239     *
8240     * @param views Touchable views found so far
8241     */
8242    public void addTouchables(ArrayList<View> views) {
8243        final int viewFlags = mViewFlags;
8244
8245        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8246                || (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE)
8247                && (viewFlags & ENABLED_MASK) == ENABLED) {
8248            views.add(this);
8249        }
8250    }
8251
8252    /**
8253     * Returns whether this View is accessibility focused.
8254     *
8255     * @return True if this View is accessibility focused.
8256     */
8257    public boolean isAccessibilityFocused() {
8258        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8259    }
8260
8261    /**
8262     * Call this to try to give accessibility focus to this view.
8263     *
8264     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8265     * returns false or the view is no visible or the view already has accessibility
8266     * focus.
8267     *
8268     * See also {@link #focusSearch(int)}, which is what you call to say that you
8269     * have focus, and you want your parent to look for the next one.
8270     *
8271     * @return Whether this view actually took accessibility focus.
8272     *
8273     * @hide
8274     */
8275    public boolean requestAccessibilityFocus() {
8276        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8277        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8278            return false;
8279        }
8280        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8281            return false;
8282        }
8283        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8284            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8285            ViewRootImpl viewRootImpl = getViewRootImpl();
8286            if (viewRootImpl != null) {
8287                viewRootImpl.setAccessibilityFocus(this, null);
8288            }
8289            invalidate();
8290            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8291            return true;
8292        }
8293        return false;
8294    }
8295
8296    /**
8297     * Call this to try to clear accessibility focus of this view.
8298     *
8299     * See also {@link #focusSearch(int)}, which is what you call to say that you
8300     * have focus, and you want your parent to look for the next one.
8301     *
8302     * @hide
8303     */
8304    public void clearAccessibilityFocus() {
8305        clearAccessibilityFocusNoCallbacks();
8306        // Clear the global reference of accessibility focus if this
8307        // view or any of its descendants had accessibility focus.
8308        ViewRootImpl viewRootImpl = getViewRootImpl();
8309        if (viewRootImpl != null) {
8310            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8311            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8312                viewRootImpl.setAccessibilityFocus(null, null);
8313            }
8314        }
8315    }
8316
8317    private void sendAccessibilityHoverEvent(int eventType) {
8318        // Since we are not delivering to a client accessibility events from not
8319        // important views (unless the clinet request that) we need to fire the
8320        // event from the deepest view exposed to the client. As a consequence if
8321        // the user crosses a not exposed view the client will see enter and exit
8322        // of the exposed predecessor followed by and enter and exit of that same
8323        // predecessor when entering and exiting the not exposed descendant. This
8324        // is fine since the client has a clear idea which view is hovered at the
8325        // price of a couple more events being sent. This is a simple and
8326        // working solution.
8327        View source = this;
8328        while (true) {
8329            if (source.includeForAccessibility()) {
8330                source.sendAccessibilityEvent(eventType);
8331                return;
8332            }
8333            ViewParent parent = source.getParent();
8334            if (parent instanceof View) {
8335                source = (View) parent;
8336            } else {
8337                return;
8338            }
8339        }
8340    }
8341
8342    /**
8343     * Clears accessibility focus without calling any callback methods
8344     * normally invoked in {@link #clearAccessibilityFocus()}. This method
8345     * is used for clearing accessibility focus when giving this focus to
8346     * another view.
8347     */
8348    void clearAccessibilityFocusNoCallbacks() {
8349        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
8350            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
8351            invalidate();
8352            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
8353        }
8354    }
8355
8356    /**
8357     * Call this to try to give focus to a specific view or to one of its
8358     * descendants.
8359     *
8360     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8361     * false), or if it is focusable and it is not focusable in touch mode
8362     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8363     *
8364     * See also {@link #focusSearch(int)}, which is what you call to say that you
8365     * have focus, and you want your parent to look for the next one.
8366     *
8367     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
8368     * {@link #FOCUS_DOWN} and <code>null</code>.
8369     *
8370     * @return Whether this view or one of its descendants actually took focus.
8371     */
8372    public final boolean requestFocus() {
8373        return requestFocus(View.FOCUS_DOWN);
8374    }
8375
8376    /**
8377     * Call this to try to give focus to a specific view or to one of its
8378     * descendants and give it a hint about what direction focus is heading.
8379     *
8380     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8381     * false), or if it is focusable and it is not focusable in touch mode
8382     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8383     *
8384     * See also {@link #focusSearch(int)}, which is what you call to say that you
8385     * have focus, and you want your parent to look for the next one.
8386     *
8387     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
8388     * <code>null</code> set for the previously focused rectangle.
8389     *
8390     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8391     * @return Whether this view or one of its descendants actually took focus.
8392     */
8393    public final boolean requestFocus(int direction) {
8394        return requestFocus(direction, null);
8395    }
8396
8397    /**
8398     * Call this to try to give focus to a specific view or to one of its descendants
8399     * and give it hints about the direction and a specific rectangle that the focus
8400     * is coming from.  The rectangle can help give larger views a finer grained hint
8401     * about where focus is coming from, and therefore, where to show selection, or
8402     * forward focus change internally.
8403     *
8404     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8405     * false), or if it is focusable and it is not focusable in touch mode
8406     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8407     *
8408     * A View will not take focus if it is not visible.
8409     *
8410     * A View will not take focus if one of its parents has
8411     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
8412     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
8413     *
8414     * See also {@link #focusSearch(int)}, which is what you call to say that you
8415     * have focus, and you want your parent to look for the next one.
8416     *
8417     * You may wish to override this method if your custom {@link View} has an internal
8418     * {@link View} that it wishes to forward the request to.
8419     *
8420     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8421     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8422     *        to give a finer grained hint about where focus is coming from.  May be null
8423     *        if there is no hint.
8424     * @return Whether this view or one of its descendants actually took focus.
8425     */
8426    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8427        return requestFocusNoSearch(direction, previouslyFocusedRect);
8428    }
8429
8430    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8431        // need to be focusable
8432        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8433                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8434            return false;
8435        }
8436
8437        // need to be focusable in touch mode if in touch mode
8438        if (isInTouchMode() &&
8439            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8440               return false;
8441        }
8442
8443        // need to not have any parents blocking us
8444        if (hasAncestorThatBlocksDescendantFocus()) {
8445            return false;
8446        }
8447
8448        handleFocusGainInternal(direction, previouslyFocusedRect);
8449        return true;
8450    }
8451
8452    /**
8453     * Call this to try to give focus to a specific view or to one of its descendants. This is a
8454     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8455     * touch mode to request focus when they are touched.
8456     *
8457     * @return Whether this view or one of its descendants actually took focus.
8458     *
8459     * @see #isInTouchMode()
8460     *
8461     */
8462    public final boolean requestFocusFromTouch() {
8463        // Leave touch mode if we need to
8464        if (isInTouchMode()) {
8465            ViewRootImpl viewRoot = getViewRootImpl();
8466            if (viewRoot != null) {
8467                viewRoot.ensureTouchMode(false);
8468            }
8469        }
8470        return requestFocus(View.FOCUS_DOWN);
8471    }
8472
8473    /**
8474     * @return Whether any ancestor of this view blocks descendant focus.
8475     */
8476    private boolean hasAncestorThatBlocksDescendantFocus() {
8477        final boolean focusableInTouchMode = isFocusableInTouchMode();
8478        ViewParent ancestor = mParent;
8479        while (ancestor instanceof ViewGroup) {
8480            final ViewGroup vgAncestor = (ViewGroup) ancestor;
8481            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8482                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8483                return true;
8484            } else {
8485                ancestor = vgAncestor.getParent();
8486            }
8487        }
8488        return false;
8489    }
8490
8491    /**
8492     * Gets the mode for determining whether this View is important for accessibility
8493     * which is if it fires accessibility events and if it is reported to
8494     * accessibility services that query the screen.
8495     *
8496     * @return The mode for determining whether a View is important for accessibility.
8497     *
8498     * @attr ref android.R.styleable#View_importantForAccessibility
8499     *
8500     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8501     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8502     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8503     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8504     */
8505    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8506            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8507            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8508            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8509            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8510                    to = "noHideDescendants")
8511        })
8512    public int getImportantForAccessibility() {
8513        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8514                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8515    }
8516
8517    /**
8518     * Sets the live region mode for this view. This indicates to accessibility
8519     * services whether they should automatically notify the user about changes
8520     * to the view's content description or text, or to the content descriptions
8521     * or text of the view's children (where applicable).
8522     * <p>
8523     * For example, in a login screen with a TextView that displays an "incorrect
8524     * password" notification, that view should be marked as a live region with
8525     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8526     * <p>
8527     * To disable change notifications for this view, use
8528     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8529     * mode for most views.
8530     * <p>
8531     * To indicate that the user should be notified of changes, use
8532     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8533     * <p>
8534     * If the view's changes should interrupt ongoing speech and notify the user
8535     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8536     *
8537     * @param mode The live region mode for this view, one of:
8538     *        <ul>
8539     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8540     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8541     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8542     *        </ul>
8543     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8544     */
8545    public void setAccessibilityLiveRegion(int mode) {
8546        if (mode != getAccessibilityLiveRegion()) {
8547            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8548            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8549                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8550            notifyViewAccessibilityStateChangedIfNeeded(
8551                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8552        }
8553    }
8554
8555    /**
8556     * Gets the live region mode for this View.
8557     *
8558     * @return The live region mode for the view.
8559     *
8560     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8561     *
8562     * @see #setAccessibilityLiveRegion(int)
8563     */
8564    public int getAccessibilityLiveRegion() {
8565        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8566                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8567    }
8568
8569    /**
8570     * Sets how to determine whether this view is important for accessibility
8571     * which is if it fires accessibility events and if it is reported to
8572     * accessibility services that query the screen.
8573     *
8574     * @param mode How to determine whether this view is important for accessibility.
8575     *
8576     * @attr ref android.R.styleable#View_importantForAccessibility
8577     *
8578     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8579     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8580     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8581     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8582     */
8583    public void setImportantForAccessibility(int mode) {
8584        final int oldMode = getImportantForAccessibility();
8585        if (mode != oldMode) {
8586            // If we're moving between AUTO and another state, we might not need
8587            // to send a subtree changed notification. We'll store the computed
8588            // importance, since we'll need to check it later to make sure.
8589            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8590                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8591            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8592            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8593            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8594                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8595            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8596                notifySubtreeAccessibilityStateChangedIfNeeded();
8597            } else {
8598                notifyViewAccessibilityStateChangedIfNeeded(
8599                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8600            }
8601        }
8602    }
8603
8604    /**
8605     * Computes whether this view should be exposed for accessibility. In
8606     * general, views that are interactive or provide information are exposed
8607     * while views that serve only as containers are hidden.
8608     * <p>
8609     * If an ancestor of this view has importance
8610     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8611     * returns <code>false</code>.
8612     * <p>
8613     * Otherwise, the value is computed according to the view's
8614     * {@link #getImportantForAccessibility()} value:
8615     * <ol>
8616     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8617     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8618     * </code>
8619     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8620     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8621     * view satisfies any of the following:
8622     * <ul>
8623     * <li>Is actionable, e.g. {@link #isClickable()},
8624     * {@link #isLongClickable()}, or {@link #isFocusable()}
8625     * <li>Has an {@link AccessibilityDelegate}
8626     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8627     * {@link OnKeyListener}, etc.
8628     * <li>Is an accessibility live region, e.g.
8629     * {@link #getAccessibilityLiveRegion()} is not
8630     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8631     * </ul>
8632     * </ol>
8633     *
8634     * @return Whether the view is exposed for accessibility.
8635     * @see #setImportantForAccessibility(int)
8636     * @see #getImportantForAccessibility()
8637     */
8638    public boolean isImportantForAccessibility() {
8639        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8640                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8641        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8642                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8643            return false;
8644        }
8645
8646        // Check parent mode to ensure we're not hidden.
8647        ViewParent parent = mParent;
8648        while (parent instanceof View) {
8649            if (((View) parent).getImportantForAccessibility()
8650                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8651                return false;
8652            }
8653            parent = parent.getParent();
8654        }
8655
8656        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8657                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8658                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8659    }
8660
8661    /**
8662     * Gets the parent for accessibility purposes. Note that the parent for
8663     * accessibility is not necessary the immediate parent. It is the first
8664     * predecessor that is important for accessibility.
8665     *
8666     * @return The parent for accessibility purposes.
8667     */
8668    public ViewParent getParentForAccessibility() {
8669        if (mParent instanceof View) {
8670            View parentView = (View) mParent;
8671            if (parentView.includeForAccessibility()) {
8672                return mParent;
8673            } else {
8674                return mParent.getParentForAccessibility();
8675            }
8676        }
8677        return null;
8678    }
8679
8680    /**
8681     * Adds the children of a given View for accessibility. Since some Views are
8682     * not important for accessibility the children for accessibility are not
8683     * necessarily direct children of the view, rather they are the first level of
8684     * descendants important for accessibility.
8685     *
8686     * @param children The list of children for accessibility.
8687     */
8688    public void addChildrenForAccessibility(ArrayList<View> children) {
8689
8690    }
8691
8692    /**
8693     * Whether to regard this view for accessibility. A view is regarded for
8694     * accessibility if it is important for accessibility or the querying
8695     * accessibility service has explicitly requested that view not
8696     * important for accessibility are regarded.
8697     *
8698     * @return Whether to regard the view for accessibility.
8699     *
8700     * @hide
8701     */
8702    public boolean includeForAccessibility() {
8703        if (mAttachInfo != null) {
8704            return (mAttachInfo.mAccessibilityFetchFlags
8705                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8706                    || isImportantForAccessibility();
8707        }
8708        return false;
8709    }
8710
8711    /**
8712     * Returns whether the View is considered actionable from
8713     * accessibility perspective. Such view are important for
8714     * accessibility.
8715     *
8716     * @return True if the view is actionable for accessibility.
8717     *
8718     * @hide
8719     */
8720    public boolean isActionableForAccessibility() {
8721        return (isClickable() || isLongClickable() || isFocusable());
8722    }
8723
8724    /**
8725     * Returns whether the View has registered callbacks which makes it
8726     * important for accessibility.
8727     *
8728     * @return True if the view is actionable for accessibility.
8729     */
8730    private boolean hasListenersForAccessibility() {
8731        ListenerInfo info = getListenerInfo();
8732        return mTouchDelegate != null || info.mOnKeyListener != null
8733                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
8734                || info.mOnHoverListener != null || info.mOnDragListener != null;
8735    }
8736
8737    /**
8738     * Notifies that the accessibility state of this view changed. The change
8739     * is local to this view and does not represent structural changes such
8740     * as children and parent. For example, the view became focusable. The
8741     * notification is at at most once every
8742     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8743     * to avoid unnecessary load to the system. Also once a view has a pending
8744     * notification this method is a NOP until the notification has been sent.
8745     *
8746     * @hide
8747     */
8748    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
8749        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
8750            return;
8751        }
8752        if (mSendViewStateChangedAccessibilityEvent == null) {
8753            mSendViewStateChangedAccessibilityEvent =
8754                    new SendViewStateChangedAccessibilityEvent();
8755        }
8756        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
8757    }
8758
8759    /**
8760     * Notifies that the accessibility state of this view changed. The change
8761     * is *not* local to this view and does represent structural changes such
8762     * as children and parent. For example, the view size changed. The
8763     * notification is at at most once every
8764     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8765     * to avoid unnecessary load to the system. Also once a view has a pending
8766     * notification this method is a NOP until the notification has been sent.
8767     *
8768     * @hide
8769     */
8770    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8771        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
8772            return;
8773        }
8774        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8775            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8776            if (mParent != null) {
8777                try {
8778                    mParent.notifySubtreeAccessibilityStateChanged(
8779                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8780                } catch (AbstractMethodError e) {
8781                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8782                            " does not fully implement ViewParent", e);
8783                }
8784            }
8785        }
8786    }
8787
8788    /**
8789     * Reset the flag indicating the accessibility state of the subtree rooted
8790     * at this view changed.
8791     */
8792    void resetSubtreeAccessibilityStateChanged() {
8793        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8794    }
8795
8796    /**
8797     * Report an accessibility action to this view's parents for delegated processing.
8798     *
8799     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8800     * call this method to delegate an accessibility action to a supporting parent. If the parent
8801     * returns true from its
8802     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8803     * method this method will return true to signify that the action was consumed.</p>
8804     *
8805     * <p>This method is useful for implementing nested scrolling child views. If
8806     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8807     * a custom view implementation may invoke this method to allow a parent to consume the
8808     * scroll first. If this method returns true the custom view should skip its own scrolling
8809     * behavior.</p>
8810     *
8811     * @param action Accessibility action to delegate
8812     * @param arguments Optional action arguments
8813     * @return true if the action was consumed by a parent
8814     */
8815    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8816        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8817            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8818                return true;
8819            }
8820        }
8821        return false;
8822    }
8823
8824    /**
8825     * Performs the specified accessibility action on the view. For
8826     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8827     * <p>
8828     * If an {@link AccessibilityDelegate} has been specified via calling
8829     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8830     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8831     * is responsible for handling this call.
8832     * </p>
8833     *
8834     * <p>The default implementation will delegate
8835     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8836     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8837     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8838     *
8839     * @param action The action to perform.
8840     * @param arguments Optional action arguments.
8841     * @return Whether the action was performed.
8842     */
8843    public boolean performAccessibilityAction(int action, Bundle arguments) {
8844      if (mAccessibilityDelegate != null) {
8845          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8846      } else {
8847          return performAccessibilityActionInternal(action, arguments);
8848      }
8849    }
8850
8851   /**
8852    * @see #performAccessibilityAction(int, Bundle)
8853    *
8854    * Note: Called from the default {@link AccessibilityDelegate}.
8855    *
8856    * @hide
8857    */
8858    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8859        if (isNestedScrollingEnabled()
8860                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
8861                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
8862                || action == R.id.accessibilityActionScrollUp
8863                || action == R.id.accessibilityActionScrollLeft
8864                || action == R.id.accessibilityActionScrollDown
8865                || action == R.id.accessibilityActionScrollRight)) {
8866            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
8867                return true;
8868            }
8869        }
8870
8871        switch (action) {
8872            case AccessibilityNodeInfo.ACTION_CLICK: {
8873                if (isClickable()) {
8874                    performClick();
8875                    return true;
8876                }
8877            } break;
8878            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8879                if (isLongClickable()) {
8880                    performLongClick();
8881                    return true;
8882                }
8883            } break;
8884            case AccessibilityNodeInfo.ACTION_FOCUS: {
8885                if (!hasFocus()) {
8886                    // Get out of touch mode since accessibility
8887                    // wants to move focus around.
8888                    getViewRootImpl().ensureTouchMode(false);
8889                    return requestFocus();
8890                }
8891            } break;
8892            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8893                if (hasFocus()) {
8894                    clearFocus();
8895                    return !isFocused();
8896                }
8897            } break;
8898            case AccessibilityNodeInfo.ACTION_SELECT: {
8899                if (!isSelected()) {
8900                    setSelected(true);
8901                    return isSelected();
8902                }
8903            } break;
8904            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8905                if (isSelected()) {
8906                    setSelected(false);
8907                    return !isSelected();
8908                }
8909            } break;
8910            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8911                if (!isAccessibilityFocused()) {
8912                    return requestAccessibilityFocus();
8913                }
8914            } break;
8915            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8916                if (isAccessibilityFocused()) {
8917                    clearAccessibilityFocus();
8918                    return true;
8919                }
8920            } break;
8921            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8922                if (arguments != null) {
8923                    final int granularity = arguments.getInt(
8924                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8925                    final boolean extendSelection = arguments.getBoolean(
8926                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8927                    return traverseAtGranularity(granularity, true, extendSelection);
8928                }
8929            } break;
8930            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8931                if (arguments != null) {
8932                    final int granularity = arguments.getInt(
8933                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8934                    final boolean extendSelection = arguments.getBoolean(
8935                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8936                    return traverseAtGranularity(granularity, false, extendSelection);
8937                }
8938            } break;
8939            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8940                CharSequence text = getIterableTextForAccessibility();
8941                if (text == null) {
8942                    return false;
8943                }
8944                final int start = (arguments != null) ? arguments.getInt(
8945                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8946                final int end = (arguments != null) ? arguments.getInt(
8947                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8948                // Only cursor position can be specified (selection length == 0)
8949                if ((getAccessibilitySelectionStart() != start
8950                        || getAccessibilitySelectionEnd() != end)
8951                        && (start == end)) {
8952                    setAccessibilitySelection(start, end);
8953                    notifyViewAccessibilityStateChangedIfNeeded(
8954                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8955                    return true;
8956                }
8957            } break;
8958            case R.id.accessibilityActionShowOnScreen: {
8959                if (mAttachInfo != null) {
8960                    final Rect r = mAttachInfo.mTmpInvalRect;
8961                    getDrawingRect(r);
8962                    return requestRectangleOnScreen(r, true);
8963                }
8964            } break;
8965            case R.id.accessibilityActionStylusButtonPress: {
8966                if (isStylusButtonPressable()) {
8967                    performStylusButtonPress();
8968                    return true;
8969                }
8970            } break;
8971        }
8972        return false;
8973    }
8974
8975    private boolean traverseAtGranularity(int granularity, boolean forward,
8976            boolean extendSelection) {
8977        CharSequence text = getIterableTextForAccessibility();
8978        if (text == null || text.length() == 0) {
8979            return false;
8980        }
8981        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
8982        if (iterator == null) {
8983            return false;
8984        }
8985        int current = getAccessibilitySelectionEnd();
8986        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8987            current = forward ? 0 : text.length();
8988        }
8989        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
8990        if (range == null) {
8991            return false;
8992        }
8993        final int segmentStart = range[0];
8994        final int segmentEnd = range[1];
8995        int selectionStart;
8996        int selectionEnd;
8997        if (extendSelection && isAccessibilitySelectionExtendable()) {
8998            selectionStart = getAccessibilitySelectionStart();
8999            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9000                selectionStart = forward ? segmentStart : segmentEnd;
9001            }
9002            selectionEnd = forward ? segmentEnd : segmentStart;
9003        } else {
9004            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9005        }
9006        setAccessibilitySelection(selectionStart, selectionEnd);
9007        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9008                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9009        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9010        return true;
9011    }
9012
9013    /**
9014     * Gets the text reported for accessibility purposes.
9015     *
9016     * @return The accessibility text.
9017     *
9018     * @hide
9019     */
9020    public CharSequence getIterableTextForAccessibility() {
9021        return getContentDescription();
9022    }
9023
9024    /**
9025     * Gets whether accessibility selection can be extended.
9026     *
9027     * @return If selection is extensible.
9028     *
9029     * @hide
9030     */
9031    public boolean isAccessibilitySelectionExtendable() {
9032        return false;
9033    }
9034
9035    /**
9036     * @hide
9037     */
9038    public int getAccessibilitySelectionStart() {
9039        return mAccessibilityCursorPosition;
9040    }
9041
9042    /**
9043     * @hide
9044     */
9045    public int getAccessibilitySelectionEnd() {
9046        return getAccessibilitySelectionStart();
9047    }
9048
9049    /**
9050     * @hide
9051     */
9052    public void setAccessibilitySelection(int start, int end) {
9053        if (start ==  end && end == mAccessibilityCursorPosition) {
9054            return;
9055        }
9056        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9057            mAccessibilityCursorPosition = start;
9058        } else {
9059            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9060        }
9061        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9062    }
9063
9064    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9065            int fromIndex, int toIndex) {
9066        if (mParent == null) {
9067            return;
9068        }
9069        AccessibilityEvent event = AccessibilityEvent.obtain(
9070                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9071        onInitializeAccessibilityEvent(event);
9072        onPopulateAccessibilityEvent(event);
9073        event.setFromIndex(fromIndex);
9074        event.setToIndex(toIndex);
9075        event.setAction(action);
9076        event.setMovementGranularity(granularity);
9077        mParent.requestSendAccessibilityEvent(this, event);
9078    }
9079
9080    /**
9081     * @hide
9082     */
9083    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9084        switch (granularity) {
9085            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9086                CharSequence text = getIterableTextForAccessibility();
9087                if (text != null && text.length() > 0) {
9088                    CharacterTextSegmentIterator iterator =
9089                        CharacterTextSegmentIterator.getInstance(
9090                                mContext.getResources().getConfiguration().locale);
9091                    iterator.initialize(text.toString());
9092                    return iterator;
9093                }
9094            } break;
9095            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9096                CharSequence text = getIterableTextForAccessibility();
9097                if (text != null && text.length() > 0) {
9098                    WordTextSegmentIterator iterator =
9099                        WordTextSegmentIterator.getInstance(
9100                                mContext.getResources().getConfiguration().locale);
9101                    iterator.initialize(text.toString());
9102                    return iterator;
9103                }
9104            } break;
9105            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9106                CharSequence text = getIterableTextForAccessibility();
9107                if (text != null && text.length() > 0) {
9108                    ParagraphTextSegmentIterator iterator =
9109                        ParagraphTextSegmentIterator.getInstance();
9110                    iterator.initialize(text.toString());
9111                    return iterator;
9112                }
9113            } break;
9114        }
9115        return null;
9116    }
9117
9118    /**
9119     * @hide
9120     */
9121    public void dispatchStartTemporaryDetach() {
9122        onStartTemporaryDetach();
9123    }
9124
9125    /**
9126     * This is called when a container is going to temporarily detach a child, with
9127     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9128     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9129     * {@link #onDetachedFromWindow()} when the container is done.
9130     */
9131    public void onStartTemporaryDetach() {
9132        removeUnsetPressCallback();
9133        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9134    }
9135
9136    /**
9137     * @hide
9138     */
9139    public void dispatchFinishTemporaryDetach() {
9140        onFinishTemporaryDetach();
9141    }
9142
9143    /**
9144     * Called after {@link #onStartTemporaryDetach} when the container is done
9145     * changing the view.
9146     */
9147    public void onFinishTemporaryDetach() {
9148    }
9149
9150    /**
9151     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9152     * for this view's window.  Returns null if the view is not currently attached
9153     * to the window.  Normally you will not need to use this directly, but
9154     * just use the standard high-level event callbacks like
9155     * {@link #onKeyDown(int, KeyEvent)}.
9156     */
9157    public KeyEvent.DispatcherState getKeyDispatcherState() {
9158        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9159    }
9160
9161    /**
9162     * Dispatch a key event before it is processed by any input method
9163     * associated with the view hierarchy.  This can be used to intercept
9164     * key events in special situations before the IME consumes them; a
9165     * typical example would be handling the BACK key to update the application's
9166     * UI instead of allowing the IME to see it and close itself.
9167     *
9168     * @param event The key event to be dispatched.
9169     * @return True if the event was handled, false otherwise.
9170     */
9171    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9172        return onKeyPreIme(event.getKeyCode(), event);
9173    }
9174
9175    /**
9176     * Dispatch a key event to the next view on the focus path. This path runs
9177     * from the top of the view tree down to the currently focused view. If this
9178     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9179     * the next node down the focus path. This method also fires any key
9180     * listeners.
9181     *
9182     * @param event The key event to be dispatched.
9183     * @return True if the event was handled, false otherwise.
9184     */
9185    public boolean dispatchKeyEvent(KeyEvent event) {
9186        if (mInputEventConsistencyVerifier != null) {
9187            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9188        }
9189
9190        // Give any attached key listener a first crack at the event.
9191        //noinspection SimplifiableIfStatement
9192        ListenerInfo li = mListenerInfo;
9193        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9194                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9195            return true;
9196        }
9197
9198        if (event.dispatch(this, mAttachInfo != null
9199                ? mAttachInfo.mKeyDispatchState : null, this)) {
9200            return true;
9201        }
9202
9203        if (mInputEventConsistencyVerifier != null) {
9204            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9205        }
9206        return false;
9207    }
9208
9209    /**
9210     * Dispatches a key shortcut event.
9211     *
9212     * @param event The key event to be dispatched.
9213     * @return True if the event was handled by the view, false otherwise.
9214     */
9215    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9216        return onKeyShortcut(event.getKeyCode(), event);
9217    }
9218
9219    /**
9220     * Pass the touch screen motion event down to the target view, or this
9221     * view if it is the target.
9222     *
9223     * @param event The motion event to be dispatched.
9224     * @return True if the event was handled by the view, false otherwise.
9225     */
9226    public boolean dispatchTouchEvent(MotionEvent event) {
9227        // If the event should be handled by accessibility focus first.
9228        if (event.isTargetAccessibilityFocus()) {
9229            // We don't have focus or no virtual descendant has it, do not handle the event.
9230            if (!isAccessibilityFocusedViewOrHost()) {
9231                return false;
9232            }
9233            // We have focus and got the event, then use normal event dispatch.
9234            event.setTargetAccessibilityFocus(false);
9235        }
9236
9237        boolean result = false;
9238
9239        if (mInputEventConsistencyVerifier != null) {
9240            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9241        }
9242
9243        final int actionMasked = event.getActionMasked();
9244        if (actionMasked == MotionEvent.ACTION_DOWN) {
9245            // Defensive cleanup for new gesture
9246            stopNestedScroll();
9247        }
9248
9249        if (onFilterTouchEventForSecurity(event)) {
9250            //noinspection SimplifiableIfStatement
9251            ListenerInfo li = mListenerInfo;
9252            if (li != null && li.mOnTouchListener != null
9253                    && (mViewFlags & ENABLED_MASK) == ENABLED
9254                    && li.mOnTouchListener.onTouch(this, event)) {
9255                result = true;
9256            }
9257
9258            if (!result && onTouchEvent(event)) {
9259                result = true;
9260            }
9261        }
9262
9263        if (!result && mInputEventConsistencyVerifier != null) {
9264            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9265        }
9266
9267        // Clean up after nested scrolls if this is the end of a gesture;
9268        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
9269        // of the gesture.
9270        if (actionMasked == MotionEvent.ACTION_UP ||
9271                actionMasked == MotionEvent.ACTION_CANCEL ||
9272                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
9273            stopNestedScroll();
9274        }
9275
9276        return result;
9277    }
9278
9279    boolean isAccessibilityFocusedViewOrHost() {
9280        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
9281                .getAccessibilityFocusedHost() == this);
9282    }
9283
9284    /**
9285     * Filter the touch event to apply security policies.
9286     *
9287     * @param event The motion event to be filtered.
9288     * @return True if the event should be dispatched, false if the event should be dropped.
9289     *
9290     * @see #getFilterTouchesWhenObscured
9291     */
9292    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
9293        //noinspection RedundantIfStatement
9294        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
9295                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
9296            // Window is obscured, drop this touch.
9297            return false;
9298        }
9299        return true;
9300    }
9301
9302    /**
9303     * Pass a trackball motion event down to the focused view.
9304     *
9305     * @param event The motion event to be dispatched.
9306     * @return True if the event was handled by the view, false otherwise.
9307     */
9308    public boolean dispatchTrackballEvent(MotionEvent event) {
9309        if (mInputEventConsistencyVerifier != null) {
9310            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
9311        }
9312
9313        return onTrackballEvent(event);
9314    }
9315
9316    /**
9317     * Dispatch a generic motion event.
9318     * <p>
9319     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9320     * are delivered to the view under the pointer.  All other generic motion events are
9321     * delivered to the focused view.  Hover events are handled specially and are delivered
9322     * to {@link #onHoverEvent(MotionEvent)}.
9323     * </p>
9324     *
9325     * @param event The motion event to be dispatched.
9326     * @return True if the event was handled by the view, false otherwise.
9327     */
9328    public boolean dispatchGenericMotionEvent(MotionEvent event) {
9329        if (mInputEventConsistencyVerifier != null) {
9330            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
9331        }
9332
9333        final int source = event.getSource();
9334        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
9335            final int action = event.getAction();
9336            if (action == MotionEvent.ACTION_HOVER_ENTER
9337                    || action == MotionEvent.ACTION_HOVER_MOVE
9338                    || action == MotionEvent.ACTION_HOVER_EXIT) {
9339                if (dispatchHoverEvent(event)) {
9340                    return true;
9341                }
9342            } else if (dispatchGenericPointerEvent(event)) {
9343                return true;
9344            }
9345        } else if (dispatchGenericFocusedEvent(event)) {
9346            return true;
9347        }
9348
9349        if (dispatchGenericMotionEventInternal(event)) {
9350            return true;
9351        }
9352
9353        if (mInputEventConsistencyVerifier != null) {
9354            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9355        }
9356        return false;
9357    }
9358
9359    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
9360        //noinspection SimplifiableIfStatement
9361        ListenerInfo li = mListenerInfo;
9362        if (li != null && li.mOnGenericMotionListener != null
9363                && (mViewFlags & ENABLED_MASK) == ENABLED
9364                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
9365            return true;
9366        }
9367
9368        if (onGenericMotionEvent(event)) {
9369            return true;
9370        }
9371
9372        if (mInputEventConsistencyVerifier != null) {
9373            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9374        }
9375        return false;
9376    }
9377
9378    /**
9379     * Dispatch a hover event.
9380     * <p>
9381     * Do not call this method directly.
9382     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9383     * </p>
9384     *
9385     * @param event The motion event to be dispatched.
9386     * @return True if the event was handled by the view, false otherwise.
9387     */
9388    protected boolean dispatchHoverEvent(MotionEvent event) {
9389        ListenerInfo li = mListenerInfo;
9390        //noinspection SimplifiableIfStatement
9391        if (li != null && li.mOnHoverListener != null
9392                && (mViewFlags & ENABLED_MASK) == ENABLED
9393                && li.mOnHoverListener.onHover(this, event)) {
9394            return true;
9395        }
9396
9397        return onHoverEvent(event);
9398    }
9399
9400    /**
9401     * Returns true if the view has a child to which it has recently sent
9402     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
9403     * it does not have a hovered child, then it must be the innermost hovered view.
9404     * @hide
9405     */
9406    protected boolean hasHoveredChild() {
9407        return false;
9408    }
9409
9410    /**
9411     * Dispatch a generic motion event to the view under the first pointer.
9412     * <p>
9413     * Do not call this method directly.
9414     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9415     * </p>
9416     *
9417     * @param event The motion event to be dispatched.
9418     * @return True if the event was handled by the view, false otherwise.
9419     */
9420    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
9421        return false;
9422    }
9423
9424    /**
9425     * Dispatch a generic motion event to the currently focused view.
9426     * <p>
9427     * Do not call this method directly.
9428     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9429     * </p>
9430     *
9431     * @param event The motion event to be dispatched.
9432     * @return True if the event was handled by the view, false otherwise.
9433     */
9434    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9435        return false;
9436    }
9437
9438    /**
9439     * Dispatch a pointer event.
9440     * <p>
9441     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9442     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
9443     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9444     * and should not be expected to handle other pointing device features.
9445     * </p>
9446     *
9447     * @param event The motion event to be dispatched.
9448     * @return True if the event was handled by the view, false otherwise.
9449     * @hide
9450     */
9451    public final boolean dispatchPointerEvent(MotionEvent event) {
9452        if (event.isTouchEvent()) {
9453            return dispatchTouchEvent(event);
9454        } else {
9455            return dispatchGenericMotionEvent(event);
9456        }
9457    }
9458
9459    /**
9460     * Called when the window containing this view gains or loses window focus.
9461     * ViewGroups should override to route to their children.
9462     *
9463     * @param hasFocus True if the window containing this view now has focus,
9464     *        false otherwise.
9465     */
9466    public void dispatchWindowFocusChanged(boolean hasFocus) {
9467        onWindowFocusChanged(hasFocus);
9468    }
9469
9470    /**
9471     * Called when the window containing this view gains or loses focus.  Note
9472     * that this is separate from view focus: to receive key events, both
9473     * your view and its window must have focus.  If a window is displayed
9474     * on top of yours that takes input focus, then your own window will lose
9475     * focus but the view focus will remain unchanged.
9476     *
9477     * @param hasWindowFocus True if the window containing this view now has
9478     *        focus, false otherwise.
9479     */
9480    public void onWindowFocusChanged(boolean hasWindowFocus) {
9481        InputMethodManager imm = InputMethodManager.peekInstance();
9482        if (!hasWindowFocus) {
9483            if (isPressed()) {
9484                setPressed(false);
9485            }
9486            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9487                imm.focusOut(this);
9488            }
9489            removeLongPressCallback();
9490            removeTapCallback();
9491            onFocusLost();
9492        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9493            imm.focusIn(this);
9494        }
9495        refreshDrawableState();
9496    }
9497
9498    /**
9499     * Returns true if this view is in a window that currently has window focus.
9500     * Note that this is not the same as the view itself having focus.
9501     *
9502     * @return True if this view is in a window that currently has window focus.
9503     */
9504    public boolean hasWindowFocus() {
9505        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9506    }
9507
9508    /**
9509     * Dispatch a view visibility change down the view hierarchy.
9510     * ViewGroups should override to route to their children.
9511     * @param changedView The view whose visibility changed. Could be 'this' or
9512     * an ancestor view.
9513     * @param visibility The new visibility of changedView: {@link #VISIBLE},
9514     * {@link #INVISIBLE} or {@link #GONE}.
9515     */
9516    protected void dispatchVisibilityChanged(@NonNull View changedView,
9517            @Visibility int visibility) {
9518        onVisibilityChanged(changedView, visibility);
9519    }
9520
9521    /**
9522     * Called when the visibility of the view or an ancestor of the view has
9523     * changed.
9524     *
9525     * @param changedView The view whose visibility changed. May be
9526     *                    {@code this} or an ancestor view.
9527     * @param visibility The new visibility, one of {@link #VISIBLE},
9528     *                   {@link #INVISIBLE} or {@link #GONE}.
9529     */
9530    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9531        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9532        if (visible && mAttachInfo != null) {
9533            initialAwakenScrollBars();
9534        }
9535
9536        final Drawable dr = mBackground;
9537        if (dr != null && visible != dr.isVisible()) {
9538            dr.setVisible(visible, false);
9539        }
9540        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9541        if (fg != null && visible != fg.isVisible()) {
9542            fg.setVisible(visible, false);
9543        }
9544    }
9545
9546    /**
9547     * Dispatch a hint about whether this view is displayed. For instance, when
9548     * a View moves out of the screen, it might receives a display hint indicating
9549     * the view is not displayed. Applications should not <em>rely</em> on this hint
9550     * as there is no guarantee that they will receive one.
9551     *
9552     * @param hint A hint about whether or not this view is displayed:
9553     * {@link #VISIBLE} or {@link #INVISIBLE}.
9554     */
9555    public void dispatchDisplayHint(@Visibility int hint) {
9556        onDisplayHint(hint);
9557    }
9558
9559    /**
9560     * Gives this view a hint about whether is displayed or not. For instance, when
9561     * a View moves out of the screen, it might receives a display hint indicating
9562     * the view is not displayed. Applications should not <em>rely</em> on this hint
9563     * as there is no guarantee that they will receive one.
9564     *
9565     * @param hint A hint about whether or not this view is displayed:
9566     * {@link #VISIBLE} or {@link #INVISIBLE}.
9567     */
9568    protected void onDisplayHint(@Visibility int hint) {
9569    }
9570
9571    /**
9572     * Dispatch a window visibility change down the view hierarchy.
9573     * ViewGroups should override to route to their children.
9574     *
9575     * @param visibility The new visibility of the window.
9576     *
9577     * @see #onWindowVisibilityChanged(int)
9578     */
9579    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9580        onWindowVisibilityChanged(visibility);
9581    }
9582
9583    /**
9584     * Called when the window containing has change its visibility
9585     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9586     * that this tells you whether or not your window is being made visible
9587     * to the window manager; this does <em>not</em> tell you whether or not
9588     * your window is obscured by other windows on the screen, even if it
9589     * is itself visible.
9590     *
9591     * @param visibility The new visibility of the window.
9592     */
9593    protected void onWindowVisibilityChanged(@Visibility int visibility) {
9594        if (visibility == VISIBLE) {
9595            initialAwakenScrollBars();
9596        }
9597    }
9598
9599    /**
9600     * Returns the current visibility of the window this view is attached to
9601     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9602     *
9603     * @return Returns the current visibility of the view's window.
9604     */
9605    @Visibility
9606    public int getWindowVisibility() {
9607        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9608    }
9609
9610    /**
9611     * Retrieve the overall visible display size in which the window this view is
9612     * attached to has been positioned in.  This takes into account screen
9613     * decorations above the window, for both cases where the window itself
9614     * is being position inside of them or the window is being placed under
9615     * then and covered insets are used for the window to position its content
9616     * inside.  In effect, this tells you the available area where content can
9617     * be placed and remain visible to users.
9618     *
9619     * <p>This function requires an IPC back to the window manager to retrieve
9620     * the requested information, so should not be used in performance critical
9621     * code like drawing.
9622     *
9623     * @param outRect Filled in with the visible display frame.  If the view
9624     * is not attached to a window, this is simply the raw display size.
9625     */
9626    public void getWindowVisibleDisplayFrame(Rect outRect) {
9627        if (mAttachInfo != null) {
9628            try {
9629                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9630            } catch (RemoteException e) {
9631                return;
9632            }
9633            // XXX This is really broken, and probably all needs to be done
9634            // in the window manager, and we need to know more about whether
9635            // we want the area behind or in front of the IME.
9636            final Rect insets = mAttachInfo.mVisibleInsets;
9637            outRect.left += insets.left;
9638            outRect.top += insets.top;
9639            outRect.right -= insets.right;
9640            outRect.bottom -= insets.bottom;
9641            return;
9642        }
9643        // The view is not attached to a display so we don't have a context.
9644        // Make a best guess about the display size.
9645        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9646        d.getRectSize(outRect);
9647    }
9648
9649    /**
9650     * Dispatch a notification about a resource configuration change down
9651     * the view hierarchy.
9652     * ViewGroups should override to route to their children.
9653     *
9654     * @param newConfig The new resource configuration.
9655     *
9656     * @see #onConfigurationChanged(android.content.res.Configuration)
9657     */
9658    public void dispatchConfigurationChanged(Configuration newConfig) {
9659        onConfigurationChanged(newConfig);
9660    }
9661
9662    /**
9663     * Called when the current configuration of the resources being used
9664     * by the application have changed.  You can use this to decide when
9665     * to reload resources that can changed based on orientation and other
9666     * configuration characteristics.  You only need to use this if you are
9667     * not relying on the normal {@link android.app.Activity} mechanism of
9668     * recreating the activity instance upon a configuration change.
9669     *
9670     * @param newConfig The new resource configuration.
9671     */
9672    protected void onConfigurationChanged(Configuration newConfig) {
9673    }
9674
9675    /**
9676     * Private function to aggregate all per-view attributes in to the view
9677     * root.
9678     */
9679    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9680        performCollectViewAttributes(attachInfo, visibility);
9681    }
9682
9683    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9684        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
9685            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
9686                attachInfo.mKeepScreenOn = true;
9687            }
9688            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
9689            ListenerInfo li = mListenerInfo;
9690            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
9691                attachInfo.mHasSystemUiListeners = true;
9692            }
9693        }
9694    }
9695
9696    void needGlobalAttributesUpdate(boolean force) {
9697        final AttachInfo ai = mAttachInfo;
9698        if (ai != null && !ai.mRecomputeGlobalAttributes) {
9699            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
9700                    || ai.mHasSystemUiListeners) {
9701                ai.mRecomputeGlobalAttributes = true;
9702            }
9703        }
9704    }
9705
9706    /**
9707     * Returns whether the device is currently in touch mode.  Touch mode is entered
9708     * once the user begins interacting with the device by touch, and affects various
9709     * things like whether focus is always visible to the user.
9710     *
9711     * @return Whether the device is in touch mode.
9712     */
9713    @ViewDebug.ExportedProperty
9714    public boolean isInTouchMode() {
9715        if (mAttachInfo != null) {
9716            return mAttachInfo.mInTouchMode;
9717        } else {
9718            return ViewRootImpl.isInTouchMode();
9719        }
9720    }
9721
9722    /**
9723     * Returns the context the view is running in, through which it can
9724     * access the current theme, resources, etc.
9725     *
9726     * @return The view's Context.
9727     */
9728    @ViewDebug.CapturedViewProperty
9729    public final Context getContext() {
9730        return mContext;
9731    }
9732
9733    /**
9734     * Handle a key event before it is processed by any input method
9735     * associated with the view hierarchy.  This can be used to intercept
9736     * key events in special situations before the IME consumes them; a
9737     * typical example would be handling the BACK key to update the application's
9738     * UI instead of allowing the IME to see it and close itself.
9739     *
9740     * @param keyCode The value in event.getKeyCode().
9741     * @param event Description of the key event.
9742     * @return If you handled the event, return true. If you want to allow the
9743     *         event to be handled by the next receiver, return false.
9744     */
9745    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
9746        return false;
9747    }
9748
9749    /**
9750     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
9751     * KeyEvent.Callback.onKeyDown()}: perform press of the view
9752     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
9753     * is released, if the view is enabled and clickable.
9754     *
9755     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9756     * although some may elect to do so in some situations. Do not rely on this to
9757     * catch software key presses.
9758     *
9759     * @param keyCode A key code that represents the button pressed, from
9760     *                {@link android.view.KeyEvent}.
9761     * @param event   The KeyEvent object that defines the button action.
9762     */
9763    public boolean onKeyDown(int keyCode, KeyEvent event) {
9764        boolean result = false;
9765
9766        if (KeyEvent.isConfirmKey(keyCode)) {
9767            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9768                return true;
9769            }
9770            // Long clickable items don't necessarily have to be clickable
9771            if (((mViewFlags & CLICKABLE) == CLICKABLE ||
9772                    (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
9773                    (event.getRepeatCount() == 0)) {
9774                setPressed(true);
9775                checkForLongClick(0);
9776                return true;
9777            }
9778        }
9779        return result;
9780    }
9781
9782    /**
9783     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
9784     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
9785     * the event).
9786     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9787     * although some may elect to do so in some situations. Do not rely on this to
9788     * catch software key presses.
9789     */
9790    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
9791        return false;
9792    }
9793
9794    /**
9795     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9796     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9797     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9798     * {@link KeyEvent#KEYCODE_ENTER} is released.
9799     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9800     * although some may elect to do so in some situations. Do not rely on this to
9801     * catch software key presses.
9802     *
9803     * @param keyCode A key code that represents the button pressed, from
9804     *                {@link android.view.KeyEvent}.
9805     * @param event   The KeyEvent object that defines the button action.
9806     */
9807    public boolean onKeyUp(int keyCode, KeyEvent event) {
9808        if (KeyEvent.isConfirmKey(keyCode)) {
9809            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9810                return true;
9811            }
9812            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9813                setPressed(false);
9814
9815                if (!mHasPerformedLongPress) {
9816                    // This is a tap, so remove the longpress check
9817                    removeLongPressCallback();
9818                    return performClick();
9819                }
9820            }
9821        }
9822        return false;
9823    }
9824
9825    /**
9826     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
9827     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
9828     * the event).
9829     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9830     * although some may elect to do so in some situations. Do not rely on this to
9831     * catch software key presses.
9832     *
9833     * @param keyCode     A key code that represents the button pressed, from
9834     *                    {@link android.view.KeyEvent}.
9835     * @param repeatCount The number of times the action was made.
9836     * @param event       The KeyEvent object that defines the button action.
9837     */
9838    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
9839        return false;
9840    }
9841
9842    /**
9843     * Called on the focused view when a key shortcut event is not handled.
9844     * Override this method to implement local key shortcuts for the View.
9845     * Key shortcuts can also be implemented by setting the
9846     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
9847     *
9848     * @param keyCode The value in event.getKeyCode().
9849     * @param event Description of the key event.
9850     * @return If you handled the event, return true. If you want to allow the
9851     *         event to be handled by the next receiver, return false.
9852     */
9853    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
9854        return false;
9855    }
9856
9857    /**
9858     * Check whether the called view is a text editor, in which case it
9859     * would make sense to automatically display a soft input window for
9860     * it.  Subclasses should override this if they implement
9861     * {@link #onCreateInputConnection(EditorInfo)} to return true if
9862     * a call on that method would return a non-null InputConnection, and
9863     * they are really a first-class editor that the user would normally
9864     * start typing on when the go into a window containing your view.
9865     *
9866     * <p>The default implementation always returns false.  This does
9867     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
9868     * will not be called or the user can not otherwise perform edits on your
9869     * view; it is just a hint to the system that this is not the primary
9870     * purpose of this view.
9871     *
9872     * @return Returns true if this view is a text editor, else false.
9873     */
9874    public boolean onCheckIsTextEditor() {
9875        return false;
9876    }
9877
9878    /**
9879     * Create a new InputConnection for an InputMethod to interact
9880     * with the view.  The default implementation returns null, since it doesn't
9881     * support input methods.  You can override this to implement such support.
9882     * This is only needed for views that take focus and text input.
9883     *
9884     * <p>When implementing this, you probably also want to implement
9885     * {@link #onCheckIsTextEditor()} to indicate you will return a
9886     * non-null InputConnection.</p>
9887     *
9888     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9889     * object correctly and in its entirety, so that the connected IME can rely
9890     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9891     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9892     * must be filled in with the correct cursor position for IMEs to work correctly
9893     * with your application.</p>
9894     *
9895     * @param outAttrs Fill in with attribute information about the connection.
9896     */
9897    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9898        return null;
9899    }
9900
9901    /**
9902     * Called by the {@link android.view.inputmethod.InputMethodManager}
9903     * when a view who is not the current
9904     * input connection target is trying to make a call on the manager.  The
9905     * default implementation returns false; you can override this to return
9906     * true for certain views if you are performing InputConnection proxying
9907     * to them.
9908     * @param view The View that is making the InputMethodManager call.
9909     * @return Return true to allow the call, false to reject.
9910     */
9911    public boolean checkInputConnectionProxy(View view) {
9912        return false;
9913    }
9914
9915    /**
9916     * Show the context menu for this view. It is not safe to hold on to the
9917     * menu after returning from this method.
9918     *
9919     * You should normally not overload this method. Overload
9920     * {@link #onCreateContextMenu(ContextMenu)} or define an
9921     * {@link OnCreateContextMenuListener} to add items to the context menu.
9922     *
9923     * @param menu The context menu to populate
9924     */
9925    public void createContextMenu(ContextMenu menu) {
9926        ContextMenuInfo menuInfo = getContextMenuInfo();
9927
9928        // Sets the current menu info so all items added to menu will have
9929        // my extra info set.
9930        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
9931
9932        onCreateContextMenu(menu);
9933        ListenerInfo li = mListenerInfo;
9934        if (li != null && li.mOnCreateContextMenuListener != null) {
9935            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
9936        }
9937
9938        // Clear the extra information so subsequent items that aren't mine don't
9939        // have my extra info.
9940        ((MenuBuilder)menu).setCurrentMenuInfo(null);
9941
9942        if (mParent != null) {
9943            mParent.createContextMenu(menu);
9944        }
9945    }
9946
9947    /**
9948     * Views should implement this if they have extra information to associate
9949     * with the context menu. The return result is supplied as a parameter to
9950     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
9951     * callback.
9952     *
9953     * @return Extra information about the item for which the context menu
9954     *         should be shown. This information will vary across different
9955     *         subclasses of View.
9956     */
9957    protected ContextMenuInfo getContextMenuInfo() {
9958        return null;
9959    }
9960
9961    /**
9962     * Views should implement this if the view itself is going to add items to
9963     * the context menu.
9964     *
9965     * @param menu the context menu to populate
9966     */
9967    protected void onCreateContextMenu(ContextMenu menu) {
9968    }
9969
9970    /**
9971     * Implement this method to handle trackball motion events.  The
9972     * <em>relative</em> movement of the trackball since the last event
9973     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
9974     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
9975     * that a movement of 1 corresponds to the user pressing one DPAD key (so
9976     * they will often be fractional values, representing the more fine-grained
9977     * movement information available from a trackball).
9978     *
9979     * @param event The motion event.
9980     * @return True if the event was handled, false otherwise.
9981     */
9982    public boolean onTrackballEvent(MotionEvent event) {
9983        return false;
9984    }
9985
9986    /**
9987     * Implement this method to handle generic motion events.
9988     * <p>
9989     * Generic motion events describe joystick movements, mouse hovers, track pad
9990     * touches, scroll wheel movements and other input events.  The
9991     * {@link MotionEvent#getSource() source} of the motion event specifies
9992     * the class of input that was received.  Implementations of this method
9993     * must examine the bits in the source before processing the event.
9994     * The following code example shows how this is done.
9995     * </p><p>
9996     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9997     * are delivered to the view under the pointer.  All other generic motion events are
9998     * delivered to the focused view.
9999     * </p>
10000     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10001     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10002     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10003     *             // process the joystick movement...
10004     *             return true;
10005     *         }
10006     *     }
10007     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10008     *         switch (event.getAction()) {
10009     *             case MotionEvent.ACTION_HOVER_MOVE:
10010     *                 // process the mouse hover movement...
10011     *                 return true;
10012     *             case MotionEvent.ACTION_SCROLL:
10013     *                 // process the scroll wheel movement...
10014     *                 return true;
10015     *         }
10016     *     }
10017     *     return super.onGenericMotionEvent(event);
10018     * }</pre>
10019     *
10020     * @param event The generic motion event being processed.
10021     * @return True if the event was handled, false otherwise.
10022     */
10023    public boolean onGenericMotionEvent(MotionEvent event) {
10024        return false;
10025    }
10026
10027    /**
10028     * Implement this method to handle hover events.
10029     * <p>
10030     * This method is called whenever a pointer is hovering into, over, or out of the
10031     * bounds of a view and the view is not currently being touched.
10032     * Hover events are represented as pointer events with action
10033     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10034     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10035     * </p>
10036     * <ul>
10037     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10038     * when the pointer enters the bounds of the view.</li>
10039     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10040     * when the pointer has already entered the bounds of the view and has moved.</li>
10041     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10042     * when the pointer has exited the bounds of the view or when the pointer is
10043     * about to go down due to a button click, tap, or similar user action that
10044     * causes the view to be touched.</li>
10045     * </ul>
10046     * <p>
10047     * The view should implement this method to return true to indicate that it is
10048     * handling the hover event, such as by changing its drawable state.
10049     * </p><p>
10050     * The default implementation calls {@link #setHovered} to update the hovered state
10051     * of the view when a hover enter or hover exit event is received, if the view
10052     * is enabled and is clickable.  The default implementation also sends hover
10053     * accessibility events.
10054     * </p>
10055     *
10056     * @param event The motion event that describes the hover.
10057     * @return True if the view handled the hover event.
10058     *
10059     * @see #isHovered
10060     * @see #setHovered
10061     * @see #onHoverChanged
10062     */
10063    public boolean onHoverEvent(MotionEvent event) {
10064        // The root view may receive hover (or touch) events that are outside the bounds of
10065        // the window.  This code ensures that we only send accessibility events for
10066        // hovers that are actually within the bounds of the root view.
10067        final int action = event.getActionMasked();
10068        if (!mSendingHoverAccessibilityEvents) {
10069            if ((action == MotionEvent.ACTION_HOVER_ENTER
10070                    || action == MotionEvent.ACTION_HOVER_MOVE)
10071                    && !hasHoveredChild()
10072                    && pointInView(event.getX(), event.getY())) {
10073                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10074                mSendingHoverAccessibilityEvents = true;
10075            }
10076        } else {
10077            if (action == MotionEvent.ACTION_HOVER_EXIT
10078                    || (action == MotionEvent.ACTION_MOVE
10079                            && !pointInView(event.getX(), event.getY()))) {
10080                mSendingHoverAccessibilityEvents = false;
10081                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10082            }
10083        }
10084
10085        if (isHoverable()) {
10086            switch (action) {
10087                case MotionEvent.ACTION_HOVER_ENTER:
10088                    setHovered(true);
10089                    break;
10090                case MotionEvent.ACTION_HOVER_EXIT:
10091                    setHovered(false);
10092                    break;
10093            }
10094
10095            // Dispatch the event to onGenericMotionEvent before returning true.
10096            // This is to provide compatibility with existing applications that
10097            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10098            // break because of the new default handling for hoverable views
10099            // in onHoverEvent.
10100            // Note that onGenericMotionEvent will be called by default when
10101            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10102            dispatchGenericMotionEventInternal(event);
10103            // The event was already handled by calling setHovered(), so always
10104            // return true.
10105            return true;
10106        }
10107
10108        return false;
10109    }
10110
10111    /**
10112     * Returns true if the view should handle {@link #onHoverEvent}
10113     * by calling {@link #setHovered} to change its hovered state.
10114     *
10115     * @return True if the view is hoverable.
10116     */
10117    private boolean isHoverable() {
10118        final int viewFlags = mViewFlags;
10119        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10120            return false;
10121        }
10122
10123        return (viewFlags & CLICKABLE) == CLICKABLE
10124                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10125                || (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE;
10126    }
10127
10128    /**
10129     * Returns true if the view is currently hovered.
10130     *
10131     * @return True if the view is currently hovered.
10132     *
10133     * @see #setHovered
10134     * @see #onHoverChanged
10135     */
10136    @ViewDebug.ExportedProperty
10137    public boolean isHovered() {
10138        return (mPrivateFlags & PFLAG_HOVERED) != 0;
10139    }
10140
10141    /**
10142     * Sets whether the view is currently hovered.
10143     * <p>
10144     * Calling this method also changes the drawable state of the view.  This
10145     * enables the view to react to hover by using different drawable resources
10146     * to change its appearance.
10147     * </p><p>
10148     * The {@link #onHoverChanged} method is called when the hovered state changes.
10149     * </p>
10150     *
10151     * @param hovered True if the view is hovered.
10152     *
10153     * @see #isHovered
10154     * @see #onHoverChanged
10155     */
10156    public void setHovered(boolean hovered) {
10157        if (hovered) {
10158            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10159                mPrivateFlags |= PFLAG_HOVERED;
10160                refreshDrawableState();
10161                onHoverChanged(true);
10162            }
10163        } else {
10164            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10165                mPrivateFlags &= ~PFLAG_HOVERED;
10166                refreshDrawableState();
10167                onHoverChanged(false);
10168            }
10169        }
10170    }
10171
10172    /**
10173     * Implement this method to handle hover state changes.
10174     * <p>
10175     * This method is called whenever the hover state changes as a result of a
10176     * call to {@link #setHovered}.
10177     * </p>
10178     *
10179     * @param hovered The current hover state, as returned by {@link #isHovered}.
10180     *
10181     * @see #isHovered
10182     * @see #setHovered
10183     */
10184    public void onHoverChanged(boolean hovered) {
10185    }
10186
10187    /**
10188     * Implement this method to handle touch screen motion events.
10189     * <p>
10190     * If this method is used to detect click actions, it is recommended that
10191     * the actions be performed by implementing and calling
10192     * {@link #performClick()}. This will ensure consistent system behavior,
10193     * including:
10194     * <ul>
10195     * <li>obeying click sound preferences
10196     * <li>dispatching OnClickListener calls
10197     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
10198     * accessibility features are enabled
10199     * </ul>
10200     *
10201     * @param event The motion event.
10202     * @return True if the event was handled, false otherwise.
10203     */
10204    public boolean onTouchEvent(MotionEvent event) {
10205        final float x = event.getX();
10206        final float y = event.getY();
10207        final int viewFlags = mViewFlags;
10208        final int action = event.getAction();
10209
10210        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10211            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
10212                setPressed(false);
10213            }
10214            // A disabled view that is clickable still consumes the touch
10215            // events, it just doesn't respond to them.
10216            return (((viewFlags & CLICKABLE) == CLICKABLE
10217                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10218                    || (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE);
10219        }
10220
10221        if (mTouchDelegate != null) {
10222            if (mTouchDelegate.onTouchEvent(event)) {
10223                return true;
10224            }
10225        }
10226
10227        if (((viewFlags & CLICKABLE) == CLICKABLE ||
10228                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
10229                (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE) {
10230            switch (action) {
10231                case MotionEvent.ACTION_UP:
10232                    if (mInStylusButtonPress) {
10233                        mInStylusButtonPress = false;
10234                        mHasPerformedLongPress = false;
10235                    }
10236                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
10237                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
10238                        // take focus if we don't have it already and we should in
10239                        // touch mode.
10240                        boolean focusTaken = false;
10241                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
10242                            focusTaken = requestFocus();
10243                        }
10244
10245                        if (prepressed) {
10246                            // The button is being released before we actually
10247                            // showed it as pressed.  Make it show the pressed
10248                            // state now (before scheduling the click) to ensure
10249                            // the user sees it.
10250                            setPressed(true, x, y);
10251                       }
10252
10253                        if (!mHasPerformedLongPress) {
10254                            // This is a tap, so remove the longpress check
10255                            removeLongPressCallback();
10256
10257                            // Only perform take click actions if we were in the pressed state
10258                            if (!focusTaken) {
10259                                // Use a Runnable and post this rather than calling
10260                                // performClick directly. This lets other visual state
10261                                // of the view update before click actions start.
10262                                if (mPerformClick == null) {
10263                                    mPerformClick = new PerformClick();
10264                                }
10265                                if (!post(mPerformClick)) {
10266                                    performClick();
10267                                }
10268                            }
10269                        }
10270
10271                        if (mUnsetPressedState == null) {
10272                            mUnsetPressedState = new UnsetPressedState();
10273                        }
10274
10275                        if (prepressed) {
10276                            postDelayed(mUnsetPressedState,
10277                                    ViewConfiguration.getPressedStateDuration());
10278                        } else if (!post(mUnsetPressedState)) {
10279                            // If the post failed, unpress right now
10280                            mUnsetPressedState.run();
10281                        }
10282
10283                        removeTapCallback();
10284                    }
10285                    break;
10286
10287                case MotionEvent.ACTION_DOWN:
10288                    mHasPerformedLongPress = false;
10289                    mInStylusButtonPress = false;
10290
10291                    if (performStylusActionOnButtonPress(event)) {
10292                        break;
10293                    }
10294
10295                    if (performButtonActionOnTouchDown(event)) {
10296                        break;
10297                    }
10298
10299                    // Walk up the hierarchy to determine if we're inside a scrolling container.
10300                    boolean isInScrollingContainer = isInScrollingContainer();
10301
10302                    // For views inside a scrolling container, delay the pressed feedback for
10303                    // a short period in case this is a scroll.
10304                    if (isInScrollingContainer) {
10305                        mPrivateFlags |= PFLAG_PREPRESSED;
10306                        if (mPendingCheckForTap == null) {
10307                            mPendingCheckForTap = new CheckForTap();
10308                        }
10309                        mPendingCheckForTap.x = event.getX();
10310                        mPendingCheckForTap.y = event.getY();
10311                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
10312                    } else {
10313                        // Not inside a scrolling container, so show the feedback right away
10314                        setPressed(true, x, y);
10315                        checkForLongClick(0);
10316                    }
10317                    break;
10318
10319                case MotionEvent.ACTION_CANCEL:
10320                    setPressed(false);
10321                    removeTapCallback();
10322                    removeLongPressCallback();
10323                    if (mInStylusButtonPress) {
10324                        mInStylusButtonPress = false;
10325                        mHasPerformedLongPress = false;
10326                    }
10327                    break;
10328
10329                case MotionEvent.ACTION_MOVE:
10330                    drawableHotspotChanged(x, y);
10331
10332                    // Be lenient about moving outside of buttons
10333                    if (!pointInView(x, y, mTouchSlop)) {
10334                        // Outside button
10335                        removeTapCallback();
10336                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
10337                            // Remove any future long press/tap checks
10338                            removeLongPressCallback();
10339
10340                            setPressed(false);
10341                        }
10342                    } else if (performStylusActionOnButtonPress(event)) {
10343                        // Check for stylus button press if we're within the view.
10344                        break;
10345                    }
10346                    break;
10347            }
10348
10349            return true;
10350        }
10351
10352        return false;
10353    }
10354
10355    /**
10356     * @hide
10357     */
10358    public boolean isInScrollingContainer() {
10359        ViewParent p = getParent();
10360        while (p != null && p instanceof ViewGroup) {
10361            if (((ViewGroup) p).shouldDelayChildPressedState()) {
10362                return true;
10363            }
10364            p = p.getParent();
10365        }
10366        return false;
10367    }
10368
10369    /**
10370     * Remove the longpress detection timer.
10371     */
10372    private void removeLongPressCallback() {
10373        if (mPendingCheckForLongPress != null) {
10374          removeCallbacks(mPendingCheckForLongPress);
10375        }
10376    }
10377
10378    /**
10379     * Remove the pending click action
10380     */
10381    private void removePerformClickCallback() {
10382        if (mPerformClick != null) {
10383            removeCallbacks(mPerformClick);
10384        }
10385    }
10386
10387    /**
10388     * Remove the prepress detection timer.
10389     */
10390    private void removeUnsetPressCallback() {
10391        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
10392            setPressed(false);
10393            removeCallbacks(mUnsetPressedState);
10394        }
10395    }
10396
10397    /**
10398     * Remove the tap detection timer.
10399     */
10400    private void removeTapCallback() {
10401        if (mPendingCheckForTap != null) {
10402            mPrivateFlags &= ~PFLAG_PREPRESSED;
10403            removeCallbacks(mPendingCheckForTap);
10404        }
10405    }
10406
10407    /**
10408     * Cancels a pending long press.  Your subclass can use this if you
10409     * want the context menu to come up if the user presses and holds
10410     * at the same place, but you don't want it to come up if they press
10411     * and then move around enough to cause scrolling.
10412     */
10413    public void cancelLongPress() {
10414        removeLongPressCallback();
10415
10416        /*
10417         * The prepressed state handled by the tap callback is a display
10418         * construct, but the tap callback will post a long press callback
10419         * less its own timeout. Remove it here.
10420         */
10421        removeTapCallback();
10422    }
10423
10424    /**
10425     * Remove the pending callback for sending a
10426     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
10427     */
10428    private void removeSendViewScrolledAccessibilityEventCallback() {
10429        if (mSendViewScrolledAccessibilityEvent != null) {
10430            removeCallbacks(mSendViewScrolledAccessibilityEvent);
10431            mSendViewScrolledAccessibilityEvent.mIsPending = false;
10432        }
10433    }
10434
10435    /**
10436     * Sets the TouchDelegate for this View.
10437     */
10438    public void setTouchDelegate(TouchDelegate delegate) {
10439        mTouchDelegate = delegate;
10440    }
10441
10442    /**
10443     * Gets the TouchDelegate for this View.
10444     */
10445    public TouchDelegate getTouchDelegate() {
10446        return mTouchDelegate;
10447    }
10448
10449    /**
10450     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10451     *
10452     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10453     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10454     * available. This method should only be called for touch events.
10455     *
10456     * <p class="note">This api is not intended for most applications. Buffered dispatch
10457     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10458     * streams will not improve your input latency. Side effects include: increased latency,
10459     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10460     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10461     * you.</p>
10462     */
10463    public final void requestUnbufferedDispatch(MotionEvent event) {
10464        final int action = event.getAction();
10465        if (mAttachInfo == null
10466                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10467                || !event.isTouchEvent()) {
10468            return;
10469        }
10470        mAttachInfo.mUnbufferedDispatchRequested = true;
10471    }
10472
10473    /**
10474     * Set flags controlling behavior of this view.
10475     *
10476     * @param flags Constant indicating the value which should be set
10477     * @param mask Constant indicating the bit range that should be changed
10478     */
10479    void setFlags(int flags, int mask) {
10480        final boolean accessibilityEnabled =
10481                AccessibilityManager.getInstance(mContext).isEnabled();
10482        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10483
10484        int old = mViewFlags;
10485        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10486
10487        int changed = mViewFlags ^ old;
10488        if (changed == 0) {
10489            return;
10490        }
10491        int privateFlags = mPrivateFlags;
10492
10493        /* Check if the FOCUSABLE bit has changed */
10494        if (((changed & FOCUSABLE_MASK) != 0) &&
10495                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10496            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10497                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10498                /* Give up focus if we are no longer focusable */
10499                clearFocus();
10500            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10501                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10502                /*
10503                 * Tell the view system that we are now available to take focus
10504                 * if no one else already has it.
10505                 */
10506                if (mParent != null) mParent.focusableViewAvailable(this);
10507            }
10508        }
10509
10510        final int newVisibility = flags & VISIBILITY_MASK;
10511        if (newVisibility == VISIBLE) {
10512            if ((changed & VISIBILITY_MASK) != 0) {
10513                /*
10514                 * If this view is becoming visible, invalidate it in case it changed while
10515                 * it was not visible. Marking it drawn ensures that the invalidation will
10516                 * go through.
10517                 */
10518                mPrivateFlags |= PFLAG_DRAWN;
10519                invalidate(true);
10520
10521                needGlobalAttributesUpdate(true);
10522
10523                // a view becoming visible is worth notifying the parent
10524                // about in case nothing has focus.  even if this specific view
10525                // isn't focusable, it may contain something that is, so let
10526                // the root view try to give this focus if nothing else does.
10527                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10528                    mParent.focusableViewAvailable(this);
10529                }
10530            }
10531        }
10532
10533        /* Check if the GONE bit has changed */
10534        if ((changed & GONE) != 0) {
10535            needGlobalAttributesUpdate(false);
10536            requestLayout();
10537
10538            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10539                if (hasFocus()) clearFocus();
10540                clearAccessibilityFocus();
10541                destroyDrawingCache();
10542                if (mParent instanceof View) {
10543                    // GONE views noop invalidation, so invalidate the parent
10544                    ((View) mParent).invalidate(true);
10545                }
10546                // Mark the view drawn to ensure that it gets invalidated properly the next
10547                // time it is visible and gets invalidated
10548                mPrivateFlags |= PFLAG_DRAWN;
10549            }
10550            if (mAttachInfo != null) {
10551                mAttachInfo.mViewVisibilityChanged = true;
10552            }
10553        }
10554
10555        /* Check if the VISIBLE bit has changed */
10556        if ((changed & INVISIBLE) != 0) {
10557            needGlobalAttributesUpdate(false);
10558            /*
10559             * If this view is becoming invisible, set the DRAWN flag so that
10560             * the next invalidate() will not be skipped.
10561             */
10562            mPrivateFlags |= PFLAG_DRAWN;
10563
10564            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10565                // root view becoming invisible shouldn't clear focus and accessibility focus
10566                if (getRootView() != this) {
10567                    if (hasFocus()) clearFocus();
10568                    clearAccessibilityFocus();
10569                }
10570            }
10571            if (mAttachInfo != null) {
10572                mAttachInfo.mViewVisibilityChanged = true;
10573            }
10574        }
10575
10576        if ((changed & VISIBILITY_MASK) != 0) {
10577            // If the view is invisible, cleanup its display list to free up resources
10578            if (newVisibility != VISIBLE && mAttachInfo != null) {
10579                cleanupDraw();
10580            }
10581
10582            if (mParent instanceof ViewGroup) {
10583                ((ViewGroup) mParent).onChildVisibilityChanged(this,
10584                        (changed & VISIBILITY_MASK), newVisibility);
10585                ((View) mParent).invalidate(true);
10586            } else if (mParent != null) {
10587                mParent.invalidateChild(this, null);
10588            }
10589
10590            if (mAttachInfo != null) {
10591                dispatchVisibilityChanged(this, newVisibility);
10592                notifySubtreeAccessibilityStateChangedIfNeeded();
10593            }
10594        }
10595
10596        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10597            destroyDrawingCache();
10598        }
10599
10600        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10601            destroyDrawingCache();
10602            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10603            invalidateParentCaches();
10604        }
10605
10606        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10607            destroyDrawingCache();
10608            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10609        }
10610
10611        if ((changed & DRAW_MASK) != 0) {
10612            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10613                if (mBackground != null
10614                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
10615                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10616                } else {
10617                    mPrivateFlags |= PFLAG_SKIP_DRAW;
10618                }
10619            } else {
10620                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10621            }
10622            requestLayout();
10623            invalidate(true);
10624        }
10625
10626        if ((changed & KEEP_SCREEN_ON) != 0) {
10627            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10628                mParent.recomputeViewAttributes(this);
10629            }
10630        }
10631
10632        if (accessibilityEnabled) {
10633            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10634                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
10635                    || (changed & STYLUS_BUTTON_PRESSABLE) != 0) {
10636                if (oldIncludeForAccessibility != includeForAccessibility()) {
10637                    notifySubtreeAccessibilityStateChangedIfNeeded();
10638                } else {
10639                    notifyViewAccessibilityStateChangedIfNeeded(
10640                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10641                }
10642            } else if ((changed & ENABLED_MASK) != 0) {
10643                notifyViewAccessibilityStateChangedIfNeeded(
10644                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10645            }
10646        }
10647    }
10648
10649    /**
10650     * Change the view's z order in the tree, so it's on top of other sibling
10651     * views. This ordering change may affect layout, if the parent container
10652     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10653     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10654     * method should be followed by calls to {@link #requestLayout()} and
10655     * {@link View#invalidate()} on the view's parent to force the parent to redraw
10656     * with the new child ordering.
10657     *
10658     * @see ViewGroup#bringChildToFront(View)
10659     */
10660    public void bringToFront() {
10661        if (mParent != null) {
10662            mParent.bringChildToFront(this);
10663        }
10664    }
10665
10666    /**
10667     * This is called in response to an internal scroll in this view (i.e., the
10668     * view scrolled its own contents). This is typically as a result of
10669     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10670     * called.
10671     *
10672     * @param l Current horizontal scroll origin.
10673     * @param t Current vertical scroll origin.
10674     * @param oldl Previous horizontal scroll origin.
10675     * @param oldt Previous vertical scroll origin.
10676     */
10677    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10678        notifySubtreeAccessibilityStateChangedIfNeeded();
10679
10680        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10681            postSendViewScrolledAccessibilityEventCallback();
10682        }
10683
10684        mBackgroundSizeChanged = true;
10685        if (mForegroundInfo != null) {
10686            mForegroundInfo.mBoundsChanged = true;
10687        }
10688
10689        final AttachInfo ai = mAttachInfo;
10690        if (ai != null) {
10691            ai.mViewScrollChanged = true;
10692        }
10693
10694        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
10695            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
10696        }
10697    }
10698
10699    /**
10700     * Interface definition for a callback to be invoked when the scroll
10701     * X or Y positions of a view change.
10702     * <p>
10703     * <b>Note:</b> Some views handle scrolling independently from View and may
10704     * have their own separate listeners for scroll-type events. For example,
10705     * {@link android.widget.ListView ListView} allows clients to register an
10706     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
10707     * to listen for changes in list scroll position.
10708     *
10709     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
10710     */
10711    public interface OnScrollChangeListener {
10712        /**
10713         * Called when the scroll position of a view changes.
10714         *
10715         * @param v The view whose scroll position has changed.
10716         * @param scrollX Current horizontal scroll origin.
10717         * @param scrollY Current vertical scroll origin.
10718         * @param oldScrollX Previous horizontal scroll origin.
10719         * @param oldScrollY Previous vertical scroll origin.
10720         */
10721        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
10722    }
10723
10724    /**
10725     * Interface definition for a callback to be invoked when the layout bounds of a view
10726     * changes due to layout processing.
10727     */
10728    public interface OnLayoutChangeListener {
10729        /**
10730         * Called when the layout bounds of a view changes due to layout processing.
10731         *
10732         * @param v The view whose bounds have changed.
10733         * @param left The new value of the view's left property.
10734         * @param top The new value of the view's top property.
10735         * @param right The new value of the view's right property.
10736         * @param bottom The new value of the view's bottom property.
10737         * @param oldLeft The previous value of the view's left property.
10738         * @param oldTop The previous value of the view's top property.
10739         * @param oldRight The previous value of the view's right property.
10740         * @param oldBottom The previous value of the view's bottom property.
10741         */
10742        void onLayoutChange(View v, int left, int top, int right, int bottom,
10743            int oldLeft, int oldTop, int oldRight, int oldBottom);
10744    }
10745
10746    /**
10747     * This is called during layout when the size of this view has changed. If
10748     * you were just added to the view hierarchy, you're called with the old
10749     * values of 0.
10750     *
10751     * @param w Current width of this view.
10752     * @param h Current height of this view.
10753     * @param oldw Old width of this view.
10754     * @param oldh Old height of this view.
10755     */
10756    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
10757    }
10758
10759    /**
10760     * Called by draw to draw the child views. This may be overridden
10761     * by derived classes to gain control just before its children are drawn
10762     * (but after its own view has been drawn).
10763     * @param canvas the canvas on which to draw the view
10764     */
10765    protected void dispatchDraw(Canvas canvas) {
10766
10767    }
10768
10769    /**
10770     * Gets the parent of this view. Note that the parent is a
10771     * ViewParent and not necessarily a View.
10772     *
10773     * @return Parent of this view.
10774     */
10775    public final ViewParent getParent() {
10776        return mParent;
10777    }
10778
10779    /**
10780     * Set the horizontal scrolled position of your view. This will cause a call to
10781     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10782     * invalidated.
10783     * @param value the x position to scroll to
10784     */
10785    public void setScrollX(int value) {
10786        scrollTo(value, mScrollY);
10787    }
10788
10789    /**
10790     * Set the vertical scrolled position of your view. This will cause a call to
10791     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10792     * invalidated.
10793     * @param value the y position to scroll to
10794     */
10795    public void setScrollY(int value) {
10796        scrollTo(mScrollX, value);
10797    }
10798
10799    /**
10800     * Return the scrolled left position of this view. This is the left edge of
10801     * the displayed part of your view. You do not need to draw any pixels
10802     * farther left, since those are outside of the frame of your view on
10803     * screen.
10804     *
10805     * @return The left edge of the displayed part of your view, in pixels.
10806     */
10807    public final int getScrollX() {
10808        return mScrollX;
10809    }
10810
10811    /**
10812     * Return the scrolled top position of this view. This is the top edge of
10813     * the displayed part of your view. You do not need to draw any pixels above
10814     * it, since those are outside of the frame of your view on screen.
10815     *
10816     * @return The top edge of the displayed part of your view, in pixels.
10817     */
10818    public final int getScrollY() {
10819        return mScrollY;
10820    }
10821
10822    /**
10823     * Return the width of the your view.
10824     *
10825     * @return The width of your view, in pixels.
10826     */
10827    @ViewDebug.ExportedProperty(category = "layout")
10828    public final int getWidth() {
10829        return mRight - mLeft;
10830    }
10831
10832    /**
10833     * Return the height of your view.
10834     *
10835     * @return The height of your view, in pixels.
10836     */
10837    @ViewDebug.ExportedProperty(category = "layout")
10838    public final int getHeight() {
10839        return mBottom - mTop;
10840    }
10841
10842    /**
10843     * Return the visible drawing bounds of your view. Fills in the output
10844     * rectangle with the values from getScrollX(), getScrollY(),
10845     * getWidth(), and getHeight(). These bounds do not account for any
10846     * transformation properties currently set on the view, such as
10847     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
10848     *
10849     * @param outRect The (scrolled) drawing bounds of the view.
10850     */
10851    public void getDrawingRect(Rect outRect) {
10852        outRect.left = mScrollX;
10853        outRect.top = mScrollY;
10854        outRect.right = mScrollX + (mRight - mLeft);
10855        outRect.bottom = mScrollY + (mBottom - mTop);
10856    }
10857
10858    /**
10859     * Like {@link #getMeasuredWidthAndState()}, but only returns the
10860     * raw width component (that is the result is masked by
10861     * {@link #MEASURED_SIZE_MASK}).
10862     *
10863     * @return The raw measured width of this view.
10864     */
10865    public final int getMeasuredWidth() {
10866        return mMeasuredWidth & MEASURED_SIZE_MASK;
10867    }
10868
10869    /**
10870     * Return the full width measurement information for this view as computed
10871     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10872     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10873     * This should be used during measurement and layout calculations only. Use
10874     * {@link #getWidth()} to see how wide a view is after layout.
10875     *
10876     * @return The measured width of this view as a bit mask.
10877     */
10878    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10879            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10880                    name = "MEASURED_STATE_TOO_SMALL"),
10881    })
10882    public final int getMeasuredWidthAndState() {
10883        return mMeasuredWidth;
10884    }
10885
10886    /**
10887     * Like {@link #getMeasuredHeightAndState()}, but only returns the
10888     * raw width component (that is the result is masked by
10889     * {@link #MEASURED_SIZE_MASK}).
10890     *
10891     * @return The raw measured height of this view.
10892     */
10893    public final int getMeasuredHeight() {
10894        return mMeasuredHeight & MEASURED_SIZE_MASK;
10895    }
10896
10897    /**
10898     * Return the full height measurement information for this view as computed
10899     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10900     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10901     * This should be used during measurement and layout calculations only. Use
10902     * {@link #getHeight()} to see how wide a view is after layout.
10903     *
10904     * @return The measured width of this view as a bit mask.
10905     */
10906    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10907            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10908                    name = "MEASURED_STATE_TOO_SMALL"),
10909    })
10910    public final int getMeasuredHeightAndState() {
10911        return mMeasuredHeight;
10912    }
10913
10914    /**
10915     * Return only the state bits of {@link #getMeasuredWidthAndState()}
10916     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
10917     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
10918     * and the height component is at the shifted bits
10919     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
10920     */
10921    public final int getMeasuredState() {
10922        return (mMeasuredWidth&MEASURED_STATE_MASK)
10923                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
10924                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
10925    }
10926
10927    /**
10928     * The transform matrix of this view, which is calculated based on the current
10929     * rotation, scale, and pivot properties.
10930     *
10931     * @see #getRotation()
10932     * @see #getScaleX()
10933     * @see #getScaleY()
10934     * @see #getPivotX()
10935     * @see #getPivotY()
10936     * @return The current transform matrix for the view
10937     */
10938    public Matrix getMatrix() {
10939        ensureTransformationInfo();
10940        final Matrix matrix = mTransformationInfo.mMatrix;
10941        mRenderNode.getMatrix(matrix);
10942        return matrix;
10943    }
10944
10945    /**
10946     * Returns true if the transform matrix is the identity matrix.
10947     * Recomputes the matrix if necessary.
10948     *
10949     * @return True if the transform matrix is the identity matrix, false otherwise.
10950     */
10951    final boolean hasIdentityMatrix() {
10952        return mRenderNode.hasIdentityMatrix();
10953    }
10954
10955    void ensureTransformationInfo() {
10956        if (mTransformationInfo == null) {
10957            mTransformationInfo = new TransformationInfo();
10958        }
10959    }
10960
10961   /**
10962     * Utility method to retrieve the inverse of the current mMatrix property.
10963     * We cache the matrix to avoid recalculating it when transform properties
10964     * have not changed.
10965     *
10966     * @return The inverse of the current matrix of this view.
10967     * @hide
10968     */
10969    public final Matrix getInverseMatrix() {
10970        ensureTransformationInfo();
10971        if (mTransformationInfo.mInverseMatrix == null) {
10972            mTransformationInfo.mInverseMatrix = new Matrix();
10973        }
10974        final Matrix matrix = mTransformationInfo.mInverseMatrix;
10975        mRenderNode.getInverseMatrix(matrix);
10976        return matrix;
10977    }
10978
10979    /**
10980     * Gets the distance along the Z axis from the camera to this view.
10981     *
10982     * @see #setCameraDistance(float)
10983     *
10984     * @return The distance along the Z axis.
10985     */
10986    public float getCameraDistance() {
10987        final float dpi = mResources.getDisplayMetrics().densityDpi;
10988        return -(mRenderNode.getCameraDistance() * dpi);
10989    }
10990
10991    /**
10992     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
10993     * views are drawn) from the camera to this view. The camera's distance
10994     * affects 3D transformations, for instance rotations around the X and Y
10995     * axis. If the rotationX or rotationY properties are changed and this view is
10996     * large (more than half the size of the screen), it is recommended to always
10997     * use a camera distance that's greater than the height (X axis rotation) or
10998     * the width (Y axis rotation) of this view.</p>
10999     *
11000     * <p>The distance of the camera from the view plane can have an affect on the
11001     * perspective distortion of the view when it is rotated around the x or y axis.
11002     * For example, a large distance will result in a large viewing angle, and there
11003     * will not be much perspective distortion of the view as it rotates. A short
11004     * distance may cause much more perspective distortion upon rotation, and can
11005     * also result in some drawing artifacts if the rotated view ends up partially
11006     * behind the camera (which is why the recommendation is to use a distance at
11007     * least as far as the size of the view, if the view is to be rotated.)</p>
11008     *
11009     * <p>The distance is expressed in "depth pixels." The default distance depends
11010     * on the screen density. For instance, on a medium density display, the
11011     * default distance is 1280. On a high density display, the default distance
11012     * is 1920.</p>
11013     *
11014     * <p>If you want to specify a distance that leads to visually consistent
11015     * results across various densities, use the following formula:</p>
11016     * <pre>
11017     * float scale = context.getResources().getDisplayMetrics().density;
11018     * view.setCameraDistance(distance * scale);
11019     * </pre>
11020     *
11021     * <p>The density scale factor of a high density display is 1.5,
11022     * and 1920 = 1280 * 1.5.</p>
11023     *
11024     * @param distance The distance in "depth pixels", if negative the opposite
11025     *        value is used
11026     *
11027     * @see #setRotationX(float)
11028     * @see #setRotationY(float)
11029     */
11030    public void setCameraDistance(float distance) {
11031        final float dpi = mResources.getDisplayMetrics().densityDpi;
11032
11033        invalidateViewProperty(true, false);
11034        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11035        invalidateViewProperty(false, false);
11036
11037        invalidateParentIfNeededAndWasQuickRejected();
11038    }
11039
11040    /**
11041     * The degrees that the view is rotated around the pivot point.
11042     *
11043     * @see #setRotation(float)
11044     * @see #getPivotX()
11045     * @see #getPivotY()
11046     *
11047     * @return The degrees of rotation.
11048     */
11049    @ViewDebug.ExportedProperty(category = "drawing")
11050    public float getRotation() {
11051        return mRenderNode.getRotation();
11052    }
11053
11054    /**
11055     * Sets the degrees that the view is rotated around the pivot point. Increasing values
11056     * result in clockwise rotation.
11057     *
11058     * @param rotation The degrees of rotation.
11059     *
11060     * @see #getRotation()
11061     * @see #getPivotX()
11062     * @see #getPivotY()
11063     * @see #setRotationX(float)
11064     * @see #setRotationY(float)
11065     *
11066     * @attr ref android.R.styleable#View_rotation
11067     */
11068    public void setRotation(float rotation) {
11069        if (rotation != getRotation()) {
11070            // Double-invalidation is necessary to capture view's old and new areas
11071            invalidateViewProperty(true, false);
11072            mRenderNode.setRotation(rotation);
11073            invalidateViewProperty(false, true);
11074
11075            invalidateParentIfNeededAndWasQuickRejected();
11076            notifySubtreeAccessibilityStateChangedIfNeeded();
11077        }
11078    }
11079
11080    /**
11081     * The degrees that the view is rotated around the vertical axis through the pivot point.
11082     *
11083     * @see #getPivotX()
11084     * @see #getPivotY()
11085     * @see #setRotationY(float)
11086     *
11087     * @return The degrees of Y rotation.
11088     */
11089    @ViewDebug.ExportedProperty(category = "drawing")
11090    public float getRotationY() {
11091        return mRenderNode.getRotationY();
11092    }
11093
11094    /**
11095     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
11096     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
11097     * down the y axis.
11098     *
11099     * When rotating large views, it is recommended to adjust the camera distance
11100     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11101     *
11102     * @param rotationY The degrees of Y rotation.
11103     *
11104     * @see #getRotationY()
11105     * @see #getPivotX()
11106     * @see #getPivotY()
11107     * @see #setRotation(float)
11108     * @see #setRotationX(float)
11109     * @see #setCameraDistance(float)
11110     *
11111     * @attr ref android.R.styleable#View_rotationY
11112     */
11113    public void setRotationY(float rotationY) {
11114        if (rotationY != getRotationY()) {
11115            invalidateViewProperty(true, false);
11116            mRenderNode.setRotationY(rotationY);
11117            invalidateViewProperty(false, true);
11118
11119            invalidateParentIfNeededAndWasQuickRejected();
11120            notifySubtreeAccessibilityStateChangedIfNeeded();
11121        }
11122    }
11123
11124    /**
11125     * The degrees that the view is rotated around the horizontal axis through the pivot point.
11126     *
11127     * @see #getPivotX()
11128     * @see #getPivotY()
11129     * @see #setRotationX(float)
11130     *
11131     * @return The degrees of X rotation.
11132     */
11133    @ViewDebug.ExportedProperty(category = "drawing")
11134    public float getRotationX() {
11135        return mRenderNode.getRotationX();
11136    }
11137
11138    /**
11139     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
11140     * Increasing values result in clockwise rotation from the viewpoint of looking down the
11141     * x axis.
11142     *
11143     * When rotating large views, it is recommended to adjust the camera distance
11144     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11145     *
11146     * @param rotationX The degrees of X rotation.
11147     *
11148     * @see #getRotationX()
11149     * @see #getPivotX()
11150     * @see #getPivotY()
11151     * @see #setRotation(float)
11152     * @see #setRotationY(float)
11153     * @see #setCameraDistance(float)
11154     *
11155     * @attr ref android.R.styleable#View_rotationX
11156     */
11157    public void setRotationX(float rotationX) {
11158        if (rotationX != getRotationX()) {
11159            invalidateViewProperty(true, false);
11160            mRenderNode.setRotationX(rotationX);
11161            invalidateViewProperty(false, true);
11162
11163            invalidateParentIfNeededAndWasQuickRejected();
11164            notifySubtreeAccessibilityStateChangedIfNeeded();
11165        }
11166    }
11167
11168    /**
11169     * The amount that the view is scaled in x around the pivot point, as a proportion of
11170     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
11171     *
11172     * <p>By default, this is 1.0f.
11173     *
11174     * @see #getPivotX()
11175     * @see #getPivotY()
11176     * @return The scaling factor.
11177     */
11178    @ViewDebug.ExportedProperty(category = "drawing")
11179    public float getScaleX() {
11180        return mRenderNode.getScaleX();
11181    }
11182
11183    /**
11184     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
11185     * the view's unscaled width. A value of 1 means that no scaling is applied.
11186     *
11187     * @param scaleX The scaling factor.
11188     * @see #getPivotX()
11189     * @see #getPivotY()
11190     *
11191     * @attr ref android.R.styleable#View_scaleX
11192     */
11193    public void setScaleX(float scaleX) {
11194        if (scaleX != getScaleX()) {
11195            invalidateViewProperty(true, false);
11196            mRenderNode.setScaleX(scaleX);
11197            invalidateViewProperty(false, true);
11198
11199            invalidateParentIfNeededAndWasQuickRejected();
11200            notifySubtreeAccessibilityStateChangedIfNeeded();
11201        }
11202    }
11203
11204    /**
11205     * The amount that the view is scaled in y around the pivot point, as a proportion of
11206     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
11207     *
11208     * <p>By default, this is 1.0f.
11209     *
11210     * @see #getPivotX()
11211     * @see #getPivotY()
11212     * @return The scaling factor.
11213     */
11214    @ViewDebug.ExportedProperty(category = "drawing")
11215    public float getScaleY() {
11216        return mRenderNode.getScaleY();
11217    }
11218
11219    /**
11220     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
11221     * the view's unscaled width. A value of 1 means that no scaling is applied.
11222     *
11223     * @param scaleY The scaling factor.
11224     * @see #getPivotX()
11225     * @see #getPivotY()
11226     *
11227     * @attr ref android.R.styleable#View_scaleY
11228     */
11229    public void setScaleY(float scaleY) {
11230        if (scaleY != getScaleY()) {
11231            invalidateViewProperty(true, false);
11232            mRenderNode.setScaleY(scaleY);
11233            invalidateViewProperty(false, true);
11234
11235            invalidateParentIfNeededAndWasQuickRejected();
11236            notifySubtreeAccessibilityStateChangedIfNeeded();
11237        }
11238    }
11239
11240    /**
11241     * The x location of the point around which the view is {@link #setRotation(float) rotated}
11242     * and {@link #setScaleX(float) scaled}.
11243     *
11244     * @see #getRotation()
11245     * @see #getScaleX()
11246     * @see #getScaleY()
11247     * @see #getPivotY()
11248     * @return The x location of the pivot point.
11249     *
11250     * @attr ref android.R.styleable#View_transformPivotX
11251     */
11252    @ViewDebug.ExportedProperty(category = "drawing")
11253    public float getPivotX() {
11254        return mRenderNode.getPivotX();
11255    }
11256
11257    /**
11258     * Sets the x location of the point around which the view is
11259     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
11260     * By default, the pivot point is centered on the object.
11261     * Setting this property disables this behavior and causes the view to use only the
11262     * explicitly set pivotX and pivotY values.
11263     *
11264     * @param pivotX The x location of the pivot point.
11265     * @see #getRotation()
11266     * @see #getScaleX()
11267     * @see #getScaleY()
11268     * @see #getPivotY()
11269     *
11270     * @attr ref android.R.styleable#View_transformPivotX
11271     */
11272    public void setPivotX(float pivotX) {
11273        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
11274            invalidateViewProperty(true, false);
11275            mRenderNode.setPivotX(pivotX);
11276            invalidateViewProperty(false, true);
11277
11278            invalidateParentIfNeededAndWasQuickRejected();
11279        }
11280    }
11281
11282    /**
11283     * The y location of the point around which the view is {@link #setRotation(float) rotated}
11284     * and {@link #setScaleY(float) scaled}.
11285     *
11286     * @see #getRotation()
11287     * @see #getScaleX()
11288     * @see #getScaleY()
11289     * @see #getPivotY()
11290     * @return The y location of the pivot point.
11291     *
11292     * @attr ref android.R.styleable#View_transformPivotY
11293     */
11294    @ViewDebug.ExportedProperty(category = "drawing")
11295    public float getPivotY() {
11296        return mRenderNode.getPivotY();
11297    }
11298
11299    /**
11300     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
11301     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
11302     * Setting this property disables this behavior and causes the view to use only the
11303     * explicitly set pivotX and pivotY values.
11304     *
11305     * @param pivotY The y location of the pivot point.
11306     * @see #getRotation()
11307     * @see #getScaleX()
11308     * @see #getScaleY()
11309     * @see #getPivotY()
11310     *
11311     * @attr ref android.R.styleable#View_transformPivotY
11312     */
11313    public void setPivotY(float pivotY) {
11314        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
11315            invalidateViewProperty(true, false);
11316            mRenderNode.setPivotY(pivotY);
11317            invalidateViewProperty(false, true);
11318
11319            invalidateParentIfNeededAndWasQuickRejected();
11320        }
11321    }
11322
11323    /**
11324     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
11325     * completely transparent and 1 means the view is completely opaque.
11326     *
11327     * <p>By default this is 1.0f.
11328     * @return The opacity of the view.
11329     */
11330    @ViewDebug.ExportedProperty(category = "drawing")
11331    public float getAlpha() {
11332        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
11333    }
11334
11335    /**
11336     * Returns whether this View has content which overlaps.
11337     *
11338     * <p>This function, intended to be overridden by specific View types, is an optimization when
11339     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
11340     * an offscreen buffer and then composited into place, which can be expensive. If the view has
11341     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
11342     * directly. An example of overlapping rendering is a TextView with a background image, such as
11343     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
11344     * ImageView with only the foreground image. The default implementation returns true; subclasses
11345     * should override if they have cases which can be optimized.</p>
11346     *
11347     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
11348     * necessitates that a View return true if it uses the methods internally without passing the
11349     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
11350     *
11351     * @return true if the content in this view might overlap, false otherwise.
11352     */
11353    @ViewDebug.ExportedProperty(category = "drawing")
11354    public boolean hasOverlappingRendering() {
11355        return true;
11356    }
11357
11358    /**
11359     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
11360     * completely transparent and 1 means the view is completely opaque.
11361     *
11362     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
11363     * can have significant performance implications, especially for large views. It is best to use
11364     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
11365     *
11366     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
11367     * strongly recommended for performance reasons to either override
11368     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
11369     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
11370     * of the animation. On versions {@link android.os.Build.VERSION_CODES#MNC} and below,
11371     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
11372     * of rendering cost, even for simple or small views. Starting with
11373     * {@link android.os.Build.VERSION_CODES#MNC}, {@link #LAYER_TYPE_HARDWARE} is automatically
11374     * applied to the view at the rendering level.</p>
11375     *
11376     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
11377     * responsible for applying the opacity itself.</p>
11378     *
11379     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
11380     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
11381     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
11382     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
11383     *
11384     * <p>Starting with {@link android.os.Build.VERSION_CODES#MNC}, setting a translucent alpha
11385     * value will clip a View to its bounds, unless the View returns <code>false</code> from
11386     * {@link #hasOverlappingRendering}.</p>
11387     *
11388     * @param alpha The opacity of the view.
11389     *
11390     * @see #hasOverlappingRendering()
11391     * @see #setLayerType(int, android.graphics.Paint)
11392     *
11393     * @attr ref android.R.styleable#View_alpha
11394     */
11395    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
11396        ensureTransformationInfo();
11397        if (mTransformationInfo.mAlpha != alpha) {
11398            mTransformationInfo.mAlpha = alpha;
11399            if (onSetAlpha((int) (alpha * 255))) {
11400                mPrivateFlags |= PFLAG_ALPHA_SET;
11401                // subclass is handling alpha - don't optimize rendering cache invalidation
11402                invalidateParentCaches();
11403                invalidate(true);
11404            } else {
11405                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11406                invalidateViewProperty(true, false);
11407                mRenderNode.setAlpha(getFinalAlpha());
11408                notifyViewAccessibilityStateChangedIfNeeded(
11409                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11410            }
11411        }
11412    }
11413
11414    /**
11415     * Faster version of setAlpha() which performs the same steps except there are
11416     * no calls to invalidate(). The caller of this function should perform proper invalidation
11417     * on the parent and this object. The return value indicates whether the subclass handles
11418     * alpha (the return value for onSetAlpha()).
11419     *
11420     * @param alpha The new value for the alpha property
11421     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
11422     *         the new value for the alpha property is different from the old value
11423     */
11424    boolean setAlphaNoInvalidation(float alpha) {
11425        ensureTransformationInfo();
11426        if (mTransformationInfo.mAlpha != alpha) {
11427            mTransformationInfo.mAlpha = alpha;
11428            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
11429            if (subclassHandlesAlpha) {
11430                mPrivateFlags |= PFLAG_ALPHA_SET;
11431                return true;
11432            } else {
11433                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11434                mRenderNode.setAlpha(getFinalAlpha());
11435            }
11436        }
11437        return false;
11438    }
11439
11440    /**
11441     * This property is hidden and intended only for use by the Fade transition, which
11442     * animates it to produce a visual translucency that does not side-effect (or get
11443     * affected by) the real alpha property. This value is composited with the other
11444     * alpha value (and the AlphaAnimation value, when that is present) to produce
11445     * a final visual translucency result, which is what is passed into the DisplayList.
11446     *
11447     * @hide
11448     */
11449    public void setTransitionAlpha(float alpha) {
11450        ensureTransformationInfo();
11451        if (mTransformationInfo.mTransitionAlpha != alpha) {
11452            mTransformationInfo.mTransitionAlpha = alpha;
11453            mPrivateFlags &= ~PFLAG_ALPHA_SET;
11454            invalidateViewProperty(true, false);
11455            mRenderNode.setAlpha(getFinalAlpha());
11456        }
11457    }
11458
11459    /**
11460     * Calculates the visual alpha of this view, which is a combination of the actual
11461     * alpha value and the transitionAlpha value (if set).
11462     */
11463    private float getFinalAlpha() {
11464        if (mTransformationInfo != null) {
11465            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11466        }
11467        return 1;
11468    }
11469
11470    /**
11471     * This property is hidden and intended only for use by the Fade transition, which
11472     * animates it to produce a visual translucency that does not side-effect (or get
11473     * affected by) the real alpha property. This value is composited with the other
11474     * alpha value (and the AlphaAnimation value, when that is present) to produce
11475     * a final visual translucency result, which is what is passed into the DisplayList.
11476     *
11477     * @hide
11478     */
11479    @ViewDebug.ExportedProperty(category = "drawing")
11480    public float getTransitionAlpha() {
11481        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11482    }
11483
11484    /**
11485     * Top position of this view relative to its parent.
11486     *
11487     * @return The top of this view, in pixels.
11488     */
11489    @ViewDebug.CapturedViewProperty
11490    public final int getTop() {
11491        return mTop;
11492    }
11493
11494    /**
11495     * Sets the top position of this view relative to its parent. This method is meant to be called
11496     * by the layout system and should not generally be called otherwise, because the property
11497     * may be changed at any time by the layout.
11498     *
11499     * @param top The top of this view, in pixels.
11500     */
11501    public final void setTop(int top) {
11502        if (top != mTop) {
11503            final boolean matrixIsIdentity = hasIdentityMatrix();
11504            if (matrixIsIdentity) {
11505                if (mAttachInfo != null) {
11506                    int minTop;
11507                    int yLoc;
11508                    if (top < mTop) {
11509                        minTop = top;
11510                        yLoc = top - mTop;
11511                    } else {
11512                        minTop = mTop;
11513                        yLoc = 0;
11514                    }
11515                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11516                }
11517            } else {
11518                // Double-invalidation is necessary to capture view's old and new areas
11519                invalidate(true);
11520            }
11521
11522            int width = mRight - mLeft;
11523            int oldHeight = mBottom - mTop;
11524
11525            mTop = top;
11526            mRenderNode.setTop(mTop);
11527
11528            sizeChange(width, mBottom - mTop, width, oldHeight);
11529
11530            if (!matrixIsIdentity) {
11531                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11532                invalidate(true);
11533            }
11534            mBackgroundSizeChanged = true;
11535            if (mForegroundInfo != null) {
11536                mForegroundInfo.mBoundsChanged = true;
11537            }
11538            invalidateParentIfNeeded();
11539            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11540                // View was rejected last time it was drawn by its parent; this may have changed
11541                invalidateParentIfNeeded();
11542            }
11543        }
11544    }
11545
11546    /**
11547     * Bottom position of this view relative to its parent.
11548     *
11549     * @return The bottom of this view, in pixels.
11550     */
11551    @ViewDebug.CapturedViewProperty
11552    public final int getBottom() {
11553        return mBottom;
11554    }
11555
11556    /**
11557     * True if this view has changed since the last time being drawn.
11558     *
11559     * @return The dirty state of this view.
11560     */
11561    public boolean isDirty() {
11562        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11563    }
11564
11565    /**
11566     * Sets the bottom position of this view relative to its parent. This method is meant to be
11567     * called by the layout system and should not generally be called otherwise, because the
11568     * property may be changed at any time by the layout.
11569     *
11570     * @param bottom The bottom of this view, in pixels.
11571     */
11572    public final void setBottom(int bottom) {
11573        if (bottom != mBottom) {
11574            final boolean matrixIsIdentity = hasIdentityMatrix();
11575            if (matrixIsIdentity) {
11576                if (mAttachInfo != null) {
11577                    int maxBottom;
11578                    if (bottom < mBottom) {
11579                        maxBottom = mBottom;
11580                    } else {
11581                        maxBottom = bottom;
11582                    }
11583                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11584                }
11585            } else {
11586                // Double-invalidation is necessary to capture view's old and new areas
11587                invalidate(true);
11588            }
11589
11590            int width = mRight - mLeft;
11591            int oldHeight = mBottom - mTop;
11592
11593            mBottom = bottom;
11594            mRenderNode.setBottom(mBottom);
11595
11596            sizeChange(width, mBottom - mTop, width, oldHeight);
11597
11598            if (!matrixIsIdentity) {
11599                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11600                invalidate(true);
11601            }
11602            mBackgroundSizeChanged = true;
11603            if (mForegroundInfo != null) {
11604                mForegroundInfo.mBoundsChanged = true;
11605            }
11606            invalidateParentIfNeeded();
11607            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11608                // View was rejected last time it was drawn by its parent; this may have changed
11609                invalidateParentIfNeeded();
11610            }
11611        }
11612    }
11613
11614    /**
11615     * Left position of this view relative to its parent.
11616     *
11617     * @return The left edge of this view, in pixels.
11618     */
11619    @ViewDebug.CapturedViewProperty
11620    public final int getLeft() {
11621        return mLeft;
11622    }
11623
11624    /**
11625     * Sets the left position of this view relative to its parent. This method is meant to be called
11626     * by the layout system and should not generally be called otherwise, because the property
11627     * may be changed at any time by the layout.
11628     *
11629     * @param left The left of this view, in pixels.
11630     */
11631    public final void setLeft(int left) {
11632        if (left != mLeft) {
11633            final boolean matrixIsIdentity = hasIdentityMatrix();
11634            if (matrixIsIdentity) {
11635                if (mAttachInfo != null) {
11636                    int minLeft;
11637                    int xLoc;
11638                    if (left < mLeft) {
11639                        minLeft = left;
11640                        xLoc = left - mLeft;
11641                    } else {
11642                        minLeft = mLeft;
11643                        xLoc = 0;
11644                    }
11645                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11646                }
11647            } else {
11648                // Double-invalidation is necessary to capture view's old and new areas
11649                invalidate(true);
11650            }
11651
11652            int oldWidth = mRight - mLeft;
11653            int height = mBottom - mTop;
11654
11655            mLeft = left;
11656            mRenderNode.setLeft(left);
11657
11658            sizeChange(mRight - mLeft, height, oldWidth, height);
11659
11660            if (!matrixIsIdentity) {
11661                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11662                invalidate(true);
11663            }
11664            mBackgroundSizeChanged = true;
11665            if (mForegroundInfo != null) {
11666                mForegroundInfo.mBoundsChanged = true;
11667            }
11668            invalidateParentIfNeeded();
11669            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11670                // View was rejected last time it was drawn by its parent; this may have changed
11671                invalidateParentIfNeeded();
11672            }
11673        }
11674    }
11675
11676    /**
11677     * Right position of this view relative to its parent.
11678     *
11679     * @return The right edge of this view, in pixels.
11680     */
11681    @ViewDebug.CapturedViewProperty
11682    public final int getRight() {
11683        return mRight;
11684    }
11685
11686    /**
11687     * Sets the right position of this view relative to its parent. This method is meant to be called
11688     * by the layout system and should not generally be called otherwise, because the property
11689     * may be changed at any time by the layout.
11690     *
11691     * @param right The right of this view, in pixels.
11692     */
11693    public final void setRight(int right) {
11694        if (right != mRight) {
11695            final boolean matrixIsIdentity = hasIdentityMatrix();
11696            if (matrixIsIdentity) {
11697                if (mAttachInfo != null) {
11698                    int maxRight;
11699                    if (right < mRight) {
11700                        maxRight = mRight;
11701                    } else {
11702                        maxRight = right;
11703                    }
11704                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
11705                }
11706            } else {
11707                // Double-invalidation is necessary to capture view's old and new areas
11708                invalidate(true);
11709            }
11710
11711            int oldWidth = mRight - mLeft;
11712            int height = mBottom - mTop;
11713
11714            mRight = right;
11715            mRenderNode.setRight(mRight);
11716
11717            sizeChange(mRight - mLeft, height, oldWidth, height);
11718
11719            if (!matrixIsIdentity) {
11720                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11721                invalidate(true);
11722            }
11723            mBackgroundSizeChanged = true;
11724            if (mForegroundInfo != null) {
11725                mForegroundInfo.mBoundsChanged = true;
11726            }
11727            invalidateParentIfNeeded();
11728            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11729                // View was rejected last time it was drawn by its parent; this may have changed
11730                invalidateParentIfNeeded();
11731            }
11732        }
11733    }
11734
11735    /**
11736     * The visual x position of this view, in pixels. This is equivalent to the
11737     * {@link #setTranslationX(float) translationX} property plus the current
11738     * {@link #getLeft() left} property.
11739     *
11740     * @return The visual x position of this view, in pixels.
11741     */
11742    @ViewDebug.ExportedProperty(category = "drawing")
11743    public float getX() {
11744        return mLeft + getTranslationX();
11745    }
11746
11747    /**
11748     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
11749     * {@link #setTranslationX(float) translationX} property to be the difference between
11750     * the x value passed in and the current {@link #getLeft() left} property.
11751     *
11752     * @param x The visual x position of this view, in pixels.
11753     */
11754    public void setX(float x) {
11755        setTranslationX(x - mLeft);
11756    }
11757
11758    /**
11759     * The visual y position of this view, in pixels. This is equivalent to the
11760     * {@link #setTranslationY(float) translationY} property plus the current
11761     * {@link #getTop() top} property.
11762     *
11763     * @return The visual y position of this view, in pixels.
11764     */
11765    @ViewDebug.ExportedProperty(category = "drawing")
11766    public float getY() {
11767        return mTop + getTranslationY();
11768    }
11769
11770    /**
11771     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
11772     * {@link #setTranslationY(float) translationY} property to be the difference between
11773     * the y value passed in and the current {@link #getTop() top} property.
11774     *
11775     * @param y The visual y position of this view, in pixels.
11776     */
11777    public void setY(float y) {
11778        setTranslationY(y - mTop);
11779    }
11780
11781    /**
11782     * The visual z position of this view, in pixels. This is equivalent to the
11783     * {@link #setTranslationZ(float) translationZ} property plus the current
11784     * {@link #getElevation() elevation} property.
11785     *
11786     * @return The visual z position of this view, in pixels.
11787     */
11788    @ViewDebug.ExportedProperty(category = "drawing")
11789    public float getZ() {
11790        return getElevation() + getTranslationZ();
11791    }
11792
11793    /**
11794     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
11795     * {@link #setTranslationZ(float) translationZ} property to be the difference between
11796     * the x value passed in and the current {@link #getElevation() elevation} property.
11797     *
11798     * @param z The visual z position of this view, in pixels.
11799     */
11800    public void setZ(float z) {
11801        setTranslationZ(z - getElevation());
11802    }
11803
11804    /**
11805     * The base elevation of this view relative to its parent, in pixels.
11806     *
11807     * @return The base depth position of the view, in pixels.
11808     */
11809    @ViewDebug.ExportedProperty(category = "drawing")
11810    public float getElevation() {
11811        return mRenderNode.getElevation();
11812    }
11813
11814    /**
11815     * Sets the base elevation of this view, in pixels.
11816     *
11817     * @attr ref android.R.styleable#View_elevation
11818     */
11819    public void setElevation(float elevation) {
11820        if (elevation != getElevation()) {
11821            invalidateViewProperty(true, false);
11822            mRenderNode.setElevation(elevation);
11823            invalidateViewProperty(false, true);
11824
11825            invalidateParentIfNeededAndWasQuickRejected();
11826        }
11827    }
11828
11829    /**
11830     * The horizontal location of this view relative to its {@link #getLeft() left} position.
11831     * This position is post-layout, in addition to wherever the object's
11832     * layout placed it.
11833     *
11834     * @return The horizontal position of this view relative to its left position, in pixels.
11835     */
11836    @ViewDebug.ExportedProperty(category = "drawing")
11837    public float getTranslationX() {
11838        return mRenderNode.getTranslationX();
11839    }
11840
11841    /**
11842     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
11843     * This effectively positions the object post-layout, in addition to wherever the object's
11844     * layout placed it.
11845     *
11846     * @param translationX The horizontal position of this view relative to its left position,
11847     * in pixels.
11848     *
11849     * @attr ref android.R.styleable#View_translationX
11850     */
11851    public void setTranslationX(float translationX) {
11852        if (translationX != getTranslationX()) {
11853            invalidateViewProperty(true, false);
11854            mRenderNode.setTranslationX(translationX);
11855            invalidateViewProperty(false, true);
11856
11857            invalidateParentIfNeededAndWasQuickRejected();
11858            notifySubtreeAccessibilityStateChangedIfNeeded();
11859        }
11860    }
11861
11862    /**
11863     * The vertical location of this view relative to its {@link #getTop() top} position.
11864     * This position is post-layout, in addition to wherever the object's
11865     * layout placed it.
11866     *
11867     * @return The vertical position of this view relative to its top position,
11868     * in pixels.
11869     */
11870    @ViewDebug.ExportedProperty(category = "drawing")
11871    public float getTranslationY() {
11872        return mRenderNode.getTranslationY();
11873    }
11874
11875    /**
11876     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
11877     * This effectively positions the object post-layout, in addition to wherever the object's
11878     * layout placed it.
11879     *
11880     * @param translationY The vertical position of this view relative to its top position,
11881     * in pixels.
11882     *
11883     * @attr ref android.R.styleable#View_translationY
11884     */
11885    public void setTranslationY(float translationY) {
11886        if (translationY != getTranslationY()) {
11887            invalidateViewProperty(true, false);
11888            mRenderNode.setTranslationY(translationY);
11889            invalidateViewProperty(false, true);
11890
11891            invalidateParentIfNeededAndWasQuickRejected();
11892            notifySubtreeAccessibilityStateChangedIfNeeded();
11893        }
11894    }
11895
11896    /**
11897     * The depth location of this view relative to its {@link #getElevation() elevation}.
11898     *
11899     * @return The depth of this view relative to its elevation.
11900     */
11901    @ViewDebug.ExportedProperty(category = "drawing")
11902    public float getTranslationZ() {
11903        return mRenderNode.getTranslationZ();
11904    }
11905
11906    /**
11907     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
11908     *
11909     * @attr ref android.R.styleable#View_translationZ
11910     */
11911    public void setTranslationZ(float translationZ) {
11912        if (translationZ != getTranslationZ()) {
11913            invalidateViewProperty(true, false);
11914            mRenderNode.setTranslationZ(translationZ);
11915            invalidateViewProperty(false, true);
11916
11917            invalidateParentIfNeededAndWasQuickRejected();
11918        }
11919    }
11920
11921    /** @hide */
11922    public void setAnimationMatrix(Matrix matrix) {
11923        invalidateViewProperty(true, false);
11924        mRenderNode.setAnimationMatrix(matrix);
11925        invalidateViewProperty(false, true);
11926
11927        invalidateParentIfNeededAndWasQuickRejected();
11928    }
11929
11930    /**
11931     * Returns the current StateListAnimator if exists.
11932     *
11933     * @return StateListAnimator or null if it does not exists
11934     * @see    #setStateListAnimator(android.animation.StateListAnimator)
11935     */
11936    public StateListAnimator getStateListAnimator() {
11937        return mStateListAnimator;
11938    }
11939
11940    /**
11941     * Attaches the provided StateListAnimator to this View.
11942     * <p>
11943     * Any previously attached StateListAnimator will be detached.
11944     *
11945     * @param stateListAnimator The StateListAnimator to update the view
11946     * @see {@link android.animation.StateListAnimator}
11947     */
11948    public void setStateListAnimator(StateListAnimator stateListAnimator) {
11949        if (mStateListAnimator == stateListAnimator) {
11950            return;
11951        }
11952        if (mStateListAnimator != null) {
11953            mStateListAnimator.setTarget(null);
11954        }
11955        mStateListAnimator = stateListAnimator;
11956        if (stateListAnimator != null) {
11957            stateListAnimator.setTarget(this);
11958            if (isAttachedToWindow()) {
11959                stateListAnimator.setState(getDrawableState());
11960            }
11961        }
11962    }
11963
11964    /**
11965     * Returns whether the Outline should be used to clip the contents of the View.
11966     * <p>
11967     * Note that this flag will only be respected if the View's Outline returns true from
11968     * {@link Outline#canClip()}.
11969     *
11970     * @see #setOutlineProvider(ViewOutlineProvider)
11971     * @see #setClipToOutline(boolean)
11972     */
11973    public final boolean getClipToOutline() {
11974        return mRenderNode.getClipToOutline();
11975    }
11976
11977    /**
11978     * Sets whether the View's Outline should be used to clip the contents of the View.
11979     * <p>
11980     * Only a single non-rectangular clip can be applied on a View at any time.
11981     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
11982     * circular reveal} animation take priority over Outline clipping, and
11983     * child Outline clipping takes priority over Outline clipping done by a
11984     * parent.
11985     * <p>
11986     * Note that this flag will only be respected if the View's Outline returns true from
11987     * {@link Outline#canClip()}.
11988     *
11989     * @see #setOutlineProvider(ViewOutlineProvider)
11990     * @see #getClipToOutline()
11991     */
11992    public void setClipToOutline(boolean clipToOutline) {
11993        damageInParent();
11994        if (getClipToOutline() != clipToOutline) {
11995            mRenderNode.setClipToOutline(clipToOutline);
11996        }
11997    }
11998
11999    // correspond to the enum values of View_outlineProvider
12000    private static final int PROVIDER_BACKGROUND = 0;
12001    private static final int PROVIDER_NONE = 1;
12002    private static final int PROVIDER_BOUNDS = 2;
12003    private static final int PROVIDER_PADDED_BOUNDS = 3;
12004    private void setOutlineProviderFromAttribute(int providerInt) {
12005        switch (providerInt) {
12006            case PROVIDER_BACKGROUND:
12007                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12008                break;
12009            case PROVIDER_NONE:
12010                setOutlineProvider(null);
12011                break;
12012            case PROVIDER_BOUNDS:
12013                setOutlineProvider(ViewOutlineProvider.BOUNDS);
12014                break;
12015            case PROVIDER_PADDED_BOUNDS:
12016                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12017                break;
12018        }
12019    }
12020
12021    /**
12022     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12023     * the shape of the shadow it casts, and enables outline clipping.
12024     * <p>
12025     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12026     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12027     * outline provider with this method allows this behavior to be overridden.
12028     * <p>
12029     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12030     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12031     * <p>
12032     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12033     *
12034     * @see #setClipToOutline(boolean)
12035     * @see #getClipToOutline()
12036     * @see #getOutlineProvider()
12037     */
12038    public void setOutlineProvider(ViewOutlineProvider provider) {
12039        mOutlineProvider = provider;
12040        invalidateOutline();
12041    }
12042
12043    /**
12044     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
12045     * that defines the shape of the shadow it casts, and enables outline clipping.
12046     *
12047     * @see #setOutlineProvider(ViewOutlineProvider)
12048     */
12049    public ViewOutlineProvider getOutlineProvider() {
12050        return mOutlineProvider;
12051    }
12052
12053    /**
12054     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
12055     *
12056     * @see #setOutlineProvider(ViewOutlineProvider)
12057     */
12058    public void invalidateOutline() {
12059        rebuildOutline();
12060
12061        notifySubtreeAccessibilityStateChangedIfNeeded();
12062        invalidateViewProperty(false, false);
12063    }
12064
12065    /**
12066     * Internal version of {@link #invalidateOutline()} which invalidates the
12067     * outline without invalidating the view itself. This is intended to be called from
12068     * within methods in the View class itself which are the result of the view being
12069     * invalidated already. For example, when we are drawing the background of a View,
12070     * we invalidate the outline in case it changed in the meantime, but we do not
12071     * need to invalidate the view because we're already drawing the background as part
12072     * of drawing the view in response to an earlier invalidation of the view.
12073     */
12074    private void rebuildOutline() {
12075        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
12076        if (mAttachInfo == null) return;
12077
12078        if (mOutlineProvider == null) {
12079            // no provider, remove outline
12080            mRenderNode.setOutline(null);
12081        } else {
12082            final Outline outline = mAttachInfo.mTmpOutline;
12083            outline.setEmpty();
12084            outline.setAlpha(1.0f);
12085
12086            mOutlineProvider.getOutline(this, outline);
12087            mRenderNode.setOutline(outline);
12088        }
12089    }
12090
12091    /**
12092     * HierarchyViewer only
12093     *
12094     * @hide
12095     */
12096    @ViewDebug.ExportedProperty(category = "drawing")
12097    public boolean hasShadow() {
12098        return mRenderNode.hasShadow();
12099    }
12100
12101
12102    /** @hide */
12103    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
12104        mRenderNode.setRevealClip(shouldClip, x, y, radius);
12105        invalidateViewProperty(false, false);
12106    }
12107
12108    /**
12109     * Hit rectangle in parent's coordinates
12110     *
12111     * @param outRect The hit rectangle of the view.
12112     */
12113    public void getHitRect(Rect outRect) {
12114        if (hasIdentityMatrix() || mAttachInfo == null) {
12115            outRect.set(mLeft, mTop, mRight, mBottom);
12116        } else {
12117            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
12118            tmpRect.set(0, 0, getWidth(), getHeight());
12119            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
12120            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
12121                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
12122        }
12123    }
12124
12125    /**
12126     * Determines whether the given point, in local coordinates is inside the view.
12127     */
12128    /*package*/ final boolean pointInView(float localX, float localY) {
12129        return localX >= 0 && localX < (mRight - mLeft)
12130                && localY >= 0 && localY < (mBottom - mTop);
12131    }
12132
12133    /**
12134     * Utility method to determine whether the given point, in local coordinates,
12135     * is inside the view, where the area of the view is expanded by the slop factor.
12136     * This method is called while processing touch-move events to determine if the event
12137     * is still within the view.
12138     *
12139     * @hide
12140     */
12141    public boolean pointInView(float localX, float localY, float slop) {
12142        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
12143                localY < ((mBottom - mTop) + slop);
12144    }
12145
12146    /**
12147     * When a view has focus and the user navigates away from it, the next view is searched for
12148     * starting from the rectangle filled in by this method.
12149     *
12150     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
12151     * of the view.  However, if your view maintains some idea of internal selection,
12152     * such as a cursor, or a selected row or column, you should override this method and
12153     * fill in a more specific rectangle.
12154     *
12155     * @param r The rectangle to fill in, in this view's coordinates.
12156     */
12157    public void getFocusedRect(Rect r) {
12158        getDrawingRect(r);
12159    }
12160
12161    /**
12162     * If some part of this view is not clipped by any of its parents, then
12163     * return that area in r in global (root) coordinates. To convert r to local
12164     * coordinates (without taking possible View rotations into account), offset
12165     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
12166     * If the view is completely clipped or translated out, return false.
12167     *
12168     * @param r If true is returned, r holds the global coordinates of the
12169     *        visible portion of this view.
12170     * @param globalOffset If true is returned, globalOffset holds the dx,dy
12171     *        between this view and its root. globalOffet may be null.
12172     * @return true if r is non-empty (i.e. part of the view is visible at the
12173     *         root level.
12174     */
12175    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
12176        int width = mRight - mLeft;
12177        int height = mBottom - mTop;
12178        if (width > 0 && height > 0) {
12179            r.set(0, 0, width, height);
12180            if (globalOffset != null) {
12181                globalOffset.set(-mScrollX, -mScrollY);
12182            }
12183            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
12184        }
12185        return false;
12186    }
12187
12188    public final boolean getGlobalVisibleRect(Rect r) {
12189        return getGlobalVisibleRect(r, null);
12190    }
12191
12192    public final boolean getLocalVisibleRect(Rect r) {
12193        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
12194        if (getGlobalVisibleRect(r, offset)) {
12195            r.offset(-offset.x, -offset.y); // make r local
12196            return true;
12197        }
12198        return false;
12199    }
12200
12201    /**
12202     * Offset this view's vertical location by the specified number of pixels.
12203     *
12204     * @param offset the number of pixels to offset the view by
12205     */
12206    public void offsetTopAndBottom(int offset) {
12207        if (offset != 0) {
12208            final boolean matrixIsIdentity = hasIdentityMatrix();
12209            if (matrixIsIdentity) {
12210                if (isHardwareAccelerated()) {
12211                    invalidateViewProperty(false, false);
12212                } else {
12213                    final ViewParent p = mParent;
12214                    if (p != null && mAttachInfo != null) {
12215                        final Rect r = mAttachInfo.mTmpInvalRect;
12216                        int minTop;
12217                        int maxBottom;
12218                        int yLoc;
12219                        if (offset < 0) {
12220                            minTop = mTop + offset;
12221                            maxBottom = mBottom;
12222                            yLoc = offset;
12223                        } else {
12224                            minTop = mTop;
12225                            maxBottom = mBottom + offset;
12226                            yLoc = 0;
12227                        }
12228                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
12229                        p.invalidateChild(this, r);
12230                    }
12231                }
12232            } else {
12233                invalidateViewProperty(false, false);
12234            }
12235
12236            mTop += offset;
12237            mBottom += offset;
12238            mRenderNode.offsetTopAndBottom(offset);
12239            if (isHardwareAccelerated()) {
12240                invalidateViewProperty(false, false);
12241            } else {
12242                if (!matrixIsIdentity) {
12243                    invalidateViewProperty(false, true);
12244                }
12245                invalidateParentIfNeeded();
12246            }
12247            notifySubtreeAccessibilityStateChangedIfNeeded();
12248        }
12249    }
12250
12251    /**
12252     * Offset this view's horizontal location by the specified amount of pixels.
12253     *
12254     * @param offset the number of pixels to offset the view by
12255     */
12256    public void offsetLeftAndRight(int offset) {
12257        if (offset != 0) {
12258            final boolean matrixIsIdentity = hasIdentityMatrix();
12259            if (matrixIsIdentity) {
12260                if (isHardwareAccelerated()) {
12261                    invalidateViewProperty(false, false);
12262                } else {
12263                    final ViewParent p = mParent;
12264                    if (p != null && mAttachInfo != null) {
12265                        final Rect r = mAttachInfo.mTmpInvalRect;
12266                        int minLeft;
12267                        int maxRight;
12268                        if (offset < 0) {
12269                            minLeft = mLeft + offset;
12270                            maxRight = mRight;
12271                        } else {
12272                            minLeft = mLeft;
12273                            maxRight = mRight + offset;
12274                        }
12275                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
12276                        p.invalidateChild(this, r);
12277                    }
12278                }
12279            } else {
12280                invalidateViewProperty(false, false);
12281            }
12282
12283            mLeft += offset;
12284            mRight += offset;
12285            mRenderNode.offsetLeftAndRight(offset);
12286            if (isHardwareAccelerated()) {
12287                invalidateViewProperty(false, false);
12288            } else {
12289                if (!matrixIsIdentity) {
12290                    invalidateViewProperty(false, true);
12291                }
12292                invalidateParentIfNeeded();
12293            }
12294            notifySubtreeAccessibilityStateChangedIfNeeded();
12295        }
12296    }
12297
12298    /**
12299     * Get the LayoutParams associated with this view. All views should have
12300     * layout parameters. These supply parameters to the <i>parent</i> of this
12301     * view specifying how it should be arranged. There are many subclasses of
12302     * ViewGroup.LayoutParams, and these correspond to the different subclasses
12303     * of ViewGroup that are responsible for arranging their children.
12304     *
12305     * This method may return null if this View is not attached to a parent
12306     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
12307     * was not invoked successfully. When a View is attached to a parent
12308     * ViewGroup, this method must not return null.
12309     *
12310     * @return The LayoutParams associated with this view, or null if no
12311     *         parameters have been set yet
12312     */
12313    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
12314    public ViewGroup.LayoutParams getLayoutParams() {
12315        return mLayoutParams;
12316    }
12317
12318    /**
12319     * Set the layout parameters associated with this view. These supply
12320     * parameters to the <i>parent</i> of this view specifying how it should be
12321     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
12322     * correspond to the different subclasses of ViewGroup that are responsible
12323     * for arranging their children.
12324     *
12325     * @param params The layout parameters for this view, cannot be null
12326     */
12327    public void setLayoutParams(ViewGroup.LayoutParams params) {
12328        if (params == null) {
12329            throw new NullPointerException("Layout parameters cannot be null");
12330        }
12331        mLayoutParams = params;
12332        resolveLayoutParams();
12333        if (mParent instanceof ViewGroup) {
12334            ((ViewGroup) mParent).onSetLayoutParams(this, params);
12335        }
12336        requestLayout();
12337    }
12338
12339    /**
12340     * Resolve the layout parameters depending on the resolved layout direction
12341     *
12342     * @hide
12343     */
12344    public void resolveLayoutParams() {
12345        if (mLayoutParams != null) {
12346            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
12347        }
12348    }
12349
12350    /**
12351     * Set the scrolled position of your view. This will cause a call to
12352     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12353     * invalidated.
12354     * @param x the x position to scroll to
12355     * @param y the y position to scroll to
12356     */
12357    public void scrollTo(int x, int y) {
12358        if (mScrollX != x || mScrollY != y) {
12359            int oldX = mScrollX;
12360            int oldY = mScrollY;
12361            mScrollX = x;
12362            mScrollY = y;
12363            invalidateParentCaches();
12364            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
12365            if (!awakenScrollBars()) {
12366                postInvalidateOnAnimation();
12367            }
12368        }
12369    }
12370
12371    /**
12372     * Move the scrolled position of your view. This will cause a call to
12373     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12374     * invalidated.
12375     * @param x the amount of pixels to scroll by horizontally
12376     * @param y the amount of pixels to scroll by vertically
12377     */
12378    public void scrollBy(int x, int y) {
12379        scrollTo(mScrollX + x, mScrollY + y);
12380    }
12381
12382    /**
12383     * <p>Trigger the scrollbars to draw. When invoked this method starts an
12384     * animation to fade the scrollbars out after a default delay. If a subclass
12385     * provides animated scrolling, the start delay should equal the duration
12386     * of the scrolling animation.</p>
12387     *
12388     * <p>The animation starts only if at least one of the scrollbars is
12389     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
12390     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12391     * this method returns true, and false otherwise. If the animation is
12392     * started, this method calls {@link #invalidate()}; in that case the
12393     * caller should not call {@link #invalidate()}.</p>
12394     *
12395     * <p>This method should be invoked every time a subclass directly updates
12396     * the scroll parameters.</p>
12397     *
12398     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
12399     * and {@link #scrollTo(int, int)}.</p>
12400     *
12401     * @return true if the animation is played, false otherwise
12402     *
12403     * @see #awakenScrollBars(int)
12404     * @see #scrollBy(int, int)
12405     * @see #scrollTo(int, int)
12406     * @see #isHorizontalScrollBarEnabled()
12407     * @see #isVerticalScrollBarEnabled()
12408     * @see #setHorizontalScrollBarEnabled(boolean)
12409     * @see #setVerticalScrollBarEnabled(boolean)
12410     */
12411    protected boolean awakenScrollBars() {
12412        return mScrollCache != null &&
12413                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
12414    }
12415
12416    /**
12417     * Trigger the scrollbars to draw.
12418     * This method differs from awakenScrollBars() only in its default duration.
12419     * initialAwakenScrollBars() will show the scroll bars for longer than
12420     * usual to give the user more of a chance to notice them.
12421     *
12422     * @return true if the animation is played, false otherwise.
12423     */
12424    private boolean initialAwakenScrollBars() {
12425        return mScrollCache != null &&
12426                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
12427    }
12428
12429    /**
12430     * <p>
12431     * Trigger the scrollbars to draw. When invoked this method starts an
12432     * animation to fade the scrollbars out after a fixed delay. If a subclass
12433     * provides animated scrolling, the start delay should equal the duration of
12434     * the scrolling animation.
12435     * </p>
12436     *
12437     * <p>
12438     * The animation starts only if at least one of the scrollbars is enabled,
12439     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12440     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12441     * this method returns true, and false otherwise. If the animation is
12442     * started, this method calls {@link #invalidate()}; in that case the caller
12443     * should not call {@link #invalidate()}.
12444     * </p>
12445     *
12446     * <p>
12447     * This method should be invoked every time a subclass directly updates the
12448     * scroll parameters.
12449     * </p>
12450     *
12451     * @param startDelay the delay, in milliseconds, after which the animation
12452     *        should start; when the delay is 0, the animation starts
12453     *        immediately
12454     * @return true if the animation is played, false otherwise
12455     *
12456     * @see #scrollBy(int, int)
12457     * @see #scrollTo(int, int)
12458     * @see #isHorizontalScrollBarEnabled()
12459     * @see #isVerticalScrollBarEnabled()
12460     * @see #setHorizontalScrollBarEnabled(boolean)
12461     * @see #setVerticalScrollBarEnabled(boolean)
12462     */
12463    protected boolean awakenScrollBars(int startDelay) {
12464        return awakenScrollBars(startDelay, true);
12465    }
12466
12467    /**
12468     * <p>
12469     * Trigger the scrollbars to draw. When invoked this method starts an
12470     * animation to fade the scrollbars out after a fixed delay. If a subclass
12471     * provides animated scrolling, the start delay should equal the duration of
12472     * the scrolling animation.
12473     * </p>
12474     *
12475     * <p>
12476     * The animation starts only if at least one of the scrollbars is enabled,
12477     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12478     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12479     * this method returns true, and false otherwise. If the animation is
12480     * started, this method calls {@link #invalidate()} if the invalidate parameter
12481     * is set to true; in that case the caller
12482     * should not call {@link #invalidate()}.
12483     * </p>
12484     *
12485     * <p>
12486     * This method should be invoked every time a subclass directly updates the
12487     * scroll parameters.
12488     * </p>
12489     *
12490     * @param startDelay the delay, in milliseconds, after which the animation
12491     *        should start; when the delay is 0, the animation starts
12492     *        immediately
12493     *
12494     * @param invalidate Whether this method should call invalidate
12495     *
12496     * @return true if the animation is played, false otherwise
12497     *
12498     * @see #scrollBy(int, int)
12499     * @see #scrollTo(int, int)
12500     * @see #isHorizontalScrollBarEnabled()
12501     * @see #isVerticalScrollBarEnabled()
12502     * @see #setHorizontalScrollBarEnabled(boolean)
12503     * @see #setVerticalScrollBarEnabled(boolean)
12504     */
12505    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12506        final ScrollabilityCache scrollCache = mScrollCache;
12507
12508        if (scrollCache == null || !scrollCache.fadeScrollBars) {
12509            return false;
12510        }
12511
12512        if (scrollCache.scrollBar == null) {
12513            scrollCache.scrollBar = new ScrollBarDrawable();
12514            scrollCache.scrollBar.setCallback(this);
12515            scrollCache.scrollBar.setState(getDrawableState());
12516        }
12517
12518        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12519
12520            if (invalidate) {
12521                // Invalidate to show the scrollbars
12522                postInvalidateOnAnimation();
12523            }
12524
12525            if (scrollCache.state == ScrollabilityCache.OFF) {
12526                // FIXME: this is copied from WindowManagerService.
12527                // We should get this value from the system when it
12528                // is possible to do so.
12529                final int KEY_REPEAT_FIRST_DELAY = 750;
12530                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12531            }
12532
12533            // Tell mScrollCache when we should start fading. This may
12534            // extend the fade start time if one was already scheduled
12535            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12536            scrollCache.fadeStartTime = fadeStartTime;
12537            scrollCache.state = ScrollabilityCache.ON;
12538
12539            // Schedule our fader to run, unscheduling any old ones first
12540            if (mAttachInfo != null) {
12541                mAttachInfo.mHandler.removeCallbacks(scrollCache);
12542                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12543            }
12544
12545            return true;
12546        }
12547
12548        return false;
12549    }
12550
12551    /**
12552     * Do not invalidate views which are not visible and which are not running an animation. They
12553     * will not get drawn and they should not set dirty flags as if they will be drawn
12554     */
12555    private boolean skipInvalidate() {
12556        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12557                (!(mParent instanceof ViewGroup) ||
12558                        !((ViewGroup) mParent).isViewTransitioning(this));
12559    }
12560
12561    /**
12562     * Mark the area defined by dirty as needing to be drawn. If the view is
12563     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12564     * point in the future.
12565     * <p>
12566     * This must be called from a UI thread. To call from a non-UI thread, call
12567     * {@link #postInvalidate()}.
12568     * <p>
12569     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12570     * {@code dirty}.
12571     *
12572     * @param dirty the rectangle representing the bounds of the dirty region
12573     */
12574    public void invalidate(Rect dirty) {
12575        final int scrollX = mScrollX;
12576        final int scrollY = mScrollY;
12577        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12578                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12579    }
12580
12581    /**
12582     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12583     * coordinates of the dirty rect are relative to the view. If the view is
12584     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12585     * point in the future.
12586     * <p>
12587     * This must be called from a UI thread. To call from a non-UI thread, call
12588     * {@link #postInvalidate()}.
12589     *
12590     * @param l the left position of the dirty region
12591     * @param t the top position of the dirty region
12592     * @param r the right position of the dirty region
12593     * @param b the bottom position of the dirty region
12594     */
12595    public void invalidate(int l, int t, int r, int b) {
12596        final int scrollX = mScrollX;
12597        final int scrollY = mScrollY;
12598        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12599    }
12600
12601    /**
12602     * Invalidate the whole view. If the view is visible,
12603     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12604     * the future.
12605     * <p>
12606     * This must be called from a UI thread. To call from a non-UI thread, call
12607     * {@link #postInvalidate()}.
12608     */
12609    public void invalidate() {
12610        invalidate(true);
12611    }
12612
12613    /**
12614     * This is where the invalidate() work actually happens. A full invalidate()
12615     * causes the drawing cache to be invalidated, but this function can be
12616     * called with invalidateCache set to false to skip that invalidation step
12617     * for cases that do not need it (for example, a component that remains at
12618     * the same dimensions with the same content).
12619     *
12620     * @param invalidateCache Whether the drawing cache for this view should be
12621     *            invalidated as well. This is usually true for a full
12622     *            invalidate, but may be set to false if the View's contents or
12623     *            dimensions have not changed.
12624     */
12625    void invalidate(boolean invalidateCache) {
12626        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12627    }
12628
12629    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12630            boolean fullInvalidate) {
12631        if (mGhostView != null) {
12632            mGhostView.invalidate(true);
12633            return;
12634        }
12635
12636        if (skipInvalidate()) {
12637            return;
12638        }
12639
12640        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12641                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12642                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12643                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12644            if (fullInvalidate) {
12645                mLastIsOpaque = isOpaque();
12646                mPrivateFlags &= ~PFLAG_DRAWN;
12647            }
12648
12649            mPrivateFlags |= PFLAG_DIRTY;
12650
12651            if (invalidateCache) {
12652                mPrivateFlags |= PFLAG_INVALIDATED;
12653                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12654            }
12655
12656            // Propagate the damage rectangle to the parent view.
12657            final AttachInfo ai = mAttachInfo;
12658            final ViewParent p = mParent;
12659            if (p != null && ai != null && l < r && t < b) {
12660                final Rect damage = ai.mTmpInvalRect;
12661                damage.set(l, t, r, b);
12662                p.invalidateChild(this, damage);
12663            }
12664
12665            // Damage the entire projection receiver, if necessary.
12666            if (mBackground != null && mBackground.isProjected()) {
12667                final View receiver = getProjectionReceiver();
12668                if (receiver != null) {
12669                    receiver.damageInParent();
12670                }
12671            }
12672
12673            // Damage the entire IsolatedZVolume receiving this view's shadow.
12674            if (isHardwareAccelerated() && getZ() != 0) {
12675                damageShadowReceiver();
12676            }
12677        }
12678    }
12679
12680    /**
12681     * @return this view's projection receiver, or {@code null} if none exists
12682     */
12683    private View getProjectionReceiver() {
12684        ViewParent p = getParent();
12685        while (p != null && p instanceof View) {
12686            final View v = (View) p;
12687            if (v.isProjectionReceiver()) {
12688                return v;
12689            }
12690            p = p.getParent();
12691        }
12692
12693        return null;
12694    }
12695
12696    /**
12697     * @return whether the view is a projection receiver
12698     */
12699    private boolean isProjectionReceiver() {
12700        return mBackground != null;
12701    }
12702
12703    /**
12704     * Damage area of the screen that can be covered by this View's shadow.
12705     *
12706     * This method will guarantee that any changes to shadows cast by a View
12707     * are damaged on the screen for future redraw.
12708     */
12709    private void damageShadowReceiver() {
12710        final AttachInfo ai = mAttachInfo;
12711        if (ai != null) {
12712            ViewParent p = getParent();
12713            if (p != null && p instanceof ViewGroup) {
12714                final ViewGroup vg = (ViewGroup) p;
12715                vg.damageInParent();
12716            }
12717        }
12718    }
12719
12720    /**
12721     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
12722     * set any flags or handle all of the cases handled by the default invalidation methods.
12723     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
12724     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
12725     * walk up the hierarchy, transforming the dirty rect as necessary.
12726     *
12727     * The method also handles normal invalidation logic if display list properties are not
12728     * being used in this view. The invalidateParent and forceRedraw flags are used by that
12729     * backup approach, to handle these cases used in the various property-setting methods.
12730     *
12731     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
12732     * are not being used in this view
12733     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
12734     * list properties are not being used in this view
12735     */
12736    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
12737        if (!isHardwareAccelerated()
12738                || !mRenderNode.isValid()
12739                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
12740            if (invalidateParent) {
12741                invalidateParentCaches();
12742            }
12743            if (forceRedraw) {
12744                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12745            }
12746            invalidate(false);
12747        } else {
12748            damageInParent();
12749        }
12750        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
12751            damageShadowReceiver();
12752        }
12753    }
12754
12755    /**
12756     * Tells the parent view to damage this view's bounds.
12757     *
12758     * @hide
12759     */
12760    protected void damageInParent() {
12761        final AttachInfo ai = mAttachInfo;
12762        final ViewParent p = mParent;
12763        if (p != null && ai != null) {
12764            final Rect r = ai.mTmpInvalRect;
12765            r.set(0, 0, mRight - mLeft, mBottom - mTop);
12766            if (mParent instanceof ViewGroup) {
12767                ((ViewGroup) mParent).damageChild(this, r);
12768            } else {
12769                mParent.invalidateChild(this, r);
12770            }
12771        }
12772    }
12773
12774    /**
12775     * Utility method to transform a given Rect by the current matrix of this view.
12776     */
12777    void transformRect(final Rect rect) {
12778        if (!getMatrix().isIdentity()) {
12779            RectF boundingRect = mAttachInfo.mTmpTransformRect;
12780            boundingRect.set(rect);
12781            getMatrix().mapRect(boundingRect);
12782            rect.set((int) Math.floor(boundingRect.left),
12783                    (int) Math.floor(boundingRect.top),
12784                    (int) Math.ceil(boundingRect.right),
12785                    (int) Math.ceil(boundingRect.bottom));
12786        }
12787    }
12788
12789    /**
12790     * Used to indicate that the parent of this view should clear its caches. This functionality
12791     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12792     * which is necessary when various parent-managed properties of the view change, such as
12793     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
12794     * clears the parent caches and does not causes an invalidate event.
12795     *
12796     * @hide
12797     */
12798    protected void invalidateParentCaches() {
12799        if (mParent instanceof View) {
12800            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
12801        }
12802    }
12803
12804    /**
12805     * Used to indicate that the parent of this view should be invalidated. This functionality
12806     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12807     * which is necessary when various parent-managed properties of the view change, such as
12808     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
12809     * an invalidation event to the parent.
12810     *
12811     * @hide
12812     */
12813    protected void invalidateParentIfNeeded() {
12814        if (isHardwareAccelerated() && mParent instanceof View) {
12815            ((View) mParent).invalidate(true);
12816        }
12817    }
12818
12819    /**
12820     * @hide
12821     */
12822    protected void invalidateParentIfNeededAndWasQuickRejected() {
12823        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
12824            // View was rejected last time it was drawn by its parent; this may have changed
12825            invalidateParentIfNeeded();
12826        }
12827    }
12828
12829    /**
12830     * Indicates whether this View is opaque. An opaque View guarantees that it will
12831     * draw all the pixels overlapping its bounds using a fully opaque color.
12832     *
12833     * Subclasses of View should override this method whenever possible to indicate
12834     * whether an instance is opaque. Opaque Views are treated in a special way by
12835     * the View hierarchy, possibly allowing it to perform optimizations during
12836     * invalidate/draw passes.
12837     *
12838     * @return True if this View is guaranteed to be fully opaque, false otherwise.
12839     */
12840    @ViewDebug.ExportedProperty(category = "drawing")
12841    public boolean isOpaque() {
12842        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
12843                getFinalAlpha() >= 1.0f;
12844    }
12845
12846    /**
12847     * @hide
12848     */
12849    protected void computeOpaqueFlags() {
12850        // Opaque if:
12851        //   - Has a background
12852        //   - Background is opaque
12853        //   - Doesn't have scrollbars or scrollbars overlay
12854
12855        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
12856            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
12857        } else {
12858            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
12859        }
12860
12861        final int flags = mViewFlags;
12862        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
12863                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
12864                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
12865            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
12866        } else {
12867            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
12868        }
12869    }
12870
12871    /**
12872     * @hide
12873     */
12874    protected boolean hasOpaqueScrollbars() {
12875        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
12876    }
12877
12878    /**
12879     * @return A handler associated with the thread running the View. This
12880     * handler can be used to pump events in the UI events queue.
12881     */
12882    public Handler getHandler() {
12883        final AttachInfo attachInfo = mAttachInfo;
12884        if (attachInfo != null) {
12885            return attachInfo.mHandler;
12886        }
12887        return null;
12888    }
12889
12890    /**
12891     * Gets the view root associated with the View.
12892     * @return The view root, or null if none.
12893     * @hide
12894     */
12895    public ViewRootImpl getViewRootImpl() {
12896        if (mAttachInfo != null) {
12897            return mAttachInfo.mViewRootImpl;
12898        }
12899        return null;
12900    }
12901
12902    /**
12903     * @hide
12904     */
12905    public HardwareRenderer getHardwareRenderer() {
12906        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
12907    }
12908
12909    /**
12910     * <p>Causes the Runnable to be added to the message queue.
12911     * The runnable will be run on the user interface thread.</p>
12912     *
12913     * @param action The Runnable that will be executed.
12914     *
12915     * @return Returns true if the Runnable was successfully placed in to the
12916     *         message queue.  Returns false on failure, usually because the
12917     *         looper processing the message queue is exiting.
12918     *
12919     * @see #postDelayed
12920     * @see #removeCallbacks
12921     */
12922    public boolean post(Runnable action) {
12923        final AttachInfo attachInfo = mAttachInfo;
12924        if (attachInfo != null) {
12925            return attachInfo.mHandler.post(action);
12926        }
12927        // Assume that post will succeed later
12928        ViewRootImpl.getRunQueue().post(action);
12929        return true;
12930    }
12931
12932    /**
12933     * <p>Causes the Runnable to be added to the message queue, to be run
12934     * after the specified amount of time elapses.
12935     * The runnable will be run on the user interface thread.</p>
12936     *
12937     * @param action The Runnable that will be executed.
12938     * @param delayMillis The delay (in milliseconds) until the Runnable
12939     *        will be executed.
12940     *
12941     * @return true if the Runnable was successfully placed in to the
12942     *         message queue.  Returns false on failure, usually because the
12943     *         looper processing the message queue is exiting.  Note that a
12944     *         result of true does not mean the Runnable will be processed --
12945     *         if the looper is quit before the delivery time of the message
12946     *         occurs then the message will be dropped.
12947     *
12948     * @see #post
12949     * @see #removeCallbacks
12950     */
12951    public boolean postDelayed(Runnable action, long delayMillis) {
12952        final AttachInfo attachInfo = mAttachInfo;
12953        if (attachInfo != null) {
12954            return attachInfo.mHandler.postDelayed(action, delayMillis);
12955        }
12956        // Assume that post will succeed later
12957        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12958        return true;
12959    }
12960
12961    /**
12962     * <p>Causes the Runnable to execute on the next animation time step.
12963     * The runnable will be run on the user interface thread.</p>
12964     *
12965     * @param action The Runnable that will be executed.
12966     *
12967     * @see #postOnAnimationDelayed
12968     * @see #removeCallbacks
12969     */
12970    public void postOnAnimation(Runnable action) {
12971        final AttachInfo attachInfo = mAttachInfo;
12972        if (attachInfo != null) {
12973            attachInfo.mViewRootImpl.mChoreographer.postCallback(
12974                    Choreographer.CALLBACK_ANIMATION, action, null);
12975        } else {
12976            // Assume that post will succeed later
12977            ViewRootImpl.getRunQueue().post(action);
12978        }
12979    }
12980
12981    /**
12982     * <p>Causes the Runnable to execute on the next animation time step,
12983     * after the specified amount of time elapses.
12984     * The runnable will be run on the user interface thread.</p>
12985     *
12986     * @param action The Runnable that will be executed.
12987     * @param delayMillis The delay (in milliseconds) until the Runnable
12988     *        will be executed.
12989     *
12990     * @see #postOnAnimation
12991     * @see #removeCallbacks
12992     */
12993    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
12994        final AttachInfo attachInfo = mAttachInfo;
12995        if (attachInfo != null) {
12996            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
12997                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
12998        } else {
12999            // Assume that post will succeed later
13000            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
13001        }
13002    }
13003
13004    /**
13005     * <p>Removes the specified Runnable from the message queue.</p>
13006     *
13007     * @param action The Runnable to remove from the message handling queue
13008     *
13009     * @return true if this view could ask the Handler to remove the Runnable,
13010     *         false otherwise. When the returned value is true, the Runnable
13011     *         may or may not have been actually removed from the message queue
13012     *         (for instance, if the Runnable was not in the queue already.)
13013     *
13014     * @see #post
13015     * @see #postDelayed
13016     * @see #postOnAnimation
13017     * @see #postOnAnimationDelayed
13018     */
13019    public boolean removeCallbacks(Runnable action) {
13020        if (action != null) {
13021            final AttachInfo attachInfo = mAttachInfo;
13022            if (attachInfo != null) {
13023                attachInfo.mHandler.removeCallbacks(action);
13024                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13025                        Choreographer.CALLBACK_ANIMATION, action, null);
13026            }
13027            // Assume that post will succeed later
13028            ViewRootImpl.getRunQueue().removeCallbacks(action);
13029        }
13030        return true;
13031    }
13032
13033    /**
13034     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
13035     * Use this to invalidate the View from a non-UI thread.</p>
13036     *
13037     * <p>This method can be invoked from outside of the UI thread
13038     * only when this View is attached to a window.</p>
13039     *
13040     * @see #invalidate()
13041     * @see #postInvalidateDelayed(long)
13042     */
13043    public void postInvalidate() {
13044        postInvalidateDelayed(0);
13045    }
13046
13047    /**
13048     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13049     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
13050     *
13051     * <p>This method can be invoked from outside of the UI thread
13052     * only when this View is attached to a window.</p>
13053     *
13054     * @param left The left coordinate of the rectangle to invalidate.
13055     * @param top The top coordinate of the rectangle to invalidate.
13056     * @param right The right coordinate of the rectangle to invalidate.
13057     * @param bottom The bottom coordinate of the rectangle to invalidate.
13058     *
13059     * @see #invalidate(int, int, int, int)
13060     * @see #invalidate(Rect)
13061     * @see #postInvalidateDelayed(long, int, int, int, int)
13062     */
13063    public void postInvalidate(int left, int top, int right, int bottom) {
13064        postInvalidateDelayed(0, left, top, right, bottom);
13065    }
13066
13067    /**
13068     * <p>Cause an invalidate to happen on a subsequent cycle through the event
13069     * loop. Waits for the specified amount of time.</p>
13070     *
13071     * <p>This method can be invoked from outside of the UI thread
13072     * only when this View is attached to a window.</p>
13073     *
13074     * @param delayMilliseconds the duration in milliseconds to delay the
13075     *         invalidation by
13076     *
13077     * @see #invalidate()
13078     * @see #postInvalidate()
13079     */
13080    public void postInvalidateDelayed(long delayMilliseconds) {
13081        // We try only with the AttachInfo because there's no point in invalidating
13082        // if we are not attached to our window
13083        final AttachInfo attachInfo = mAttachInfo;
13084        if (attachInfo != null) {
13085            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
13086        }
13087    }
13088
13089    /**
13090     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13091     * through the event loop. Waits for the specified amount of time.</p>
13092     *
13093     * <p>This method can be invoked from outside of the UI thread
13094     * only when this View is attached to a window.</p>
13095     *
13096     * @param delayMilliseconds the duration in milliseconds to delay the
13097     *         invalidation by
13098     * @param left The left coordinate of the rectangle to invalidate.
13099     * @param top The top coordinate of the rectangle to invalidate.
13100     * @param right The right coordinate of the rectangle to invalidate.
13101     * @param bottom The bottom coordinate of the rectangle to invalidate.
13102     *
13103     * @see #invalidate(int, int, int, int)
13104     * @see #invalidate(Rect)
13105     * @see #postInvalidate(int, int, int, int)
13106     */
13107    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
13108            int right, int bottom) {
13109
13110        // We try only with the AttachInfo because there's no point in invalidating
13111        // if we are not attached to our window
13112        final AttachInfo attachInfo = mAttachInfo;
13113        if (attachInfo != null) {
13114            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13115            info.target = this;
13116            info.left = left;
13117            info.top = top;
13118            info.right = right;
13119            info.bottom = bottom;
13120
13121            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
13122        }
13123    }
13124
13125    /**
13126     * <p>Cause an invalidate to happen on the next animation time step, typically the
13127     * next display frame.</p>
13128     *
13129     * <p>This method can be invoked from outside of the UI thread
13130     * only when this View is attached to a window.</p>
13131     *
13132     * @see #invalidate()
13133     */
13134    public void postInvalidateOnAnimation() {
13135        // We try only with the AttachInfo because there's no point in invalidating
13136        // if we are not attached to our window
13137        final AttachInfo attachInfo = mAttachInfo;
13138        if (attachInfo != null) {
13139            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
13140        }
13141    }
13142
13143    /**
13144     * <p>Cause an invalidate of the specified area to happen on the next animation
13145     * time step, typically the next display frame.</p>
13146     *
13147     * <p>This method can be invoked from outside of the UI thread
13148     * only when this View is attached to a window.</p>
13149     *
13150     * @param left The left coordinate of the rectangle to invalidate.
13151     * @param top The top coordinate of the rectangle to invalidate.
13152     * @param right The right coordinate of the rectangle to invalidate.
13153     * @param bottom The bottom coordinate of the rectangle to invalidate.
13154     *
13155     * @see #invalidate(int, int, int, int)
13156     * @see #invalidate(Rect)
13157     */
13158    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
13159        // We try only with the AttachInfo because there's no point in invalidating
13160        // if we are not attached to our window
13161        final AttachInfo attachInfo = mAttachInfo;
13162        if (attachInfo != null) {
13163            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13164            info.target = this;
13165            info.left = left;
13166            info.top = top;
13167            info.right = right;
13168            info.bottom = bottom;
13169
13170            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
13171        }
13172    }
13173
13174    /**
13175     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
13176     * This event is sent at most once every
13177     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
13178     */
13179    private void postSendViewScrolledAccessibilityEventCallback() {
13180        if (mSendViewScrolledAccessibilityEvent == null) {
13181            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
13182        }
13183        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
13184            mSendViewScrolledAccessibilityEvent.mIsPending = true;
13185            postDelayed(mSendViewScrolledAccessibilityEvent,
13186                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
13187        }
13188    }
13189
13190    /**
13191     * Called by a parent to request that a child update its values for mScrollX
13192     * and mScrollY if necessary. This will typically be done if the child is
13193     * animating a scroll using a {@link android.widget.Scroller Scroller}
13194     * object.
13195     */
13196    public void computeScroll() {
13197    }
13198
13199    /**
13200     * <p>Indicate whether the horizontal edges are faded when the view is
13201     * scrolled horizontally.</p>
13202     *
13203     * @return true if the horizontal edges should are faded on scroll, false
13204     *         otherwise
13205     *
13206     * @see #setHorizontalFadingEdgeEnabled(boolean)
13207     *
13208     * @attr ref android.R.styleable#View_requiresFadingEdge
13209     */
13210    public boolean isHorizontalFadingEdgeEnabled() {
13211        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
13212    }
13213
13214    /**
13215     * <p>Define whether the horizontal edges should be faded when this view
13216     * is scrolled horizontally.</p>
13217     *
13218     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
13219     *                                    be faded when the view is scrolled
13220     *                                    horizontally
13221     *
13222     * @see #isHorizontalFadingEdgeEnabled()
13223     *
13224     * @attr ref android.R.styleable#View_requiresFadingEdge
13225     */
13226    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
13227        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
13228            if (horizontalFadingEdgeEnabled) {
13229                initScrollCache();
13230            }
13231
13232            mViewFlags ^= FADING_EDGE_HORIZONTAL;
13233        }
13234    }
13235
13236    /**
13237     * <p>Indicate whether the vertical edges are faded when the view is
13238     * scrolled horizontally.</p>
13239     *
13240     * @return true if the vertical edges should are faded on scroll, false
13241     *         otherwise
13242     *
13243     * @see #setVerticalFadingEdgeEnabled(boolean)
13244     *
13245     * @attr ref android.R.styleable#View_requiresFadingEdge
13246     */
13247    public boolean isVerticalFadingEdgeEnabled() {
13248        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
13249    }
13250
13251    /**
13252     * <p>Define whether the vertical edges should be faded when this view
13253     * is scrolled vertically.</p>
13254     *
13255     * @param verticalFadingEdgeEnabled true if the vertical edges should
13256     *                                  be faded when the view is scrolled
13257     *                                  vertically
13258     *
13259     * @see #isVerticalFadingEdgeEnabled()
13260     *
13261     * @attr ref android.R.styleable#View_requiresFadingEdge
13262     */
13263    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
13264        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
13265            if (verticalFadingEdgeEnabled) {
13266                initScrollCache();
13267            }
13268
13269            mViewFlags ^= FADING_EDGE_VERTICAL;
13270        }
13271    }
13272
13273    /**
13274     * Returns the strength, or intensity, of the top faded edge. The strength is
13275     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13276     * returns 0.0 or 1.0 but no value in between.
13277     *
13278     * Subclasses should override this method to provide a smoother fade transition
13279     * when scrolling occurs.
13280     *
13281     * @return the intensity of the top fade as a float between 0.0f and 1.0f
13282     */
13283    protected float getTopFadingEdgeStrength() {
13284        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
13285    }
13286
13287    /**
13288     * Returns the strength, or intensity, of the bottom faded edge. The strength is
13289     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13290     * returns 0.0 or 1.0 but no value in between.
13291     *
13292     * Subclasses should override this method to provide a smoother fade transition
13293     * when scrolling occurs.
13294     *
13295     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
13296     */
13297    protected float getBottomFadingEdgeStrength() {
13298        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
13299                computeVerticalScrollRange() ? 1.0f : 0.0f;
13300    }
13301
13302    /**
13303     * Returns the strength, or intensity, of the left faded edge. The strength is
13304     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13305     * returns 0.0 or 1.0 but no value in between.
13306     *
13307     * Subclasses should override this method to provide a smoother fade transition
13308     * when scrolling occurs.
13309     *
13310     * @return the intensity of the left fade as a float between 0.0f and 1.0f
13311     */
13312    protected float getLeftFadingEdgeStrength() {
13313        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
13314    }
13315
13316    /**
13317     * Returns the strength, or intensity, of the right faded edge. The strength is
13318     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13319     * returns 0.0 or 1.0 but no value in between.
13320     *
13321     * Subclasses should override this method to provide a smoother fade transition
13322     * when scrolling occurs.
13323     *
13324     * @return the intensity of the right fade as a float between 0.0f and 1.0f
13325     */
13326    protected float getRightFadingEdgeStrength() {
13327        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
13328                computeHorizontalScrollRange() ? 1.0f : 0.0f;
13329    }
13330
13331    /**
13332     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
13333     * scrollbar is not drawn by default.</p>
13334     *
13335     * @return true if the horizontal scrollbar should be painted, false
13336     *         otherwise
13337     *
13338     * @see #setHorizontalScrollBarEnabled(boolean)
13339     */
13340    public boolean isHorizontalScrollBarEnabled() {
13341        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13342    }
13343
13344    /**
13345     * <p>Define whether the horizontal scrollbar should be drawn or not. The
13346     * scrollbar is not drawn by default.</p>
13347     *
13348     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
13349     *                                   be painted
13350     *
13351     * @see #isHorizontalScrollBarEnabled()
13352     */
13353    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
13354        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
13355            mViewFlags ^= SCROLLBARS_HORIZONTAL;
13356            computeOpaqueFlags();
13357            resolvePadding();
13358        }
13359    }
13360
13361    /**
13362     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
13363     * scrollbar is not drawn by default.</p>
13364     *
13365     * @return true if the vertical scrollbar should be painted, false
13366     *         otherwise
13367     *
13368     * @see #setVerticalScrollBarEnabled(boolean)
13369     */
13370    public boolean isVerticalScrollBarEnabled() {
13371        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
13372    }
13373
13374    /**
13375     * <p>Define whether the vertical scrollbar should be drawn or not. The
13376     * scrollbar is not drawn by default.</p>
13377     *
13378     * @param verticalScrollBarEnabled true if the vertical scrollbar should
13379     *                                 be painted
13380     *
13381     * @see #isVerticalScrollBarEnabled()
13382     */
13383    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
13384        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
13385            mViewFlags ^= SCROLLBARS_VERTICAL;
13386            computeOpaqueFlags();
13387            resolvePadding();
13388        }
13389    }
13390
13391    /**
13392     * @hide
13393     */
13394    protected void recomputePadding() {
13395        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13396    }
13397
13398    /**
13399     * Define whether scrollbars will fade when the view is not scrolling.
13400     *
13401     * @param fadeScrollbars whether to enable fading
13402     *
13403     * @attr ref android.R.styleable#View_fadeScrollbars
13404     */
13405    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
13406        initScrollCache();
13407        final ScrollabilityCache scrollabilityCache = mScrollCache;
13408        scrollabilityCache.fadeScrollBars = fadeScrollbars;
13409        if (fadeScrollbars) {
13410            scrollabilityCache.state = ScrollabilityCache.OFF;
13411        } else {
13412            scrollabilityCache.state = ScrollabilityCache.ON;
13413        }
13414    }
13415
13416    /**
13417     *
13418     * Returns true if scrollbars will fade when this view is not scrolling
13419     *
13420     * @return true if scrollbar fading is enabled
13421     *
13422     * @attr ref android.R.styleable#View_fadeScrollbars
13423     */
13424    public boolean isScrollbarFadingEnabled() {
13425        return mScrollCache != null && mScrollCache.fadeScrollBars;
13426    }
13427
13428    /**
13429     *
13430     * Returns the delay before scrollbars fade.
13431     *
13432     * @return the delay before scrollbars fade
13433     *
13434     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13435     */
13436    public int getScrollBarDefaultDelayBeforeFade() {
13437        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
13438                mScrollCache.scrollBarDefaultDelayBeforeFade;
13439    }
13440
13441    /**
13442     * Define the delay before scrollbars fade.
13443     *
13444     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
13445     *
13446     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13447     */
13448    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
13449        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
13450    }
13451
13452    /**
13453     *
13454     * Returns the scrollbar fade duration.
13455     *
13456     * @return the scrollbar fade duration
13457     *
13458     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13459     */
13460    public int getScrollBarFadeDuration() {
13461        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13462                mScrollCache.scrollBarFadeDuration;
13463    }
13464
13465    /**
13466     * Define the scrollbar fade duration.
13467     *
13468     * @param scrollBarFadeDuration - the scrollbar fade duration
13469     *
13470     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13471     */
13472    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13473        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13474    }
13475
13476    /**
13477     *
13478     * Returns the scrollbar size.
13479     *
13480     * @return the scrollbar size
13481     *
13482     * @attr ref android.R.styleable#View_scrollbarSize
13483     */
13484    public int getScrollBarSize() {
13485        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13486                mScrollCache.scrollBarSize;
13487    }
13488
13489    /**
13490     * Define the scrollbar size.
13491     *
13492     * @param scrollBarSize - the scrollbar size
13493     *
13494     * @attr ref android.R.styleable#View_scrollbarSize
13495     */
13496    public void setScrollBarSize(int scrollBarSize) {
13497        getScrollCache().scrollBarSize = scrollBarSize;
13498    }
13499
13500    /**
13501     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13502     * inset. When inset, they add to the padding of the view. And the scrollbars
13503     * can be drawn inside the padding area or on the edge of the view. For example,
13504     * if a view has a background drawable and you want to draw the scrollbars
13505     * inside the padding specified by the drawable, you can use
13506     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13507     * appear at the edge of the view, ignoring the padding, then you can use
13508     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13509     * @param style the style of the scrollbars. Should be one of
13510     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13511     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13512     * @see #SCROLLBARS_INSIDE_OVERLAY
13513     * @see #SCROLLBARS_INSIDE_INSET
13514     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13515     * @see #SCROLLBARS_OUTSIDE_INSET
13516     *
13517     * @attr ref android.R.styleable#View_scrollbarStyle
13518     */
13519    public void setScrollBarStyle(@ScrollBarStyle int style) {
13520        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13521            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13522            computeOpaqueFlags();
13523            resolvePadding();
13524        }
13525    }
13526
13527    /**
13528     * <p>Returns the current scrollbar style.</p>
13529     * @return the current scrollbar style
13530     * @see #SCROLLBARS_INSIDE_OVERLAY
13531     * @see #SCROLLBARS_INSIDE_INSET
13532     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13533     * @see #SCROLLBARS_OUTSIDE_INSET
13534     *
13535     * @attr ref android.R.styleable#View_scrollbarStyle
13536     */
13537    @ViewDebug.ExportedProperty(mapping = {
13538            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13539            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13540            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13541            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13542    })
13543    @ScrollBarStyle
13544    public int getScrollBarStyle() {
13545        return mViewFlags & SCROLLBARS_STYLE_MASK;
13546    }
13547
13548    /**
13549     * <p>Compute the horizontal range that the horizontal scrollbar
13550     * represents.</p>
13551     *
13552     * <p>The range is expressed in arbitrary units that must be the same as the
13553     * units used by {@link #computeHorizontalScrollExtent()} and
13554     * {@link #computeHorizontalScrollOffset()}.</p>
13555     *
13556     * <p>The default range is the drawing width of this view.</p>
13557     *
13558     * @return the total horizontal range represented by the horizontal
13559     *         scrollbar
13560     *
13561     * @see #computeHorizontalScrollExtent()
13562     * @see #computeHorizontalScrollOffset()
13563     * @see android.widget.ScrollBarDrawable
13564     */
13565    protected int computeHorizontalScrollRange() {
13566        return getWidth();
13567    }
13568
13569    /**
13570     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13571     * within the horizontal range. This value is used to compute the position
13572     * of the thumb within the scrollbar's track.</p>
13573     *
13574     * <p>The range is expressed in arbitrary units that must be the same as the
13575     * units used by {@link #computeHorizontalScrollRange()} and
13576     * {@link #computeHorizontalScrollExtent()}.</p>
13577     *
13578     * <p>The default offset is the scroll offset of this view.</p>
13579     *
13580     * @return the horizontal offset of the scrollbar's thumb
13581     *
13582     * @see #computeHorizontalScrollRange()
13583     * @see #computeHorizontalScrollExtent()
13584     * @see android.widget.ScrollBarDrawable
13585     */
13586    protected int computeHorizontalScrollOffset() {
13587        return mScrollX;
13588    }
13589
13590    /**
13591     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13592     * within the horizontal range. This value is used to compute the length
13593     * of the thumb within the scrollbar's track.</p>
13594     *
13595     * <p>The range is expressed in arbitrary units that must be the same as the
13596     * units used by {@link #computeHorizontalScrollRange()} and
13597     * {@link #computeHorizontalScrollOffset()}.</p>
13598     *
13599     * <p>The default extent is the drawing width of this view.</p>
13600     *
13601     * @return the horizontal extent of the scrollbar's thumb
13602     *
13603     * @see #computeHorizontalScrollRange()
13604     * @see #computeHorizontalScrollOffset()
13605     * @see android.widget.ScrollBarDrawable
13606     */
13607    protected int computeHorizontalScrollExtent() {
13608        return getWidth();
13609    }
13610
13611    /**
13612     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13613     *
13614     * <p>The range is expressed in arbitrary units that must be the same as the
13615     * units used by {@link #computeVerticalScrollExtent()} and
13616     * {@link #computeVerticalScrollOffset()}.</p>
13617     *
13618     * @return the total vertical range represented by the vertical scrollbar
13619     *
13620     * <p>The default range is the drawing height of this view.</p>
13621     *
13622     * @see #computeVerticalScrollExtent()
13623     * @see #computeVerticalScrollOffset()
13624     * @see android.widget.ScrollBarDrawable
13625     */
13626    protected int computeVerticalScrollRange() {
13627        return getHeight();
13628    }
13629
13630    /**
13631     * <p>Compute the vertical offset of the vertical scrollbar's thumb
13632     * within the horizontal range. This value is used to compute the position
13633     * of the thumb within the scrollbar's track.</p>
13634     *
13635     * <p>The range is expressed in arbitrary units that must be the same as the
13636     * units used by {@link #computeVerticalScrollRange()} and
13637     * {@link #computeVerticalScrollExtent()}.</p>
13638     *
13639     * <p>The default offset is the scroll offset of this view.</p>
13640     *
13641     * @return the vertical offset of the scrollbar's thumb
13642     *
13643     * @see #computeVerticalScrollRange()
13644     * @see #computeVerticalScrollExtent()
13645     * @see android.widget.ScrollBarDrawable
13646     */
13647    protected int computeVerticalScrollOffset() {
13648        return mScrollY;
13649    }
13650
13651    /**
13652     * <p>Compute the vertical extent of the vertical scrollbar's thumb
13653     * within the vertical range. This value is used to compute the length
13654     * of the thumb within the scrollbar's track.</p>
13655     *
13656     * <p>The range is expressed in arbitrary units that must be the same as the
13657     * units used by {@link #computeVerticalScrollRange()} and
13658     * {@link #computeVerticalScrollOffset()}.</p>
13659     *
13660     * <p>The default extent is the drawing height of this view.</p>
13661     *
13662     * @return the vertical extent of the scrollbar's thumb
13663     *
13664     * @see #computeVerticalScrollRange()
13665     * @see #computeVerticalScrollOffset()
13666     * @see android.widget.ScrollBarDrawable
13667     */
13668    protected int computeVerticalScrollExtent() {
13669        return getHeight();
13670    }
13671
13672    /**
13673     * Check if this view can be scrolled horizontally in a certain direction.
13674     *
13675     * @param direction Negative to check scrolling left, positive to check scrolling right.
13676     * @return true if this view can be scrolled in the specified direction, false otherwise.
13677     */
13678    public boolean canScrollHorizontally(int direction) {
13679        final int offset = computeHorizontalScrollOffset();
13680        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
13681        if (range == 0) return false;
13682        if (direction < 0) {
13683            return offset > 0;
13684        } else {
13685            return offset < range - 1;
13686        }
13687    }
13688
13689    /**
13690     * Check if this view can be scrolled vertically in a certain direction.
13691     *
13692     * @param direction Negative to check scrolling up, positive to check scrolling down.
13693     * @return true if this view can be scrolled in the specified direction, false otherwise.
13694     */
13695    public boolean canScrollVertically(int direction) {
13696        final int offset = computeVerticalScrollOffset();
13697        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
13698        if (range == 0) return false;
13699        if (direction < 0) {
13700            return offset > 0;
13701        } else {
13702            return offset < range - 1;
13703        }
13704    }
13705
13706    void getScrollIndicatorBounds(@NonNull Rect out) {
13707        out.left = mScrollX;
13708        out.right = mScrollX + mRight - mLeft;
13709        out.top = mScrollY;
13710        out.bottom = mScrollY + mBottom - mTop;
13711    }
13712
13713    private void onDrawScrollIndicators(Canvas c) {
13714        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
13715            // No scroll indicators enabled.
13716            return;
13717        }
13718
13719        final Drawable dr = mScrollIndicatorDrawable;
13720        if (dr == null) {
13721            // Scroll indicators aren't supported here.
13722            return;
13723        }
13724
13725        final int h = dr.getIntrinsicHeight();
13726        final int w = dr.getIntrinsicWidth();
13727        final Rect rect = mAttachInfo.mTmpInvalRect;
13728        getScrollIndicatorBounds(rect);
13729
13730        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
13731            final boolean canScrollUp = canScrollVertically(-1);
13732            if (canScrollUp) {
13733                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
13734                dr.draw(c);
13735            }
13736        }
13737
13738        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
13739            final boolean canScrollDown = canScrollVertically(1);
13740            if (canScrollDown) {
13741                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
13742                dr.draw(c);
13743            }
13744        }
13745
13746        final int leftRtl;
13747        final int rightRtl;
13748        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13749            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
13750            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
13751        } else {
13752            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
13753            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
13754        }
13755
13756        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
13757        if ((mPrivateFlags3 & leftMask) != 0) {
13758            final boolean canScrollLeft = canScrollHorizontally(-1);
13759            if (canScrollLeft) {
13760                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
13761                dr.draw(c);
13762            }
13763        }
13764
13765        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
13766        if ((mPrivateFlags3 & rightMask) != 0) {
13767            final boolean canScrollRight = canScrollHorizontally(1);
13768            if (canScrollRight) {
13769                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
13770                dr.draw(c);
13771            }
13772        }
13773    }
13774
13775    /**
13776     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
13777     * scrollbars are painted only if they have been awakened first.</p>
13778     *
13779     * @param canvas the canvas on which to draw the scrollbars
13780     *
13781     * @see #awakenScrollBars(int)
13782     */
13783    protected final void onDrawScrollBars(Canvas canvas) {
13784        // scrollbars are drawn only when the animation is running
13785        final ScrollabilityCache cache = mScrollCache;
13786        if (cache != null) {
13787
13788            int state = cache.state;
13789
13790            if (state == ScrollabilityCache.OFF) {
13791                return;
13792            }
13793
13794            boolean invalidate = false;
13795
13796            if (state == ScrollabilityCache.FADING) {
13797                // We're fading -- get our fade interpolation
13798                if (cache.interpolatorValues == null) {
13799                    cache.interpolatorValues = new float[1];
13800                }
13801
13802                float[] values = cache.interpolatorValues;
13803
13804                // Stops the animation if we're done
13805                if (cache.scrollBarInterpolator.timeToValues(values) ==
13806                        Interpolator.Result.FREEZE_END) {
13807                    cache.state = ScrollabilityCache.OFF;
13808                } else {
13809                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
13810                }
13811
13812                // This will make the scroll bars inval themselves after
13813                // drawing. We only want this when we're fading so that
13814                // we prevent excessive redraws
13815                invalidate = true;
13816            } else {
13817                // We're just on -- but we may have been fading before so
13818                // reset alpha
13819                cache.scrollBar.mutate().setAlpha(255);
13820            }
13821
13822
13823            final int viewFlags = mViewFlags;
13824
13825            final boolean drawHorizontalScrollBar =
13826                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13827            final boolean drawVerticalScrollBar =
13828                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
13829                && !isVerticalScrollBarHidden();
13830
13831            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
13832                final int width = mRight - mLeft;
13833                final int height = mBottom - mTop;
13834
13835                final ScrollBarDrawable scrollBar = cache.scrollBar;
13836
13837                final int scrollX = mScrollX;
13838                final int scrollY = mScrollY;
13839                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
13840
13841                int left;
13842                int top;
13843                int right;
13844                int bottom;
13845
13846                if (drawHorizontalScrollBar) {
13847                    int size = scrollBar.getSize(false);
13848                    if (size <= 0) {
13849                        size = cache.scrollBarSize;
13850                    }
13851
13852                    scrollBar.setParameters(computeHorizontalScrollRange(),
13853                                            computeHorizontalScrollOffset(),
13854                                            computeHorizontalScrollExtent(), false);
13855                    final int verticalScrollBarGap = drawVerticalScrollBar ?
13856                            getVerticalScrollbarWidth() : 0;
13857                    top = scrollY + height - size - (mUserPaddingBottom & inside);
13858                    left = scrollX + (mPaddingLeft & inside);
13859                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
13860                    bottom = top + size;
13861                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
13862                    if (invalidate) {
13863                        invalidate(left, top, right, bottom);
13864                    }
13865                }
13866
13867                if (drawVerticalScrollBar) {
13868                    int size = scrollBar.getSize(true);
13869                    if (size <= 0) {
13870                        size = cache.scrollBarSize;
13871                    }
13872
13873                    scrollBar.setParameters(computeVerticalScrollRange(),
13874                                            computeVerticalScrollOffset(),
13875                                            computeVerticalScrollExtent(), true);
13876                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
13877                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
13878                        verticalScrollbarPosition = isLayoutRtl() ?
13879                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
13880                    }
13881                    switch (verticalScrollbarPosition) {
13882                        default:
13883                        case SCROLLBAR_POSITION_RIGHT:
13884                            left = scrollX + width - size - (mUserPaddingRight & inside);
13885                            break;
13886                        case SCROLLBAR_POSITION_LEFT:
13887                            left = scrollX + (mUserPaddingLeft & inside);
13888                            break;
13889                    }
13890                    top = scrollY + (mPaddingTop & inside);
13891                    right = left + size;
13892                    bottom = scrollY + height - (mUserPaddingBottom & inside);
13893                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
13894                    if (invalidate) {
13895                        invalidate(left, top, right, bottom);
13896                    }
13897                }
13898            }
13899        }
13900    }
13901
13902    /**
13903     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
13904     * FastScroller is visible.
13905     * @return whether to temporarily hide the vertical scrollbar
13906     * @hide
13907     */
13908    protected boolean isVerticalScrollBarHidden() {
13909        return false;
13910    }
13911
13912    /**
13913     * <p>Draw the horizontal scrollbar if
13914     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
13915     *
13916     * @param canvas the canvas on which to draw the scrollbar
13917     * @param scrollBar the scrollbar's drawable
13918     *
13919     * @see #isHorizontalScrollBarEnabled()
13920     * @see #computeHorizontalScrollRange()
13921     * @see #computeHorizontalScrollExtent()
13922     * @see #computeHorizontalScrollOffset()
13923     * @see android.widget.ScrollBarDrawable
13924     * @hide
13925     */
13926    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
13927            int l, int t, int r, int b) {
13928        scrollBar.setBounds(l, t, r, b);
13929        scrollBar.draw(canvas);
13930    }
13931
13932    /**
13933     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
13934     * returns true.</p>
13935     *
13936     * @param canvas the canvas on which to draw the scrollbar
13937     * @param scrollBar the scrollbar's drawable
13938     *
13939     * @see #isVerticalScrollBarEnabled()
13940     * @see #computeVerticalScrollRange()
13941     * @see #computeVerticalScrollExtent()
13942     * @see #computeVerticalScrollOffset()
13943     * @see android.widget.ScrollBarDrawable
13944     * @hide
13945     */
13946    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
13947            int l, int t, int r, int b) {
13948        scrollBar.setBounds(l, t, r, b);
13949        scrollBar.draw(canvas);
13950    }
13951
13952    /**
13953     * Implement this to do your drawing.
13954     *
13955     * @param canvas the canvas on which the background will be drawn
13956     */
13957    protected void onDraw(Canvas canvas) {
13958    }
13959
13960    /*
13961     * Caller is responsible for calling requestLayout if necessary.
13962     * (This allows addViewInLayout to not request a new layout.)
13963     */
13964    void assignParent(ViewParent parent) {
13965        if (mParent == null) {
13966            mParent = parent;
13967        } else if (parent == null) {
13968            mParent = null;
13969        } else {
13970            throw new RuntimeException("view " + this + " being added, but"
13971                    + " it already has a parent");
13972        }
13973    }
13974
13975    /**
13976     * This is called when the view is attached to a window.  At this point it
13977     * has a Surface and will start drawing.  Note that this function is
13978     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
13979     * however it may be called any time before the first onDraw -- including
13980     * before or after {@link #onMeasure(int, int)}.
13981     *
13982     * @see #onDetachedFromWindow()
13983     */
13984    @CallSuper
13985    protected void onAttachedToWindow() {
13986        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
13987            mParent.requestTransparentRegion(this);
13988        }
13989
13990        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13991
13992        jumpDrawablesToCurrentState();
13993
13994        resetSubtreeAccessibilityStateChanged();
13995
13996        // rebuild, since Outline not maintained while View is detached
13997        rebuildOutline();
13998
13999        if (isFocused()) {
14000            InputMethodManager imm = InputMethodManager.peekInstance();
14001            if (imm != null) {
14002                imm.focusIn(this);
14003            }
14004        }
14005    }
14006
14007    /**
14008     * Resolve all RTL related properties.
14009     *
14010     * @return true if resolution of RTL properties has been done
14011     *
14012     * @hide
14013     */
14014    public boolean resolveRtlPropertiesIfNeeded() {
14015        if (!needRtlPropertiesResolution()) return false;
14016
14017        // Order is important here: LayoutDirection MUST be resolved first
14018        if (!isLayoutDirectionResolved()) {
14019            resolveLayoutDirection();
14020            resolveLayoutParams();
14021        }
14022        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
14023        if (!isTextDirectionResolved()) {
14024            resolveTextDirection();
14025        }
14026        if (!isTextAlignmentResolved()) {
14027            resolveTextAlignment();
14028        }
14029        // Should resolve Drawables before Padding because we need the layout direction of the
14030        // Drawable to correctly resolve Padding.
14031        if (!areDrawablesResolved()) {
14032            resolveDrawables();
14033        }
14034        if (!isPaddingResolved()) {
14035            resolvePadding();
14036        }
14037        onRtlPropertiesChanged(getLayoutDirection());
14038        return true;
14039    }
14040
14041    /**
14042     * Reset resolution of all RTL related properties.
14043     *
14044     * @hide
14045     */
14046    public void resetRtlProperties() {
14047        resetResolvedLayoutDirection();
14048        resetResolvedTextDirection();
14049        resetResolvedTextAlignment();
14050        resetResolvedPadding();
14051        resetResolvedDrawables();
14052    }
14053
14054    /**
14055     * @see #onScreenStateChanged(int)
14056     */
14057    void dispatchScreenStateChanged(int screenState) {
14058        onScreenStateChanged(screenState);
14059    }
14060
14061    /**
14062     * This method is called whenever the state of the screen this view is
14063     * attached to changes. A state change will usually occurs when the screen
14064     * turns on or off (whether it happens automatically or the user does it
14065     * manually.)
14066     *
14067     * @param screenState The new state of the screen. Can be either
14068     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
14069     */
14070    public void onScreenStateChanged(int screenState) {
14071    }
14072
14073    /**
14074     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
14075     */
14076    private boolean hasRtlSupport() {
14077        return mContext.getApplicationInfo().hasRtlSupport();
14078    }
14079
14080    /**
14081     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
14082     * RTL not supported)
14083     */
14084    private boolean isRtlCompatibilityMode() {
14085        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
14086        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
14087    }
14088
14089    /**
14090     * @return true if RTL properties need resolution.
14091     *
14092     */
14093    private boolean needRtlPropertiesResolution() {
14094        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
14095    }
14096
14097    /**
14098     * Called when any RTL property (layout direction or text direction or text alignment) has
14099     * been changed.
14100     *
14101     * Subclasses need to override this method to take care of cached information that depends on the
14102     * resolved layout direction, or to inform child views that inherit their layout direction.
14103     *
14104     * The default implementation does nothing.
14105     *
14106     * @param layoutDirection the direction of the layout
14107     *
14108     * @see #LAYOUT_DIRECTION_LTR
14109     * @see #LAYOUT_DIRECTION_RTL
14110     */
14111    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
14112    }
14113
14114    /**
14115     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
14116     * that the parent directionality can and will be resolved before its children.
14117     *
14118     * @return true if resolution has been done, false otherwise.
14119     *
14120     * @hide
14121     */
14122    public boolean resolveLayoutDirection() {
14123        // Clear any previous layout direction resolution
14124        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14125
14126        if (hasRtlSupport()) {
14127            // Set resolved depending on layout direction
14128            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
14129                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
14130                case LAYOUT_DIRECTION_INHERIT:
14131                    // We cannot resolve yet. LTR is by default and let the resolution happen again
14132                    // later to get the correct resolved value
14133                    if (!canResolveLayoutDirection()) return false;
14134
14135                    // Parent has not yet resolved, LTR is still the default
14136                    try {
14137                        if (!mParent.isLayoutDirectionResolved()) return false;
14138
14139                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14140                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14141                        }
14142                    } catch (AbstractMethodError e) {
14143                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14144                                " does not fully implement ViewParent", e);
14145                    }
14146                    break;
14147                case LAYOUT_DIRECTION_RTL:
14148                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14149                    break;
14150                case LAYOUT_DIRECTION_LOCALE:
14151                    if((LAYOUT_DIRECTION_RTL ==
14152                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
14153                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14154                    }
14155                    break;
14156                default:
14157                    // Nothing to do, LTR by default
14158            }
14159        }
14160
14161        // Set to resolved
14162        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14163        return true;
14164    }
14165
14166    /**
14167     * Check if layout direction resolution can be done.
14168     *
14169     * @return true if layout direction resolution can be done otherwise return false.
14170     */
14171    public boolean canResolveLayoutDirection() {
14172        switch (getRawLayoutDirection()) {
14173            case LAYOUT_DIRECTION_INHERIT:
14174                if (mParent != null) {
14175                    try {
14176                        return mParent.canResolveLayoutDirection();
14177                    } catch (AbstractMethodError e) {
14178                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14179                                " does not fully implement ViewParent", e);
14180                    }
14181                }
14182                return false;
14183
14184            default:
14185                return true;
14186        }
14187    }
14188
14189    /**
14190     * Reset the resolved layout direction. Layout direction will be resolved during a call to
14191     * {@link #onMeasure(int, int)}.
14192     *
14193     * @hide
14194     */
14195    public void resetResolvedLayoutDirection() {
14196        // Reset the current resolved bits
14197        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14198    }
14199
14200    /**
14201     * @return true if the layout direction is inherited.
14202     *
14203     * @hide
14204     */
14205    public boolean isLayoutDirectionInherited() {
14206        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
14207    }
14208
14209    /**
14210     * @return true if layout direction has been resolved.
14211     */
14212    public boolean isLayoutDirectionResolved() {
14213        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14214    }
14215
14216    /**
14217     * Return if padding has been resolved
14218     *
14219     * @hide
14220     */
14221    boolean isPaddingResolved() {
14222        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
14223    }
14224
14225    /**
14226     * Resolves padding depending on layout direction, if applicable, and
14227     * recomputes internal padding values to adjust for scroll bars.
14228     *
14229     * @hide
14230     */
14231    public void resolvePadding() {
14232        final int resolvedLayoutDirection = getLayoutDirection();
14233
14234        if (!isRtlCompatibilityMode()) {
14235            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
14236            // If start / end padding are defined, they will be resolved (hence overriding) to
14237            // left / right or right / left depending on the resolved layout direction.
14238            // If start / end padding are not defined, use the left / right ones.
14239            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
14240                Rect padding = sThreadLocal.get();
14241                if (padding == null) {
14242                    padding = new Rect();
14243                    sThreadLocal.set(padding);
14244                }
14245                mBackground.getPadding(padding);
14246                if (!mLeftPaddingDefined) {
14247                    mUserPaddingLeftInitial = padding.left;
14248                }
14249                if (!mRightPaddingDefined) {
14250                    mUserPaddingRightInitial = padding.right;
14251                }
14252            }
14253            switch (resolvedLayoutDirection) {
14254                case LAYOUT_DIRECTION_RTL:
14255                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14256                        mUserPaddingRight = mUserPaddingStart;
14257                    } else {
14258                        mUserPaddingRight = mUserPaddingRightInitial;
14259                    }
14260                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14261                        mUserPaddingLeft = mUserPaddingEnd;
14262                    } else {
14263                        mUserPaddingLeft = mUserPaddingLeftInitial;
14264                    }
14265                    break;
14266                case LAYOUT_DIRECTION_LTR:
14267                default:
14268                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14269                        mUserPaddingLeft = mUserPaddingStart;
14270                    } else {
14271                        mUserPaddingLeft = mUserPaddingLeftInitial;
14272                    }
14273                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14274                        mUserPaddingRight = mUserPaddingEnd;
14275                    } else {
14276                        mUserPaddingRight = mUserPaddingRightInitial;
14277                    }
14278            }
14279
14280            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
14281        }
14282
14283        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14284        onRtlPropertiesChanged(resolvedLayoutDirection);
14285
14286        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
14287    }
14288
14289    /**
14290     * Reset the resolved layout direction.
14291     *
14292     * @hide
14293     */
14294    public void resetResolvedPadding() {
14295        resetResolvedPaddingInternal();
14296    }
14297
14298    /**
14299     * Used when we only want to reset *this* view's padding and not trigger overrides
14300     * in ViewGroup that reset children too.
14301     */
14302    void resetResolvedPaddingInternal() {
14303        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14304    }
14305
14306    /**
14307     * This is called when the view is detached from a window.  At this point it
14308     * no longer has a surface for drawing.
14309     *
14310     * @see #onAttachedToWindow()
14311     */
14312    @CallSuper
14313    protected void onDetachedFromWindow() {
14314    }
14315
14316    /**
14317     * This is a framework-internal mirror of onDetachedFromWindow() that's called
14318     * after onDetachedFromWindow().
14319     *
14320     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
14321     * The super method should be called at the end of the overridden method to ensure
14322     * subclasses are destroyed first
14323     *
14324     * @hide
14325     */
14326    @CallSuper
14327    protected void onDetachedFromWindowInternal() {
14328        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
14329        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14330
14331        removeUnsetPressCallback();
14332        removeLongPressCallback();
14333        removePerformClickCallback();
14334        removeSendViewScrolledAccessibilityEventCallback();
14335        stopNestedScroll();
14336
14337        // Anything that started animating right before detach should already
14338        // be in its final state when re-attached.
14339        jumpDrawablesToCurrentState();
14340
14341        destroyDrawingCache();
14342
14343        cleanupDraw();
14344        mCurrentAnimation = null;
14345    }
14346
14347    private void cleanupDraw() {
14348        resetDisplayList();
14349        if (mAttachInfo != null) {
14350            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
14351        }
14352    }
14353
14354    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
14355    }
14356
14357    /**
14358     * @return The number of times this view has been attached to a window
14359     */
14360    protected int getWindowAttachCount() {
14361        return mWindowAttachCount;
14362    }
14363
14364    /**
14365     * Retrieve a unique token identifying the window this view is attached to.
14366     * @return Return the window's token for use in
14367     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
14368     */
14369    public IBinder getWindowToken() {
14370        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
14371    }
14372
14373    /**
14374     * Retrieve the {@link WindowId} for the window this view is
14375     * currently attached to.
14376     */
14377    public WindowId getWindowId() {
14378        if (mAttachInfo == null) {
14379            return null;
14380        }
14381        if (mAttachInfo.mWindowId == null) {
14382            try {
14383                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
14384                        mAttachInfo.mWindowToken);
14385                mAttachInfo.mWindowId = new WindowId(
14386                        mAttachInfo.mIWindowId);
14387            } catch (RemoteException e) {
14388            }
14389        }
14390        return mAttachInfo.mWindowId;
14391    }
14392
14393    /**
14394     * Retrieve a unique token identifying the top-level "real" window of
14395     * the window that this view is attached to.  That is, this is like
14396     * {@link #getWindowToken}, except if the window this view in is a panel
14397     * window (attached to another containing window), then the token of
14398     * the containing window is returned instead.
14399     *
14400     * @return Returns the associated window token, either
14401     * {@link #getWindowToken()} or the containing window's token.
14402     */
14403    public IBinder getApplicationWindowToken() {
14404        AttachInfo ai = mAttachInfo;
14405        if (ai != null) {
14406            IBinder appWindowToken = ai.mPanelParentWindowToken;
14407            if (appWindowToken == null) {
14408                appWindowToken = ai.mWindowToken;
14409            }
14410            return appWindowToken;
14411        }
14412        return null;
14413    }
14414
14415    /**
14416     * Gets the logical display to which the view's window has been attached.
14417     *
14418     * @return The logical display, or null if the view is not currently attached to a window.
14419     */
14420    public Display getDisplay() {
14421        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
14422    }
14423
14424    /**
14425     * Retrieve private session object this view hierarchy is using to
14426     * communicate with the window manager.
14427     * @return the session object to communicate with the window manager
14428     */
14429    /*package*/ IWindowSession getWindowSession() {
14430        return mAttachInfo != null ? mAttachInfo.mSession : null;
14431    }
14432
14433    /**
14434     * Return the visibility value of the least visible component passed.
14435     */
14436    int combineVisibility(int vis1, int vis2) {
14437        // This works because VISIBLE < INVISIBLE < GONE.
14438        return Math.max(vis1, vis2);
14439    }
14440
14441    /**
14442     * @param info the {@link android.view.View.AttachInfo} to associated with
14443     *        this view
14444     */
14445    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
14446        //System.out.println("Attached! " + this);
14447        mAttachInfo = info;
14448        if (mOverlay != null) {
14449            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
14450        }
14451        mWindowAttachCount++;
14452        // We will need to evaluate the drawable state at least once.
14453        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14454        if (mFloatingTreeObserver != null) {
14455            info.mTreeObserver.merge(mFloatingTreeObserver);
14456            mFloatingTreeObserver = null;
14457        }
14458        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
14459            mAttachInfo.mScrollContainers.add(this);
14460            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
14461        }
14462        performCollectViewAttributes(mAttachInfo, visibility);
14463        onAttachedToWindow();
14464
14465        ListenerInfo li = mListenerInfo;
14466        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14467                li != null ? li.mOnAttachStateChangeListeners : null;
14468        if (listeners != null && listeners.size() > 0) {
14469            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14470            // perform the dispatching. The iterator is a safe guard against listeners that
14471            // could mutate the list by calling the various add/remove methods. This prevents
14472            // the array from being modified while we iterate it.
14473            for (OnAttachStateChangeListener listener : listeners) {
14474                listener.onViewAttachedToWindow(this);
14475            }
14476        }
14477
14478        int vis = info.mWindowVisibility;
14479        if (vis != GONE) {
14480            onWindowVisibilityChanged(vis);
14481        }
14482
14483        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
14484        // As all views in the subtree will already receive dispatchAttachedToWindow
14485        // traversing the subtree again here is not desired.
14486        onVisibilityChanged(this, visibility);
14487
14488        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
14489            // If nobody has evaluated the drawable state yet, then do it now.
14490            refreshDrawableState();
14491        }
14492        needGlobalAttributesUpdate(false);
14493    }
14494
14495    void dispatchDetachedFromWindow() {
14496        AttachInfo info = mAttachInfo;
14497        if (info != null) {
14498            int vis = info.mWindowVisibility;
14499            if (vis != GONE) {
14500                onWindowVisibilityChanged(GONE);
14501            }
14502        }
14503
14504        onDetachedFromWindow();
14505        onDetachedFromWindowInternal();
14506
14507        ListenerInfo li = mListenerInfo;
14508        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14509                li != null ? li.mOnAttachStateChangeListeners : null;
14510        if (listeners != null && listeners.size() > 0) {
14511            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14512            // perform the dispatching. The iterator is a safe guard against listeners that
14513            // could mutate the list by calling the various add/remove methods. This prevents
14514            // the array from being modified while we iterate it.
14515            for (OnAttachStateChangeListener listener : listeners) {
14516                listener.onViewDetachedFromWindow(this);
14517            }
14518        }
14519
14520        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
14521            mAttachInfo.mScrollContainers.remove(this);
14522            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
14523        }
14524
14525        mAttachInfo = null;
14526        if (mOverlay != null) {
14527            mOverlay.getOverlayView().dispatchDetachedFromWindow();
14528        }
14529    }
14530
14531    /**
14532     * Cancel any deferred high-level input events that were previously posted to the event queue.
14533     *
14534     * <p>Many views post high-level events such as click handlers to the event queue
14535     * to run deferred in order to preserve a desired user experience - clearing visible
14536     * pressed states before executing, etc. This method will abort any events of this nature
14537     * that are currently in flight.</p>
14538     *
14539     * <p>Custom views that generate their own high-level deferred input events should override
14540     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14541     *
14542     * <p>This will also cancel pending input events for any child views.</p>
14543     *
14544     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14545     * This will not impact newer events posted after this call that may occur as a result of
14546     * lower-level input events still waiting in the queue. If you are trying to prevent
14547     * double-submitted  events for the duration of some sort of asynchronous transaction
14548     * you should also take other steps to protect against unexpected double inputs e.g. calling
14549     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14550     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14551     */
14552    public final void cancelPendingInputEvents() {
14553        dispatchCancelPendingInputEvents();
14554    }
14555
14556    /**
14557     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14558     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14559     */
14560    void dispatchCancelPendingInputEvents() {
14561        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14562        onCancelPendingInputEvents();
14563        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14564            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14565                    " did not call through to super.onCancelPendingInputEvents()");
14566        }
14567    }
14568
14569    /**
14570     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14571     * a parent view.
14572     *
14573     * <p>This method is responsible for removing any pending high-level input events that were
14574     * posted to the event queue to run later. Custom view classes that post their own deferred
14575     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14576     * {@link android.os.Handler} should override this method, call
14577     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14578     * </p>
14579     */
14580    public void onCancelPendingInputEvents() {
14581        removePerformClickCallback();
14582        cancelLongPress();
14583        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14584    }
14585
14586    /**
14587     * Store this view hierarchy's frozen state into the given container.
14588     *
14589     * @param container The SparseArray in which to save the view's state.
14590     *
14591     * @see #restoreHierarchyState(android.util.SparseArray)
14592     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14593     * @see #onSaveInstanceState()
14594     */
14595    public void saveHierarchyState(SparseArray<Parcelable> container) {
14596        dispatchSaveInstanceState(container);
14597    }
14598
14599    /**
14600     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
14601     * this view and its children. May be overridden to modify how freezing happens to a
14602     * view's children; for example, some views may want to not store state for their children.
14603     *
14604     * @param container The SparseArray in which to save the view's state.
14605     *
14606     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14607     * @see #saveHierarchyState(android.util.SparseArray)
14608     * @see #onSaveInstanceState()
14609     */
14610    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
14611        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
14612            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14613            Parcelable state = onSaveInstanceState();
14614            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14615                throw new IllegalStateException(
14616                        "Derived class did not call super.onSaveInstanceState()");
14617            }
14618            if (state != null) {
14619                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
14620                // + ": " + state);
14621                container.put(mID, state);
14622            }
14623        }
14624    }
14625
14626    /**
14627     * Hook allowing a view to generate a representation of its internal state
14628     * that can later be used to create a new instance with that same state.
14629     * This state should only contain information that is not persistent or can
14630     * not be reconstructed later. For example, you will never store your
14631     * current position on screen because that will be computed again when a
14632     * new instance of the view is placed in its view hierarchy.
14633     * <p>
14634     * Some examples of things you may store here: the current cursor position
14635     * in a text view (but usually not the text itself since that is stored in a
14636     * content provider or other persistent storage), the currently selected
14637     * item in a list view.
14638     *
14639     * @return Returns a Parcelable object containing the view's current dynamic
14640     *         state, or null if there is nothing interesting to save. The
14641     *         default implementation returns null.
14642     * @see #onRestoreInstanceState(android.os.Parcelable)
14643     * @see #saveHierarchyState(android.util.SparseArray)
14644     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14645     * @see #setSaveEnabled(boolean)
14646     */
14647    @CallSuper
14648    protected Parcelable onSaveInstanceState() {
14649        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14650        if (mStartActivityRequestWho != null) {
14651            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
14652            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
14653            return state;
14654        }
14655        return BaseSavedState.EMPTY_STATE;
14656    }
14657
14658    /**
14659     * Restore this view hierarchy's frozen state from the given container.
14660     *
14661     * @param container The SparseArray which holds previously frozen states.
14662     *
14663     * @see #saveHierarchyState(android.util.SparseArray)
14664     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14665     * @see #onRestoreInstanceState(android.os.Parcelable)
14666     */
14667    public void restoreHierarchyState(SparseArray<Parcelable> container) {
14668        dispatchRestoreInstanceState(container);
14669    }
14670
14671    /**
14672     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
14673     * state for this view and its children. May be overridden to modify how restoring
14674     * happens to a view's children; for example, some views may want to not store state
14675     * for their children.
14676     *
14677     * @param container The SparseArray which holds previously saved state.
14678     *
14679     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14680     * @see #restoreHierarchyState(android.util.SparseArray)
14681     * @see #onRestoreInstanceState(android.os.Parcelable)
14682     */
14683    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
14684        if (mID != NO_ID) {
14685            Parcelable state = container.get(mID);
14686            if (state != null) {
14687                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
14688                // + ": " + state);
14689                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14690                onRestoreInstanceState(state);
14691                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14692                    throw new IllegalStateException(
14693                            "Derived class did not call super.onRestoreInstanceState()");
14694                }
14695            }
14696        }
14697    }
14698
14699    /**
14700     * Hook allowing a view to re-apply a representation of its internal state that had previously
14701     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
14702     * null state.
14703     *
14704     * @param state The frozen state that had previously been returned by
14705     *        {@link #onSaveInstanceState}.
14706     *
14707     * @see #onSaveInstanceState()
14708     * @see #restoreHierarchyState(android.util.SparseArray)
14709     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14710     */
14711    @CallSuper
14712    protected void onRestoreInstanceState(Parcelable state) {
14713        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14714        if (state != null && !(state instanceof AbsSavedState)) {
14715            throw new IllegalArgumentException("Wrong state class, expecting View State but "
14716                    + "received " + state.getClass().toString() + " instead. This usually happens "
14717                    + "when two views of different type have the same id in the same hierarchy. "
14718                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
14719                    + "other views do not use the same id.");
14720        }
14721        if (state != null && state instanceof BaseSavedState) {
14722            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
14723        }
14724    }
14725
14726    /**
14727     * <p>Return the time at which the drawing of the view hierarchy started.</p>
14728     *
14729     * @return the drawing start time in milliseconds
14730     */
14731    public long getDrawingTime() {
14732        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
14733    }
14734
14735    /**
14736     * <p>Enables or disables the duplication of the parent's state into this view. When
14737     * duplication is enabled, this view gets its drawable state from its parent rather
14738     * than from its own internal properties.</p>
14739     *
14740     * <p>Note: in the current implementation, setting this property to true after the
14741     * view was added to a ViewGroup might have no effect at all. This property should
14742     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
14743     *
14744     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
14745     * property is enabled, an exception will be thrown.</p>
14746     *
14747     * <p>Note: if the child view uses and updates additional states which are unknown to the
14748     * parent, these states should not be affected by this method.</p>
14749     *
14750     * @param enabled True to enable duplication of the parent's drawable state, false
14751     *                to disable it.
14752     *
14753     * @see #getDrawableState()
14754     * @see #isDuplicateParentStateEnabled()
14755     */
14756    public void setDuplicateParentStateEnabled(boolean enabled) {
14757        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
14758    }
14759
14760    /**
14761     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
14762     *
14763     * @return True if this view's drawable state is duplicated from the parent,
14764     *         false otherwise
14765     *
14766     * @see #getDrawableState()
14767     * @see #setDuplicateParentStateEnabled(boolean)
14768     */
14769    public boolean isDuplicateParentStateEnabled() {
14770        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
14771    }
14772
14773    /**
14774     * <p>Specifies the type of layer backing this view. The layer can be
14775     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14776     * {@link #LAYER_TYPE_HARDWARE}.</p>
14777     *
14778     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14779     * instance that controls how the layer is composed on screen. The following
14780     * properties of the paint are taken into account when composing the layer:</p>
14781     * <ul>
14782     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14783     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14784     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14785     * </ul>
14786     *
14787     * <p>If this view has an alpha value set to < 1.0 by calling
14788     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
14789     * by this view's alpha value.</p>
14790     *
14791     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
14792     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
14793     * for more information on when and how to use layers.</p>
14794     *
14795     * @param layerType The type of layer to use with this view, must be one of
14796     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14797     *        {@link #LAYER_TYPE_HARDWARE}
14798     * @param paint The paint used to compose the layer. This argument is optional
14799     *        and can be null. It is ignored when the layer type is
14800     *        {@link #LAYER_TYPE_NONE}
14801     *
14802     * @see #getLayerType()
14803     * @see #LAYER_TYPE_NONE
14804     * @see #LAYER_TYPE_SOFTWARE
14805     * @see #LAYER_TYPE_HARDWARE
14806     * @see #setAlpha(float)
14807     *
14808     * @attr ref android.R.styleable#View_layerType
14809     */
14810    public void setLayerType(int layerType, Paint paint) {
14811        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
14812            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
14813                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
14814        }
14815
14816        boolean typeChanged = mRenderNode.setLayerType(layerType);
14817
14818        if (!typeChanged) {
14819            setLayerPaint(paint);
14820            return;
14821        }
14822
14823        // Destroy any previous software drawing cache if needed
14824        if (mLayerType == LAYER_TYPE_SOFTWARE) {
14825            destroyDrawingCache();
14826        }
14827
14828        mLayerType = layerType;
14829        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
14830        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
14831        mRenderNode.setLayerPaint(mLayerPaint);
14832
14833        // draw() behaves differently if we are on a layer, so we need to
14834        // invalidate() here
14835        invalidateParentCaches();
14836        invalidate(true);
14837    }
14838
14839    /**
14840     * Updates the {@link Paint} object used with the current layer (used only if the current
14841     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
14842     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
14843     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
14844     * ensure that the view gets redrawn immediately.
14845     *
14846     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14847     * instance that controls how the layer is composed on screen. The following
14848     * properties of the paint are taken into account when composing the layer:</p>
14849     * <ul>
14850     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14851     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14852     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14853     * </ul>
14854     *
14855     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
14856     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
14857     *
14858     * @param paint The paint used to compose the layer. This argument is optional
14859     *        and can be null. It is ignored when the layer type is
14860     *        {@link #LAYER_TYPE_NONE}
14861     *
14862     * @see #setLayerType(int, android.graphics.Paint)
14863     */
14864    public void setLayerPaint(Paint paint) {
14865        int layerType = getLayerType();
14866        if (layerType != LAYER_TYPE_NONE) {
14867            mLayerPaint = paint == null ? new Paint() : paint;
14868            if (layerType == LAYER_TYPE_HARDWARE) {
14869                if (mRenderNode.setLayerPaint(mLayerPaint)) {
14870                    invalidateViewProperty(false, false);
14871                }
14872            } else {
14873                invalidate();
14874            }
14875        }
14876    }
14877
14878    /**
14879     * Indicates what type of layer is currently associated with this view. By default
14880     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
14881     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
14882     * for more information on the different types of layers.
14883     *
14884     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14885     *         {@link #LAYER_TYPE_HARDWARE}
14886     *
14887     * @see #setLayerType(int, android.graphics.Paint)
14888     * @see #buildLayer()
14889     * @see #LAYER_TYPE_NONE
14890     * @see #LAYER_TYPE_SOFTWARE
14891     * @see #LAYER_TYPE_HARDWARE
14892     */
14893    public int getLayerType() {
14894        return mLayerType;
14895    }
14896
14897    /**
14898     * Forces this view's layer to be created and this view to be rendered
14899     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
14900     * invoking this method will have no effect.
14901     *
14902     * This method can for instance be used to render a view into its layer before
14903     * starting an animation. If this view is complex, rendering into the layer
14904     * before starting the animation will avoid skipping frames.
14905     *
14906     * @throws IllegalStateException If this view is not attached to a window
14907     *
14908     * @see #setLayerType(int, android.graphics.Paint)
14909     */
14910    public void buildLayer() {
14911        if (mLayerType == LAYER_TYPE_NONE) return;
14912
14913        final AttachInfo attachInfo = mAttachInfo;
14914        if (attachInfo == null) {
14915            throw new IllegalStateException("This view must be attached to a window first");
14916        }
14917
14918        if (getWidth() == 0 || getHeight() == 0) {
14919            return;
14920        }
14921
14922        switch (mLayerType) {
14923            case LAYER_TYPE_HARDWARE:
14924                updateDisplayListIfDirty();
14925                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
14926                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
14927                }
14928                break;
14929            case LAYER_TYPE_SOFTWARE:
14930                buildDrawingCache(true);
14931                break;
14932        }
14933    }
14934
14935    /**
14936     * If this View draws with a HardwareLayer, returns it.
14937     * Otherwise returns null
14938     *
14939     * TODO: Only TextureView uses this, can we eliminate it?
14940     */
14941    HardwareLayer getHardwareLayer() {
14942        return null;
14943    }
14944
14945    /**
14946     * Destroys all hardware rendering resources. This method is invoked
14947     * when the system needs to reclaim resources. Upon execution of this
14948     * method, you should free any OpenGL resources created by the view.
14949     *
14950     * Note: you <strong>must</strong> call
14951     * <code>super.destroyHardwareResources()</code> when overriding
14952     * this method.
14953     *
14954     * @hide
14955     */
14956    @CallSuper
14957    protected void destroyHardwareResources() {
14958        // Although the Layer will be destroyed by RenderNode, we want to release
14959        // the staging display list, which is also a signal to RenderNode that it's
14960        // safe to free its copy of the display list as it knows that we will
14961        // push an updated DisplayList if we try to draw again
14962        resetDisplayList();
14963    }
14964
14965    /**
14966     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
14967     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
14968     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
14969     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
14970     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
14971     * null.</p>
14972     *
14973     * <p>Enabling the drawing cache is similar to
14974     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
14975     * acceleration is turned off. When hardware acceleration is turned on, enabling the
14976     * drawing cache has no effect on rendering because the system uses a different mechanism
14977     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
14978     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
14979     * for information on how to enable software and hardware layers.</p>
14980     *
14981     * <p>This API can be used to manually generate
14982     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
14983     * {@link #getDrawingCache()}.</p>
14984     *
14985     * @param enabled true to enable the drawing cache, false otherwise
14986     *
14987     * @see #isDrawingCacheEnabled()
14988     * @see #getDrawingCache()
14989     * @see #buildDrawingCache()
14990     * @see #setLayerType(int, android.graphics.Paint)
14991     */
14992    public void setDrawingCacheEnabled(boolean enabled) {
14993        mCachingFailed = false;
14994        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
14995    }
14996
14997    /**
14998     * <p>Indicates whether the drawing cache is enabled for this view.</p>
14999     *
15000     * @return true if the drawing cache is enabled
15001     *
15002     * @see #setDrawingCacheEnabled(boolean)
15003     * @see #getDrawingCache()
15004     */
15005    @ViewDebug.ExportedProperty(category = "drawing")
15006    public boolean isDrawingCacheEnabled() {
15007        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
15008    }
15009
15010    /**
15011     * Debugging utility which recursively outputs the dirty state of a view and its
15012     * descendants.
15013     *
15014     * @hide
15015     */
15016    @SuppressWarnings({"UnusedDeclaration"})
15017    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
15018        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
15019                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
15020                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
15021                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
15022        if (clear) {
15023            mPrivateFlags &= clearMask;
15024        }
15025        if (this instanceof ViewGroup) {
15026            ViewGroup parent = (ViewGroup) this;
15027            final int count = parent.getChildCount();
15028            for (int i = 0; i < count; i++) {
15029                final View child = parent.getChildAt(i);
15030                child.outputDirtyFlags(indent + "  ", clear, clearMask);
15031            }
15032        }
15033    }
15034
15035    /**
15036     * This method is used by ViewGroup to cause its children to restore or recreate their
15037     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
15038     * to recreate its own display list, which would happen if it went through the normal
15039     * draw/dispatchDraw mechanisms.
15040     *
15041     * @hide
15042     */
15043    protected void dispatchGetDisplayList() {}
15044
15045    /**
15046     * A view that is not attached or hardware accelerated cannot create a display list.
15047     * This method checks these conditions and returns the appropriate result.
15048     *
15049     * @return true if view has the ability to create a display list, false otherwise.
15050     *
15051     * @hide
15052     */
15053    public boolean canHaveDisplayList() {
15054        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
15055    }
15056
15057    /**
15058     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
15059     * @hide
15060     */
15061    @NonNull
15062    public RenderNode updateDisplayListIfDirty() {
15063        final RenderNode renderNode = mRenderNode;
15064        if (!canHaveDisplayList()) {
15065            // can't populate RenderNode, don't try
15066            return renderNode;
15067        }
15068
15069        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
15070                || !renderNode.isValid()
15071                || (mRecreateDisplayList)) {
15072            // Don't need to recreate the display list, just need to tell our
15073            // children to restore/recreate theirs
15074            if (renderNode.isValid()
15075                    && !mRecreateDisplayList) {
15076                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15077                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15078                dispatchGetDisplayList();
15079
15080                return renderNode; // no work needed
15081            }
15082
15083            // If we got here, we're recreating it. Mark it as such to ensure that
15084            // we copy in child display lists into ours in drawChild()
15085            mRecreateDisplayList = true;
15086
15087            int width = mRight - mLeft;
15088            int height = mBottom - mTop;
15089            int layerType = getLayerType();
15090
15091            final DisplayListCanvas canvas = renderNode.start(width, height);
15092            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
15093
15094            try {
15095                final HardwareLayer layer = getHardwareLayer();
15096                if (layer != null && layer.isValid()) {
15097                    canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
15098                } else if (layerType == LAYER_TYPE_SOFTWARE) {
15099                    buildDrawingCache(true);
15100                    Bitmap cache = getDrawingCache(true);
15101                    if (cache != null) {
15102                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
15103                    }
15104                } else {
15105                    computeScroll();
15106
15107                    canvas.translate(-mScrollX, -mScrollY);
15108                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15109                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15110
15111                    // Fast path for layouts with no backgrounds
15112                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15113                        dispatchDraw(canvas);
15114                        if (mOverlay != null && !mOverlay.isEmpty()) {
15115                            mOverlay.getOverlayView().draw(canvas);
15116                        }
15117                    } else {
15118                        draw(canvas);
15119                    }
15120                }
15121            } finally {
15122                renderNode.end(canvas);
15123                setDisplayListProperties(renderNode);
15124            }
15125        } else {
15126            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15127            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15128        }
15129        return renderNode;
15130    }
15131
15132    private void resetDisplayList() {
15133        if (mRenderNode.isValid()) {
15134            mRenderNode.destroyDisplayListData();
15135        }
15136
15137        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
15138            mBackgroundRenderNode.destroyDisplayListData();
15139        }
15140    }
15141
15142    /**
15143     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
15144     *
15145     * @return A non-scaled bitmap representing this view or null if cache is disabled.
15146     *
15147     * @see #getDrawingCache(boolean)
15148     */
15149    public Bitmap getDrawingCache() {
15150        return getDrawingCache(false);
15151    }
15152
15153    /**
15154     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
15155     * is null when caching is disabled. If caching is enabled and the cache is not ready,
15156     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
15157     * draw from the cache when the cache is enabled. To benefit from the cache, you must
15158     * request the drawing cache by calling this method and draw it on screen if the
15159     * returned bitmap is not null.</p>
15160     *
15161     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15162     * this method will create a bitmap of the same size as this view. Because this bitmap
15163     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15164     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15165     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15166     * size than the view. This implies that your application must be able to handle this
15167     * size.</p>
15168     *
15169     * @param autoScale Indicates whether the generated bitmap should be scaled based on
15170     *        the current density of the screen when the application is in compatibility
15171     *        mode.
15172     *
15173     * @return A bitmap representing this view or null if cache is disabled.
15174     *
15175     * @see #setDrawingCacheEnabled(boolean)
15176     * @see #isDrawingCacheEnabled()
15177     * @see #buildDrawingCache(boolean)
15178     * @see #destroyDrawingCache()
15179     */
15180    public Bitmap getDrawingCache(boolean autoScale) {
15181        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
15182            return null;
15183        }
15184        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
15185            buildDrawingCache(autoScale);
15186        }
15187        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
15188    }
15189
15190    /**
15191     * <p>Frees the resources used by the drawing cache. If you call
15192     * {@link #buildDrawingCache()} manually without calling
15193     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15194     * should cleanup the cache with this method afterwards.</p>
15195     *
15196     * @see #setDrawingCacheEnabled(boolean)
15197     * @see #buildDrawingCache()
15198     * @see #getDrawingCache()
15199     */
15200    public void destroyDrawingCache() {
15201        if (mDrawingCache != null) {
15202            mDrawingCache.recycle();
15203            mDrawingCache = null;
15204        }
15205        if (mUnscaledDrawingCache != null) {
15206            mUnscaledDrawingCache.recycle();
15207            mUnscaledDrawingCache = null;
15208        }
15209    }
15210
15211    /**
15212     * Setting a solid background color for the drawing cache's bitmaps will improve
15213     * performance and memory usage. Note, though that this should only be used if this
15214     * view will always be drawn on top of a solid color.
15215     *
15216     * @param color The background color to use for the drawing cache's bitmap
15217     *
15218     * @see #setDrawingCacheEnabled(boolean)
15219     * @see #buildDrawingCache()
15220     * @see #getDrawingCache()
15221     */
15222    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
15223        if (color != mDrawingCacheBackgroundColor) {
15224            mDrawingCacheBackgroundColor = color;
15225            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15226        }
15227    }
15228
15229    /**
15230     * @see #setDrawingCacheBackgroundColor(int)
15231     *
15232     * @return The background color to used for the drawing cache's bitmap
15233     */
15234    @ColorInt
15235    public int getDrawingCacheBackgroundColor() {
15236        return mDrawingCacheBackgroundColor;
15237    }
15238
15239    /**
15240     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
15241     *
15242     * @see #buildDrawingCache(boolean)
15243     */
15244    public void buildDrawingCache() {
15245        buildDrawingCache(false);
15246    }
15247
15248    /**
15249     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
15250     *
15251     * <p>If you call {@link #buildDrawingCache()} manually without calling
15252     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15253     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
15254     *
15255     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15256     * this method will create a bitmap of the same size as this view. Because this bitmap
15257     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15258     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15259     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15260     * size than the view. This implies that your application must be able to handle this
15261     * size.</p>
15262     *
15263     * <p>You should avoid calling this method when hardware acceleration is enabled. If
15264     * you do not need the drawing cache bitmap, calling this method will increase memory
15265     * usage and cause the view to be rendered in software once, thus negatively impacting
15266     * performance.</p>
15267     *
15268     * @see #getDrawingCache()
15269     * @see #destroyDrawingCache()
15270     */
15271    public void buildDrawingCache(boolean autoScale) {
15272        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
15273                mDrawingCache == null : mUnscaledDrawingCache == null)) {
15274            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
15275                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
15276                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
15277            }
15278            try {
15279                buildDrawingCacheImpl(autoScale);
15280            } finally {
15281                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
15282            }
15283        }
15284    }
15285
15286    /**
15287     * private, internal implementation of buildDrawingCache, used to enable tracing
15288     */
15289    private void buildDrawingCacheImpl(boolean autoScale) {
15290        mCachingFailed = false;
15291
15292        int width = mRight - mLeft;
15293        int height = mBottom - mTop;
15294
15295        final AttachInfo attachInfo = mAttachInfo;
15296        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
15297
15298        if (autoScale && scalingRequired) {
15299            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
15300            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
15301        }
15302
15303        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
15304        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
15305        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
15306
15307        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
15308        final long drawingCacheSize =
15309                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
15310        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
15311            if (width > 0 && height > 0) {
15312                Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
15313                        + projectedBitmapSize + " bytes, only "
15314                        + drawingCacheSize + " available");
15315            }
15316            destroyDrawingCache();
15317            mCachingFailed = true;
15318            return;
15319        }
15320
15321        boolean clear = true;
15322        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
15323
15324        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
15325            Bitmap.Config quality;
15326            if (!opaque) {
15327                // Never pick ARGB_4444 because it looks awful
15328                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
15329                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
15330                    case DRAWING_CACHE_QUALITY_AUTO:
15331                    case DRAWING_CACHE_QUALITY_LOW:
15332                    case DRAWING_CACHE_QUALITY_HIGH:
15333                    default:
15334                        quality = Bitmap.Config.ARGB_8888;
15335                        break;
15336                }
15337            } else {
15338                // Optimization for translucent windows
15339                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
15340                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
15341            }
15342
15343            // Try to cleanup memory
15344            if (bitmap != null) bitmap.recycle();
15345
15346            try {
15347                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15348                        width, height, quality);
15349                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
15350                if (autoScale) {
15351                    mDrawingCache = bitmap;
15352                } else {
15353                    mUnscaledDrawingCache = bitmap;
15354                }
15355                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
15356            } catch (OutOfMemoryError e) {
15357                // If there is not enough memory to create the bitmap cache, just
15358                // ignore the issue as bitmap caches are not required to draw the
15359                // view hierarchy
15360                if (autoScale) {
15361                    mDrawingCache = null;
15362                } else {
15363                    mUnscaledDrawingCache = null;
15364                }
15365                mCachingFailed = true;
15366                return;
15367            }
15368
15369            clear = drawingCacheBackgroundColor != 0;
15370        }
15371
15372        Canvas canvas;
15373        if (attachInfo != null) {
15374            canvas = attachInfo.mCanvas;
15375            if (canvas == null) {
15376                canvas = new Canvas();
15377            }
15378            canvas.setBitmap(bitmap);
15379            // Temporarily clobber the cached Canvas in case one of our children
15380            // is also using a drawing cache. Without this, the children would
15381            // steal the canvas by attaching their own bitmap to it and bad, bad
15382            // thing would happen (invisible views, corrupted drawings, etc.)
15383            attachInfo.mCanvas = null;
15384        } else {
15385            // This case should hopefully never or seldom happen
15386            canvas = new Canvas(bitmap);
15387        }
15388
15389        if (clear) {
15390            bitmap.eraseColor(drawingCacheBackgroundColor);
15391        }
15392
15393        computeScroll();
15394        final int restoreCount = canvas.save();
15395
15396        if (autoScale && scalingRequired) {
15397            final float scale = attachInfo.mApplicationScale;
15398            canvas.scale(scale, scale);
15399        }
15400
15401        canvas.translate(-mScrollX, -mScrollY);
15402
15403        mPrivateFlags |= PFLAG_DRAWN;
15404        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
15405                mLayerType != LAYER_TYPE_NONE) {
15406            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
15407        }
15408
15409        // Fast path for layouts with no backgrounds
15410        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15411            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15412            dispatchDraw(canvas);
15413            if (mOverlay != null && !mOverlay.isEmpty()) {
15414                mOverlay.getOverlayView().draw(canvas);
15415            }
15416        } else {
15417            draw(canvas);
15418        }
15419
15420        canvas.restoreToCount(restoreCount);
15421        canvas.setBitmap(null);
15422
15423        if (attachInfo != null) {
15424            // Restore the cached Canvas for our siblings
15425            attachInfo.mCanvas = canvas;
15426        }
15427    }
15428
15429    /**
15430     * Create a snapshot of the view into a bitmap.  We should probably make
15431     * some form of this public, but should think about the API.
15432     */
15433    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
15434        int width = mRight - mLeft;
15435        int height = mBottom - mTop;
15436
15437        final AttachInfo attachInfo = mAttachInfo;
15438        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
15439        width = (int) ((width * scale) + 0.5f);
15440        height = (int) ((height * scale) + 0.5f);
15441
15442        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15443                width > 0 ? width : 1, height > 0 ? height : 1, quality);
15444        if (bitmap == null) {
15445            throw new OutOfMemoryError();
15446        }
15447
15448        Resources resources = getResources();
15449        if (resources != null) {
15450            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
15451        }
15452
15453        Canvas canvas;
15454        if (attachInfo != null) {
15455            canvas = attachInfo.mCanvas;
15456            if (canvas == null) {
15457                canvas = new Canvas();
15458            }
15459            canvas.setBitmap(bitmap);
15460            // Temporarily clobber the cached Canvas in case one of our children
15461            // is also using a drawing cache. Without this, the children would
15462            // steal the canvas by attaching their own bitmap to it and bad, bad
15463            // things would happen (invisible views, corrupted drawings, etc.)
15464            attachInfo.mCanvas = null;
15465        } else {
15466            // This case should hopefully never or seldom happen
15467            canvas = new Canvas(bitmap);
15468        }
15469
15470        if ((backgroundColor & 0xff000000) != 0) {
15471            bitmap.eraseColor(backgroundColor);
15472        }
15473
15474        computeScroll();
15475        final int restoreCount = canvas.save();
15476        canvas.scale(scale, scale);
15477        canvas.translate(-mScrollX, -mScrollY);
15478
15479        // Temporarily remove the dirty mask
15480        int flags = mPrivateFlags;
15481        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15482
15483        // Fast path for layouts with no backgrounds
15484        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15485            dispatchDraw(canvas);
15486            if (mOverlay != null && !mOverlay.isEmpty()) {
15487                mOverlay.getOverlayView().draw(canvas);
15488            }
15489        } else {
15490            draw(canvas);
15491        }
15492
15493        mPrivateFlags = flags;
15494
15495        canvas.restoreToCount(restoreCount);
15496        canvas.setBitmap(null);
15497
15498        if (attachInfo != null) {
15499            // Restore the cached Canvas for our siblings
15500            attachInfo.mCanvas = canvas;
15501        }
15502
15503        return bitmap;
15504    }
15505
15506    /**
15507     * Indicates whether this View is currently in edit mode. A View is usually
15508     * in edit mode when displayed within a developer tool. For instance, if
15509     * this View is being drawn by a visual user interface builder, this method
15510     * should return true.
15511     *
15512     * Subclasses should check the return value of this method to provide
15513     * different behaviors if their normal behavior might interfere with the
15514     * host environment. For instance: the class spawns a thread in its
15515     * constructor, the drawing code relies on device-specific features, etc.
15516     *
15517     * This method is usually checked in the drawing code of custom widgets.
15518     *
15519     * @return True if this View is in edit mode, false otherwise.
15520     */
15521    public boolean isInEditMode() {
15522        return false;
15523    }
15524
15525    /**
15526     * If the View draws content inside its padding and enables fading edges,
15527     * it needs to support padding offsets. Padding offsets are added to the
15528     * fading edges to extend the length of the fade so that it covers pixels
15529     * drawn inside the padding.
15530     *
15531     * Subclasses of this class should override this method if they need
15532     * to draw content inside the padding.
15533     *
15534     * @return True if padding offset must be applied, false otherwise.
15535     *
15536     * @see #getLeftPaddingOffset()
15537     * @see #getRightPaddingOffset()
15538     * @see #getTopPaddingOffset()
15539     * @see #getBottomPaddingOffset()
15540     *
15541     * @since CURRENT
15542     */
15543    protected boolean isPaddingOffsetRequired() {
15544        return false;
15545    }
15546
15547    /**
15548     * Amount by which to extend the left fading region. Called only when
15549     * {@link #isPaddingOffsetRequired()} returns true.
15550     *
15551     * @return The left padding offset in pixels.
15552     *
15553     * @see #isPaddingOffsetRequired()
15554     *
15555     * @since CURRENT
15556     */
15557    protected int getLeftPaddingOffset() {
15558        return 0;
15559    }
15560
15561    /**
15562     * Amount by which to extend the right fading region. Called only when
15563     * {@link #isPaddingOffsetRequired()} returns true.
15564     *
15565     * @return The right padding offset in pixels.
15566     *
15567     * @see #isPaddingOffsetRequired()
15568     *
15569     * @since CURRENT
15570     */
15571    protected int getRightPaddingOffset() {
15572        return 0;
15573    }
15574
15575    /**
15576     * Amount by which to extend the top fading region. Called only when
15577     * {@link #isPaddingOffsetRequired()} returns true.
15578     *
15579     * @return The top padding offset in pixels.
15580     *
15581     * @see #isPaddingOffsetRequired()
15582     *
15583     * @since CURRENT
15584     */
15585    protected int getTopPaddingOffset() {
15586        return 0;
15587    }
15588
15589    /**
15590     * Amount by which to extend the bottom fading region. Called only when
15591     * {@link #isPaddingOffsetRequired()} returns true.
15592     *
15593     * @return The bottom padding offset in pixels.
15594     *
15595     * @see #isPaddingOffsetRequired()
15596     *
15597     * @since CURRENT
15598     */
15599    protected int getBottomPaddingOffset() {
15600        return 0;
15601    }
15602
15603    /**
15604     * @hide
15605     * @param offsetRequired
15606     */
15607    protected int getFadeTop(boolean offsetRequired) {
15608        int top = mPaddingTop;
15609        if (offsetRequired) top += getTopPaddingOffset();
15610        return top;
15611    }
15612
15613    /**
15614     * @hide
15615     * @param offsetRequired
15616     */
15617    protected int getFadeHeight(boolean offsetRequired) {
15618        int padding = mPaddingTop;
15619        if (offsetRequired) padding += getTopPaddingOffset();
15620        return mBottom - mTop - mPaddingBottom - padding;
15621    }
15622
15623    /**
15624     * <p>Indicates whether this view is attached to a hardware accelerated
15625     * window or not.</p>
15626     *
15627     * <p>Even if this method returns true, it does not mean that every call
15628     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
15629     * accelerated {@link android.graphics.Canvas}. For instance, if this view
15630     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
15631     * window is hardware accelerated,
15632     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
15633     * return false, and this method will return true.</p>
15634     *
15635     * @return True if the view is attached to a window and the window is
15636     *         hardware accelerated; false in any other case.
15637     */
15638    @ViewDebug.ExportedProperty(category = "drawing")
15639    public boolean isHardwareAccelerated() {
15640        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15641    }
15642
15643    /**
15644     * Sets a rectangular area on this view to which the view will be clipped
15645     * when it is drawn. Setting the value to null will remove the clip bounds
15646     * and the view will draw normally, using its full bounds.
15647     *
15648     * @param clipBounds The rectangular area, in the local coordinates of
15649     * this view, to which future drawing operations will be clipped.
15650     */
15651    public void setClipBounds(Rect clipBounds) {
15652        if (clipBounds == mClipBounds
15653                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
15654            return;
15655        }
15656        if (clipBounds != null) {
15657            if (mClipBounds == null) {
15658                mClipBounds = new Rect(clipBounds);
15659            } else {
15660                mClipBounds.set(clipBounds);
15661            }
15662        } else {
15663            mClipBounds = null;
15664        }
15665        mRenderNode.setClipBounds(mClipBounds);
15666        invalidateViewProperty(false, false);
15667    }
15668
15669    /**
15670     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
15671     *
15672     * @return A copy of the current clip bounds if clip bounds are set,
15673     * otherwise null.
15674     */
15675    public Rect getClipBounds() {
15676        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
15677    }
15678
15679
15680    /**
15681     * Populates an output rectangle with the clip bounds of the view,
15682     * returning {@code true} if successful or {@code false} if the view's
15683     * clip bounds are {@code null}.
15684     *
15685     * @param outRect rectangle in which to place the clip bounds of the view
15686     * @return {@code true} if successful or {@code false} if the view's
15687     *         clip bounds are {@code null}
15688     */
15689    public boolean getClipBounds(Rect outRect) {
15690        if (mClipBounds != null) {
15691            outRect.set(mClipBounds);
15692            return true;
15693        }
15694        return false;
15695    }
15696
15697    /**
15698     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
15699     * case of an active Animation being run on the view.
15700     */
15701    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
15702            Animation a, boolean scalingRequired) {
15703        Transformation invalidationTransform;
15704        final int flags = parent.mGroupFlags;
15705        final boolean initialized = a.isInitialized();
15706        if (!initialized) {
15707            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
15708            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
15709            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
15710            onAnimationStart();
15711        }
15712
15713        final Transformation t = parent.getChildTransformation();
15714        boolean more = a.getTransformation(drawingTime, t, 1f);
15715        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
15716            if (parent.mInvalidationTransformation == null) {
15717                parent.mInvalidationTransformation = new Transformation();
15718            }
15719            invalidationTransform = parent.mInvalidationTransformation;
15720            a.getTransformation(drawingTime, invalidationTransform, 1f);
15721        } else {
15722            invalidationTransform = t;
15723        }
15724
15725        if (more) {
15726            if (!a.willChangeBounds()) {
15727                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
15728                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
15729                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
15730                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
15731                    // The child need to draw an animation, potentially offscreen, so
15732                    // make sure we do not cancel invalidate requests
15733                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15734                    parent.invalidate(mLeft, mTop, mRight, mBottom);
15735                }
15736            } else {
15737                if (parent.mInvalidateRegion == null) {
15738                    parent.mInvalidateRegion = new RectF();
15739                }
15740                final RectF region = parent.mInvalidateRegion;
15741                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
15742                        invalidationTransform);
15743
15744                // The child need to draw an animation, potentially offscreen, so
15745                // make sure we do not cancel invalidate requests
15746                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15747
15748                final int left = mLeft + (int) region.left;
15749                final int top = mTop + (int) region.top;
15750                parent.invalidate(left, top, left + (int) (region.width() + .5f),
15751                        top + (int) (region.height() + .5f));
15752            }
15753        }
15754        return more;
15755    }
15756
15757    /**
15758     * This method is called by getDisplayList() when a display list is recorded for a View.
15759     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
15760     */
15761    void setDisplayListProperties(RenderNode renderNode) {
15762        if (renderNode != null) {
15763            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
15764            renderNode.setClipToBounds(mParent instanceof ViewGroup
15765                    && ((ViewGroup) mParent).getClipChildren());
15766
15767            float alpha = 1;
15768            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
15769                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15770                ViewGroup parentVG = (ViewGroup) mParent;
15771                final Transformation t = parentVG.getChildTransformation();
15772                if (parentVG.getChildStaticTransformation(this, t)) {
15773                    final int transformType = t.getTransformationType();
15774                    if (transformType != Transformation.TYPE_IDENTITY) {
15775                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
15776                            alpha = t.getAlpha();
15777                        }
15778                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
15779                            renderNode.setStaticMatrix(t.getMatrix());
15780                        }
15781                    }
15782                }
15783            }
15784            if (mTransformationInfo != null) {
15785                alpha *= getFinalAlpha();
15786                if (alpha < 1) {
15787                    final int multipliedAlpha = (int) (255 * alpha);
15788                    if (onSetAlpha(multipliedAlpha)) {
15789                        alpha = 1;
15790                    }
15791                }
15792                renderNode.setAlpha(alpha);
15793            } else if (alpha < 1) {
15794                renderNode.setAlpha(alpha);
15795            }
15796        }
15797    }
15798
15799    /**
15800     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
15801     *
15802     * This is where the View specializes rendering behavior based on layer type,
15803     * and hardware acceleration.
15804     */
15805    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
15806        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
15807        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
15808         *
15809         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
15810         * HW accelerated, it can't handle drawing RenderNodes.
15811         */
15812        boolean drawingWithRenderNode = mAttachInfo != null
15813                && mAttachInfo.mHardwareAccelerated
15814                && hardwareAcceleratedCanvas;
15815
15816        boolean more = false;
15817        final boolean childHasIdentityMatrix = hasIdentityMatrix();
15818        final int parentFlags = parent.mGroupFlags;
15819
15820        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
15821            parent.getChildTransformation().clear();
15822            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15823        }
15824
15825        Transformation transformToApply = null;
15826        boolean concatMatrix = false;
15827        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
15828        final Animation a = getAnimation();
15829        if (a != null) {
15830            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
15831            concatMatrix = a.willChangeTransformationMatrix();
15832            if (concatMatrix) {
15833                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15834            }
15835            transformToApply = parent.getChildTransformation();
15836        } else {
15837            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
15838                // No longer animating: clear out old animation matrix
15839                mRenderNode.setAnimationMatrix(null);
15840                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15841            }
15842            if (!drawingWithRenderNode
15843                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15844                final Transformation t = parent.getChildTransformation();
15845                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
15846                if (hasTransform) {
15847                    final int transformType = t.getTransformationType();
15848                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
15849                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
15850                }
15851            }
15852        }
15853
15854        concatMatrix |= !childHasIdentityMatrix;
15855
15856        // Sets the flag as early as possible to allow draw() implementations
15857        // to call invalidate() successfully when doing animations
15858        mPrivateFlags |= PFLAG_DRAWN;
15859
15860        if (!concatMatrix &&
15861                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
15862                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
15863                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
15864                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
15865            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
15866            return more;
15867        }
15868        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
15869
15870        if (hardwareAcceleratedCanvas) {
15871            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
15872            // retain the flag's value temporarily in the mRecreateDisplayList flag
15873            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
15874            mPrivateFlags &= ~PFLAG_INVALIDATED;
15875        }
15876
15877        RenderNode renderNode = null;
15878        Bitmap cache = null;
15879        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
15880        if (layerType == LAYER_TYPE_SOFTWARE
15881                || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
15882            // If not drawing with RenderNode, treat HW layers as SW
15883            layerType = LAYER_TYPE_SOFTWARE;
15884            buildDrawingCache(true);
15885            cache = getDrawingCache(true);
15886        }
15887
15888        if (drawingWithRenderNode) {
15889            // Delay getting the display list until animation-driven alpha values are
15890            // set up and possibly passed on to the view
15891            renderNode = updateDisplayListIfDirty();
15892            if (!renderNode.isValid()) {
15893                // Uncommon, but possible. If a view is removed from the hierarchy during the call
15894                // to getDisplayList(), the display list will be marked invalid and we should not
15895                // try to use it again.
15896                renderNode = null;
15897                drawingWithRenderNode = false;
15898            }
15899        }
15900
15901        int sx = 0;
15902        int sy = 0;
15903        if (!drawingWithRenderNode) {
15904            computeScroll();
15905            sx = mScrollX;
15906            sy = mScrollY;
15907        }
15908
15909        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
15910        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
15911
15912        int restoreTo = -1;
15913        if (!drawingWithRenderNode || transformToApply != null) {
15914            restoreTo = canvas.save();
15915        }
15916        if (offsetForScroll) {
15917            canvas.translate(mLeft - sx, mTop - sy);
15918        } else {
15919            if (!drawingWithRenderNode) {
15920                canvas.translate(mLeft, mTop);
15921            }
15922            if (scalingRequired) {
15923                if (drawingWithRenderNode) {
15924                    // TODO: Might not need this if we put everything inside the DL
15925                    restoreTo = canvas.save();
15926                }
15927                // mAttachInfo cannot be null, otherwise scalingRequired == false
15928                final float scale = 1.0f / mAttachInfo.mApplicationScale;
15929                canvas.scale(scale, scale);
15930            }
15931        }
15932
15933        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
15934        if (transformToApply != null
15935                || alpha < 1
15936                || !hasIdentityMatrix()
15937                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
15938            if (transformToApply != null || !childHasIdentityMatrix) {
15939                int transX = 0;
15940                int transY = 0;
15941
15942                if (offsetForScroll) {
15943                    transX = -sx;
15944                    transY = -sy;
15945                }
15946
15947                if (transformToApply != null) {
15948                    if (concatMatrix) {
15949                        if (drawingWithRenderNode) {
15950                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
15951                        } else {
15952                            // Undo the scroll translation, apply the transformation matrix,
15953                            // then redo the scroll translate to get the correct result.
15954                            canvas.translate(-transX, -transY);
15955                            canvas.concat(transformToApply.getMatrix());
15956                            canvas.translate(transX, transY);
15957                        }
15958                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15959                    }
15960
15961                    float transformAlpha = transformToApply.getAlpha();
15962                    if (transformAlpha < 1) {
15963                        alpha *= transformAlpha;
15964                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15965                    }
15966                }
15967
15968                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
15969                    canvas.translate(-transX, -transY);
15970                    canvas.concat(getMatrix());
15971                    canvas.translate(transX, transY);
15972                }
15973            }
15974
15975            // Deal with alpha if it is or used to be <1
15976            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
15977                if (alpha < 1) {
15978                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15979                } else {
15980                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15981                }
15982                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15983                if (!drawingWithDrawingCache) {
15984                    final int multipliedAlpha = (int) (255 * alpha);
15985                    if (!onSetAlpha(multipliedAlpha)) {
15986                        if (drawingWithRenderNode) {
15987                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
15988                        } else if (layerType == LAYER_TYPE_NONE) {
15989                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
15990                                    multipliedAlpha);
15991                        }
15992                    } else {
15993                        // Alpha is handled by the child directly, clobber the layer's alpha
15994                        mPrivateFlags |= PFLAG_ALPHA_SET;
15995                    }
15996                }
15997            }
15998        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15999            onSetAlpha(255);
16000            mPrivateFlags &= ~PFLAG_ALPHA_SET;
16001        }
16002
16003        if (!drawingWithRenderNode) {
16004            // apply clips directly, since RenderNode won't do it for this draw
16005            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
16006                if (offsetForScroll) {
16007                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
16008                } else {
16009                    if (!scalingRequired || cache == null) {
16010                        canvas.clipRect(0, 0, getWidth(), getHeight());
16011                    } else {
16012                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
16013                    }
16014                }
16015            }
16016
16017            if (mClipBounds != null) {
16018                // clip bounds ignore scroll
16019                canvas.clipRect(mClipBounds);
16020            }
16021        }
16022
16023        if (!drawingWithDrawingCache) {
16024            if (drawingWithRenderNode) {
16025                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16026                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16027            } else {
16028                // Fast path for layouts with no backgrounds
16029                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16030                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16031                    dispatchDraw(canvas);
16032                } else {
16033                    draw(canvas);
16034                }
16035            }
16036        } else if (cache != null) {
16037            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16038            Paint cachePaint;
16039            int restoreAlpha = 0;
16040
16041            if (layerType == LAYER_TYPE_NONE) {
16042                cachePaint = parent.mCachePaint;
16043                if (cachePaint == null) {
16044                    cachePaint = new Paint();
16045                    cachePaint.setDither(false);
16046                    parent.mCachePaint = cachePaint;
16047                }
16048            } else {
16049                cachePaint = mLayerPaint;
16050                restoreAlpha = mLayerPaint.getAlpha();
16051            }
16052            cachePaint.setAlpha((int) (alpha * 255));
16053            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
16054            cachePaint.setAlpha(restoreAlpha);
16055        }
16056
16057        if (restoreTo >= 0) {
16058            canvas.restoreToCount(restoreTo);
16059        }
16060
16061        if (a != null && !more) {
16062            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
16063                onSetAlpha(255);
16064            }
16065            parent.finishAnimatingView(this, a);
16066        }
16067
16068        if (more && hardwareAcceleratedCanvas) {
16069            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16070                // alpha animations should cause the child to recreate its display list
16071                invalidate(true);
16072            }
16073        }
16074
16075        mRecreateDisplayList = false;
16076
16077        return more;
16078    }
16079
16080    /**
16081     * Manually render this view (and all of its children) to the given Canvas.
16082     * The view must have already done a full layout before this function is
16083     * called.  When implementing a view, implement
16084     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
16085     * If you do need to override this method, call the superclass version.
16086     *
16087     * @param canvas The Canvas to which the View is rendered.
16088     */
16089    @CallSuper
16090    public void draw(Canvas canvas) {
16091        final int privateFlags = mPrivateFlags;
16092        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
16093                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
16094        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
16095
16096        /*
16097         * Draw traversal performs several drawing steps which must be executed
16098         * in the appropriate order:
16099         *
16100         *      1. Draw the background
16101         *      2. If necessary, save the canvas' layers to prepare for fading
16102         *      3. Draw view's content
16103         *      4. Draw children
16104         *      5. If necessary, draw the fading edges and restore layers
16105         *      6. Draw decorations (scrollbars for instance)
16106         */
16107
16108        // Step 1, draw the background, if needed
16109        int saveCount;
16110
16111        if (!dirtyOpaque) {
16112            drawBackground(canvas);
16113        }
16114
16115        // skip step 2 & 5 if possible (common case)
16116        final int viewFlags = mViewFlags;
16117        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
16118        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
16119        if (!verticalEdges && !horizontalEdges) {
16120            // Step 3, draw the content
16121            if (!dirtyOpaque) onDraw(canvas);
16122
16123            // Step 4, draw the children
16124            dispatchDraw(canvas);
16125
16126            // Overlay is part of the content and draws beneath Foreground
16127            if (mOverlay != null && !mOverlay.isEmpty()) {
16128                mOverlay.getOverlayView().dispatchDraw(canvas);
16129            }
16130
16131            // Step 6, draw decorations (foreground, scrollbars)
16132            onDrawForeground(canvas);
16133
16134            // we're done...
16135            return;
16136        }
16137
16138        /*
16139         * Here we do the full fledged routine...
16140         * (this is an uncommon case where speed matters less,
16141         * this is why we repeat some of the tests that have been
16142         * done above)
16143         */
16144
16145        boolean drawTop = false;
16146        boolean drawBottom = false;
16147        boolean drawLeft = false;
16148        boolean drawRight = false;
16149
16150        float topFadeStrength = 0.0f;
16151        float bottomFadeStrength = 0.0f;
16152        float leftFadeStrength = 0.0f;
16153        float rightFadeStrength = 0.0f;
16154
16155        // Step 2, save the canvas' layers
16156        int paddingLeft = mPaddingLeft;
16157
16158        final boolean offsetRequired = isPaddingOffsetRequired();
16159        if (offsetRequired) {
16160            paddingLeft += getLeftPaddingOffset();
16161        }
16162
16163        int left = mScrollX + paddingLeft;
16164        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
16165        int top = mScrollY + getFadeTop(offsetRequired);
16166        int bottom = top + getFadeHeight(offsetRequired);
16167
16168        if (offsetRequired) {
16169            right += getRightPaddingOffset();
16170            bottom += getBottomPaddingOffset();
16171        }
16172
16173        final ScrollabilityCache scrollabilityCache = mScrollCache;
16174        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
16175        int length = (int) fadeHeight;
16176
16177        // clip the fade length if top and bottom fades overlap
16178        // overlapping fades produce odd-looking artifacts
16179        if (verticalEdges && (top + length > bottom - length)) {
16180            length = (bottom - top) / 2;
16181        }
16182
16183        // also clip horizontal fades if necessary
16184        if (horizontalEdges && (left + length > right - length)) {
16185            length = (right - left) / 2;
16186        }
16187
16188        if (verticalEdges) {
16189            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
16190            drawTop = topFadeStrength * fadeHeight > 1.0f;
16191            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
16192            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
16193        }
16194
16195        if (horizontalEdges) {
16196            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
16197            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
16198            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
16199            drawRight = rightFadeStrength * fadeHeight > 1.0f;
16200        }
16201
16202        saveCount = canvas.getSaveCount();
16203
16204        int solidColor = getSolidColor();
16205        if (solidColor == 0) {
16206            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
16207
16208            if (drawTop) {
16209                canvas.saveLayer(left, top, right, top + length, null, flags);
16210            }
16211
16212            if (drawBottom) {
16213                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
16214            }
16215
16216            if (drawLeft) {
16217                canvas.saveLayer(left, top, left + length, bottom, null, flags);
16218            }
16219
16220            if (drawRight) {
16221                canvas.saveLayer(right - length, top, right, bottom, null, flags);
16222            }
16223        } else {
16224            scrollabilityCache.setFadeColor(solidColor);
16225        }
16226
16227        // Step 3, draw the content
16228        if (!dirtyOpaque) onDraw(canvas);
16229
16230        // Step 4, draw the children
16231        dispatchDraw(canvas);
16232
16233        // Step 5, draw the fade effect and restore layers
16234        final Paint p = scrollabilityCache.paint;
16235        final Matrix matrix = scrollabilityCache.matrix;
16236        final Shader fade = scrollabilityCache.shader;
16237
16238        if (drawTop) {
16239            matrix.setScale(1, fadeHeight * topFadeStrength);
16240            matrix.postTranslate(left, top);
16241            fade.setLocalMatrix(matrix);
16242            p.setShader(fade);
16243            canvas.drawRect(left, top, right, top + length, p);
16244        }
16245
16246        if (drawBottom) {
16247            matrix.setScale(1, fadeHeight * bottomFadeStrength);
16248            matrix.postRotate(180);
16249            matrix.postTranslate(left, bottom);
16250            fade.setLocalMatrix(matrix);
16251            p.setShader(fade);
16252            canvas.drawRect(left, bottom - length, right, bottom, p);
16253        }
16254
16255        if (drawLeft) {
16256            matrix.setScale(1, fadeHeight * leftFadeStrength);
16257            matrix.postRotate(-90);
16258            matrix.postTranslate(left, top);
16259            fade.setLocalMatrix(matrix);
16260            p.setShader(fade);
16261            canvas.drawRect(left, top, left + length, bottom, p);
16262        }
16263
16264        if (drawRight) {
16265            matrix.setScale(1, fadeHeight * rightFadeStrength);
16266            matrix.postRotate(90);
16267            matrix.postTranslate(right, top);
16268            fade.setLocalMatrix(matrix);
16269            p.setShader(fade);
16270            canvas.drawRect(right - length, top, right, bottom, p);
16271        }
16272
16273        canvas.restoreToCount(saveCount);
16274
16275        // Overlay is part of the content and draws beneath Foreground
16276        if (mOverlay != null && !mOverlay.isEmpty()) {
16277            mOverlay.getOverlayView().dispatchDraw(canvas);
16278        }
16279
16280        // Step 6, draw decorations (foreground, scrollbars)
16281        onDrawForeground(canvas);
16282    }
16283
16284    /**
16285     * Draws the background onto the specified canvas.
16286     *
16287     * @param canvas Canvas on which to draw the background
16288     */
16289    private void drawBackground(Canvas canvas) {
16290        final Drawable background = mBackground;
16291        if (background == null) {
16292            return;
16293        }
16294
16295        setBackgroundBounds();
16296
16297        // Attempt to use a display list if requested.
16298        if (canvas.isHardwareAccelerated() && mAttachInfo != null
16299                && mAttachInfo.mHardwareRenderer != null) {
16300            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
16301
16302            final RenderNode renderNode = mBackgroundRenderNode;
16303            if (renderNode != null && renderNode.isValid()) {
16304                setBackgroundRenderNodeProperties(renderNode);
16305                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16306                return;
16307            }
16308        }
16309
16310        final int scrollX = mScrollX;
16311        final int scrollY = mScrollY;
16312        if ((scrollX | scrollY) == 0) {
16313            background.draw(canvas);
16314        } else {
16315            canvas.translate(scrollX, scrollY);
16316            background.draw(canvas);
16317            canvas.translate(-scrollX, -scrollY);
16318        }
16319    }
16320
16321    /**
16322     * Sets the correct background bounds and rebuilds the outline, if needed.
16323     * <p/>
16324     * This is called by LayoutLib.
16325     */
16326    void setBackgroundBounds() {
16327        if (mBackgroundSizeChanged && mBackground != null) {
16328            mBackground.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
16329            mBackgroundSizeChanged = false;
16330            rebuildOutline();
16331        }
16332    }
16333
16334    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
16335        renderNode.setTranslationX(mScrollX);
16336        renderNode.setTranslationY(mScrollY);
16337    }
16338
16339    /**
16340     * Creates a new display list or updates the existing display list for the
16341     * specified Drawable.
16342     *
16343     * @param drawable Drawable for which to create a display list
16344     * @param renderNode Existing RenderNode, or {@code null}
16345     * @return A valid display list for the specified drawable
16346     */
16347    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
16348        if (renderNode == null) {
16349            renderNode = RenderNode.create(drawable.getClass().getName(), this);
16350        }
16351
16352        final Rect bounds = drawable.getBounds();
16353        final int width = bounds.width();
16354        final int height = bounds.height();
16355        final DisplayListCanvas canvas = renderNode.start(width, height);
16356
16357        // Reverse left/top translation done by drawable canvas, which will
16358        // instead be applied by rendernode's LTRB bounds below. This way, the
16359        // drawable's bounds match with its rendernode bounds and its content
16360        // will lie within those bounds in the rendernode tree.
16361        canvas.translate(-bounds.left, -bounds.top);
16362
16363        try {
16364            drawable.draw(canvas);
16365        } finally {
16366            renderNode.end(canvas);
16367        }
16368
16369        // Set up drawable properties that are view-independent.
16370        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
16371        renderNode.setProjectBackwards(drawable.isProjected());
16372        renderNode.setProjectionReceiver(true);
16373        renderNode.setClipToBounds(false);
16374        return renderNode;
16375    }
16376
16377    /**
16378     * Returns the overlay for this view, creating it if it does not yet exist.
16379     * Adding drawables to the overlay will cause them to be displayed whenever
16380     * the view itself is redrawn. Objects in the overlay should be actively
16381     * managed: remove them when they should not be displayed anymore. The
16382     * overlay will always have the same size as its host view.
16383     *
16384     * <p>Note: Overlays do not currently work correctly with {@link
16385     * SurfaceView} or {@link TextureView}; contents in overlays for these
16386     * types of views may not display correctly.</p>
16387     *
16388     * @return The ViewOverlay object for this view.
16389     * @see ViewOverlay
16390     */
16391    public ViewOverlay getOverlay() {
16392        if (mOverlay == null) {
16393            mOverlay = new ViewOverlay(mContext, this);
16394        }
16395        return mOverlay;
16396    }
16397
16398    /**
16399     * Override this if your view is known to always be drawn on top of a solid color background,
16400     * and needs to draw fading edges. Returning a non-zero color enables the view system to
16401     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
16402     * should be set to 0xFF.
16403     *
16404     * @see #setVerticalFadingEdgeEnabled(boolean)
16405     * @see #setHorizontalFadingEdgeEnabled(boolean)
16406     *
16407     * @return The known solid color background for this view, or 0 if the color may vary
16408     */
16409    @ViewDebug.ExportedProperty(category = "drawing")
16410    @ColorInt
16411    public int getSolidColor() {
16412        return 0;
16413    }
16414
16415    /**
16416     * Build a human readable string representation of the specified view flags.
16417     *
16418     * @param flags the view flags to convert to a string
16419     * @return a String representing the supplied flags
16420     */
16421    private static String printFlags(int flags) {
16422        String output = "";
16423        int numFlags = 0;
16424        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
16425            output += "TAKES_FOCUS";
16426            numFlags++;
16427        }
16428
16429        switch (flags & VISIBILITY_MASK) {
16430        case INVISIBLE:
16431            if (numFlags > 0) {
16432                output += " ";
16433            }
16434            output += "INVISIBLE";
16435            // USELESS HERE numFlags++;
16436            break;
16437        case GONE:
16438            if (numFlags > 0) {
16439                output += " ";
16440            }
16441            output += "GONE";
16442            // USELESS HERE numFlags++;
16443            break;
16444        default:
16445            break;
16446        }
16447        return output;
16448    }
16449
16450    /**
16451     * Build a human readable string representation of the specified private
16452     * view flags.
16453     *
16454     * @param privateFlags the private view flags to convert to a string
16455     * @return a String representing the supplied flags
16456     */
16457    private static String printPrivateFlags(int privateFlags) {
16458        String output = "";
16459        int numFlags = 0;
16460
16461        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
16462            output += "WANTS_FOCUS";
16463            numFlags++;
16464        }
16465
16466        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
16467            if (numFlags > 0) {
16468                output += " ";
16469            }
16470            output += "FOCUSED";
16471            numFlags++;
16472        }
16473
16474        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
16475            if (numFlags > 0) {
16476                output += " ";
16477            }
16478            output += "SELECTED";
16479            numFlags++;
16480        }
16481
16482        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
16483            if (numFlags > 0) {
16484                output += " ";
16485            }
16486            output += "IS_ROOT_NAMESPACE";
16487            numFlags++;
16488        }
16489
16490        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
16491            if (numFlags > 0) {
16492                output += " ";
16493            }
16494            output += "HAS_BOUNDS";
16495            numFlags++;
16496        }
16497
16498        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
16499            if (numFlags > 0) {
16500                output += " ";
16501            }
16502            output += "DRAWN";
16503            // USELESS HERE numFlags++;
16504        }
16505        return output;
16506    }
16507
16508    /**
16509     * <p>Indicates whether or not this view's layout will be requested during
16510     * the next hierarchy layout pass.</p>
16511     *
16512     * @return true if the layout will be forced during next layout pass
16513     */
16514    public boolean isLayoutRequested() {
16515        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16516    }
16517
16518    /**
16519     * Return true if o is a ViewGroup that is laying out using optical bounds.
16520     * @hide
16521     */
16522    public static boolean isLayoutModeOptical(Object o) {
16523        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16524    }
16525
16526    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16527        Insets parentInsets = mParent instanceof View ?
16528                ((View) mParent).getOpticalInsets() : Insets.NONE;
16529        Insets childInsets = getOpticalInsets();
16530        return setFrame(
16531                left   + parentInsets.left - childInsets.left,
16532                top    + parentInsets.top  - childInsets.top,
16533                right  + parentInsets.left + childInsets.right,
16534                bottom + parentInsets.top  + childInsets.bottom);
16535    }
16536
16537    /**
16538     * Assign a size and position to a view and all of its
16539     * descendants
16540     *
16541     * <p>This is the second phase of the layout mechanism.
16542     * (The first is measuring). In this phase, each parent calls
16543     * layout on all of its children to position them.
16544     * This is typically done using the child measurements
16545     * that were stored in the measure pass().</p>
16546     *
16547     * <p>Derived classes should not override this method.
16548     * Derived classes with children should override
16549     * onLayout. In that method, they should
16550     * call layout on each of their children.</p>
16551     *
16552     * @param l Left position, relative to parent
16553     * @param t Top position, relative to parent
16554     * @param r Right position, relative to parent
16555     * @param b Bottom position, relative to parent
16556     */
16557    @SuppressWarnings({"unchecked"})
16558    public void layout(int l, int t, int r, int b) {
16559        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16560            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16561            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16562        }
16563
16564        int oldL = mLeft;
16565        int oldT = mTop;
16566        int oldB = mBottom;
16567        int oldR = mRight;
16568
16569        boolean changed = isLayoutModeOptical(mParent) ?
16570                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16571
16572        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
16573            onLayout(changed, l, t, r, b);
16574            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
16575
16576            ListenerInfo li = mListenerInfo;
16577            if (li != null && li.mOnLayoutChangeListeners != null) {
16578                ArrayList<OnLayoutChangeListener> listenersCopy =
16579                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
16580                int numListeners = listenersCopy.size();
16581                for (int i = 0; i < numListeners; ++i) {
16582                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
16583                }
16584            }
16585        }
16586
16587        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
16588        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
16589    }
16590
16591    /**
16592     * Called from layout when this view should
16593     * assign a size and position to each of its children.
16594     *
16595     * Derived classes with children should override
16596     * this method and call layout on each of
16597     * their children.
16598     * @param changed This is a new size or position for this view
16599     * @param left Left position, relative to parent
16600     * @param top Top position, relative to parent
16601     * @param right Right position, relative to parent
16602     * @param bottom Bottom position, relative to parent
16603     */
16604    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
16605    }
16606
16607    /**
16608     * Assign a size and position to this view.
16609     *
16610     * This is called from layout.
16611     *
16612     * @param left Left position, relative to parent
16613     * @param top Top position, relative to parent
16614     * @param right Right position, relative to parent
16615     * @param bottom Bottom position, relative to parent
16616     * @return true if the new size and position are different than the
16617     *         previous ones
16618     * {@hide}
16619     */
16620    protected boolean setFrame(int left, int top, int right, int bottom) {
16621        boolean changed = false;
16622
16623        if (DBG) {
16624            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16625                    + right + "," + bottom + ")");
16626        }
16627
16628        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16629            changed = true;
16630
16631            // Remember our drawn bit
16632            int drawn = mPrivateFlags & PFLAG_DRAWN;
16633
16634            int oldWidth = mRight - mLeft;
16635            int oldHeight = mBottom - mTop;
16636            int newWidth = right - left;
16637            int newHeight = bottom - top;
16638            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16639
16640            // Invalidate our old position
16641            invalidate(sizeChanged);
16642
16643            mLeft = left;
16644            mTop = top;
16645            mRight = right;
16646            mBottom = bottom;
16647            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16648
16649            mPrivateFlags |= PFLAG_HAS_BOUNDS;
16650
16651
16652            if (sizeChanged) {
16653                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16654            }
16655
16656            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16657                // If we are visible, force the DRAWN bit to on so that
16658                // this invalidate will go through (at least to our parent).
16659                // This is because someone may have invalidated this view
16660                // before this call to setFrame came in, thereby clearing
16661                // the DRAWN bit.
16662                mPrivateFlags |= PFLAG_DRAWN;
16663                invalidate(sizeChanged);
16664                // parent display list may need to be recreated based on a change in the bounds
16665                // of any child
16666                invalidateParentCaches();
16667            }
16668
16669            // Reset drawn bit to original value (invalidate turns it off)
16670            mPrivateFlags |= drawn;
16671
16672            mBackgroundSizeChanged = true;
16673            if (mForegroundInfo != null) {
16674                mForegroundInfo.mBoundsChanged = true;
16675            }
16676
16677            notifySubtreeAccessibilityStateChangedIfNeeded();
16678        }
16679        return changed;
16680    }
16681
16682    /**
16683     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
16684     * @hide
16685     */
16686    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
16687        setFrame(left, top, right, bottom);
16688    }
16689
16690    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
16691        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
16692        if (mOverlay != null) {
16693            mOverlay.getOverlayView().setRight(newWidth);
16694            mOverlay.getOverlayView().setBottom(newHeight);
16695        }
16696        rebuildOutline();
16697    }
16698
16699    /**
16700     * Finalize inflating a view from XML.  This is called as the last phase
16701     * of inflation, after all child views have been added.
16702     *
16703     * <p>Even if the subclass overrides onFinishInflate, they should always be
16704     * sure to call the super method, so that we get called.
16705     */
16706    @CallSuper
16707    protected void onFinishInflate() {
16708    }
16709
16710    /**
16711     * Returns the resources associated with this view.
16712     *
16713     * @return Resources object.
16714     */
16715    public Resources getResources() {
16716        return mResources;
16717    }
16718
16719    /**
16720     * Invalidates the specified Drawable.
16721     *
16722     * @param drawable the drawable to invalidate
16723     */
16724    @Override
16725    public void invalidateDrawable(@NonNull Drawable drawable) {
16726        if (verifyDrawable(drawable)) {
16727            final Rect dirty = drawable.getDirtyBounds();
16728            final int scrollX = mScrollX;
16729            final int scrollY = mScrollY;
16730
16731            invalidate(dirty.left + scrollX, dirty.top + scrollY,
16732                    dirty.right + scrollX, dirty.bottom + scrollY);
16733            rebuildOutline();
16734        }
16735    }
16736
16737    /**
16738     * Schedules an action on a drawable to occur at a specified time.
16739     *
16740     * @param who the recipient of the action
16741     * @param what the action to run on the drawable
16742     * @param when the time at which the action must occur. Uses the
16743     *        {@link SystemClock#uptimeMillis} timebase.
16744     */
16745    @Override
16746    public void scheduleDrawable(Drawable who, Runnable what, long when) {
16747        if (verifyDrawable(who) && what != null) {
16748            final long delay = when - SystemClock.uptimeMillis();
16749            if (mAttachInfo != null) {
16750                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
16751                        Choreographer.CALLBACK_ANIMATION, what, who,
16752                        Choreographer.subtractFrameDelay(delay));
16753            } else {
16754                ViewRootImpl.getRunQueue().postDelayed(what, delay);
16755            }
16756        }
16757    }
16758
16759    /**
16760     * Cancels a scheduled action on a drawable.
16761     *
16762     * @param who the recipient of the action
16763     * @param what the action to cancel
16764     */
16765    @Override
16766    public void unscheduleDrawable(Drawable who, Runnable what) {
16767        if (verifyDrawable(who) && what != null) {
16768            if (mAttachInfo != null) {
16769                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16770                        Choreographer.CALLBACK_ANIMATION, what, who);
16771            }
16772            ViewRootImpl.getRunQueue().removeCallbacks(what);
16773        }
16774    }
16775
16776    /**
16777     * Unschedule any events associated with the given Drawable.  This can be
16778     * used when selecting a new Drawable into a view, so that the previous
16779     * one is completely unscheduled.
16780     *
16781     * @param who The Drawable to unschedule.
16782     *
16783     * @see #drawableStateChanged
16784     */
16785    public void unscheduleDrawable(Drawable who) {
16786        if (mAttachInfo != null && who != null) {
16787            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16788                    Choreographer.CALLBACK_ANIMATION, null, who);
16789        }
16790    }
16791
16792    /**
16793     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
16794     * that the View directionality can and will be resolved before its Drawables.
16795     *
16796     * Will call {@link View#onResolveDrawables} when resolution is done.
16797     *
16798     * @hide
16799     */
16800    protected void resolveDrawables() {
16801        // Drawables resolution may need to happen before resolving the layout direction (which is
16802        // done only during the measure() call).
16803        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
16804        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
16805        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
16806        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
16807        // direction to be resolved as its resolved value will be the same as its raw value.
16808        if (!isLayoutDirectionResolved() &&
16809                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
16810            return;
16811        }
16812
16813        final int layoutDirection = isLayoutDirectionResolved() ?
16814                getLayoutDirection() : getRawLayoutDirection();
16815
16816        if (mBackground != null) {
16817            mBackground.setLayoutDirection(layoutDirection);
16818        }
16819        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16820            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
16821        }
16822        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
16823        onResolveDrawables(layoutDirection);
16824    }
16825
16826    boolean areDrawablesResolved() {
16827        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
16828    }
16829
16830    /**
16831     * Called when layout direction has been resolved.
16832     *
16833     * The default implementation does nothing.
16834     *
16835     * @param layoutDirection The resolved layout direction.
16836     *
16837     * @see #LAYOUT_DIRECTION_LTR
16838     * @see #LAYOUT_DIRECTION_RTL
16839     *
16840     * @hide
16841     */
16842    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
16843    }
16844
16845    /**
16846     * @hide
16847     */
16848    protected void resetResolvedDrawables() {
16849        resetResolvedDrawablesInternal();
16850    }
16851
16852    void resetResolvedDrawablesInternal() {
16853        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
16854    }
16855
16856    /**
16857     * If your view subclass is displaying its own Drawable objects, it should
16858     * override this function and return true for any Drawable it is
16859     * displaying.  This allows animations for those drawables to be
16860     * scheduled.
16861     *
16862     * <p>Be sure to call through to the super class when overriding this
16863     * function.
16864     *
16865     * @param who The Drawable to verify.  Return true if it is one you are
16866     *            displaying, else return the result of calling through to the
16867     *            super class.
16868     *
16869     * @return boolean If true than the Drawable is being displayed in the
16870     *         view; else false and it is not allowed to animate.
16871     *
16872     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
16873     * @see #drawableStateChanged()
16874     */
16875    @CallSuper
16876    protected boolean verifyDrawable(Drawable who) {
16877        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
16878                || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
16879    }
16880
16881    /**
16882     * This function is called whenever the state of the view changes in such
16883     * a way that it impacts the state of drawables being shown.
16884     * <p>
16885     * If the View has a StateListAnimator, it will also be called to run necessary state
16886     * change animations.
16887     * <p>
16888     * Be sure to call through to the superclass when overriding this function.
16889     *
16890     * @see Drawable#setState(int[])
16891     */
16892    @CallSuper
16893    protected void drawableStateChanged() {
16894        final int[] state = getDrawableState();
16895
16896        final Drawable bg = mBackground;
16897        if (bg != null && bg.isStateful()) {
16898            bg.setState(state);
16899        }
16900
16901        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16902        if (fg != null && fg.isStateful()) {
16903            fg.setState(state);
16904        }
16905
16906        if (mScrollCache != null) {
16907            final Drawable scrollBar = mScrollCache.scrollBar;
16908            if (scrollBar != null && scrollBar.isStateful()) {
16909                scrollBar.setState(state);
16910            }
16911        }
16912
16913        if (mStateListAnimator != null) {
16914            mStateListAnimator.setState(state);
16915        }
16916    }
16917
16918    /**
16919     * This function is called whenever the view hotspot changes and needs to
16920     * be propagated to drawables or child views managed by the view.
16921     * <p>
16922     * Dispatching to child views is handled by
16923     * {@link #dispatchDrawableHotspotChanged(float, float)}.
16924     * <p>
16925     * Be sure to call through to the superclass when overriding this function.
16926     *
16927     * @param x hotspot x coordinate
16928     * @param y hotspot y coordinate
16929     */
16930    @CallSuper
16931    public void drawableHotspotChanged(float x, float y) {
16932        if (mBackground != null) {
16933            mBackground.setHotspot(x, y);
16934        }
16935        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16936            mForegroundInfo.mDrawable.setHotspot(x, y);
16937        }
16938
16939        dispatchDrawableHotspotChanged(x, y);
16940    }
16941
16942    /**
16943     * Dispatches drawableHotspotChanged to all of this View's children.
16944     *
16945     * @param x hotspot x coordinate
16946     * @param y hotspot y coordinate
16947     * @see #drawableHotspotChanged(float, float)
16948     */
16949    public void dispatchDrawableHotspotChanged(float x, float y) {
16950    }
16951
16952    /**
16953     * Call this to force a view to update its drawable state. This will cause
16954     * drawableStateChanged to be called on this view. Views that are interested
16955     * in the new state should call getDrawableState.
16956     *
16957     * @see #drawableStateChanged
16958     * @see #getDrawableState
16959     */
16960    public void refreshDrawableState() {
16961        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16962        drawableStateChanged();
16963
16964        ViewParent parent = mParent;
16965        if (parent != null) {
16966            parent.childDrawableStateChanged(this);
16967        }
16968    }
16969
16970    /**
16971     * Return an array of resource IDs of the drawable states representing the
16972     * current state of the view.
16973     *
16974     * @return The current drawable state
16975     *
16976     * @see Drawable#setState(int[])
16977     * @see #drawableStateChanged()
16978     * @see #onCreateDrawableState(int)
16979     */
16980    public final int[] getDrawableState() {
16981        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
16982            return mDrawableState;
16983        } else {
16984            mDrawableState = onCreateDrawableState(0);
16985            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
16986            return mDrawableState;
16987        }
16988    }
16989
16990    /**
16991     * Generate the new {@link android.graphics.drawable.Drawable} state for
16992     * this view. This is called by the view
16993     * system when the cached Drawable state is determined to be invalid.  To
16994     * retrieve the current state, you should use {@link #getDrawableState}.
16995     *
16996     * @param extraSpace if non-zero, this is the number of extra entries you
16997     * would like in the returned array in which you can place your own
16998     * states.
16999     *
17000     * @return Returns an array holding the current {@link Drawable} state of
17001     * the view.
17002     *
17003     * @see #mergeDrawableStates(int[], int[])
17004     */
17005    protected int[] onCreateDrawableState(int extraSpace) {
17006        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
17007                mParent instanceof View) {
17008            return ((View) mParent).onCreateDrawableState(extraSpace);
17009        }
17010
17011        int[] drawableState;
17012
17013        int privateFlags = mPrivateFlags;
17014
17015        int viewStateIndex = 0;
17016        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
17017        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
17018        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
17019        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
17020        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
17021        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
17022        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
17023                HardwareRenderer.isAvailable()) {
17024            // This is set if HW acceleration is requested, even if the current
17025            // process doesn't allow it.  This is just to allow app preview
17026            // windows to better match their app.
17027            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
17028        }
17029        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
17030
17031        final int privateFlags2 = mPrivateFlags2;
17032        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
17033            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
17034        }
17035        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
17036            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
17037        }
17038
17039        drawableState = StateSet.get(viewStateIndex);
17040
17041        //noinspection ConstantIfStatement
17042        if (false) {
17043            Log.i("View", "drawableStateIndex=" + viewStateIndex);
17044            Log.i("View", toString()
17045                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
17046                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
17047                    + " fo=" + hasFocus()
17048                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
17049                    + " wf=" + hasWindowFocus()
17050                    + ": " + Arrays.toString(drawableState));
17051        }
17052
17053        if (extraSpace == 0) {
17054            return drawableState;
17055        }
17056
17057        final int[] fullState;
17058        if (drawableState != null) {
17059            fullState = new int[drawableState.length + extraSpace];
17060            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
17061        } else {
17062            fullState = new int[extraSpace];
17063        }
17064
17065        return fullState;
17066    }
17067
17068    /**
17069     * Merge your own state values in <var>additionalState</var> into the base
17070     * state values <var>baseState</var> that were returned by
17071     * {@link #onCreateDrawableState(int)}.
17072     *
17073     * @param baseState The base state values returned by
17074     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
17075     * own additional state values.
17076     *
17077     * @param additionalState The additional state values you would like
17078     * added to <var>baseState</var>; this array is not modified.
17079     *
17080     * @return As a convenience, the <var>baseState</var> array you originally
17081     * passed into the function is returned.
17082     *
17083     * @see #onCreateDrawableState(int)
17084     */
17085    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
17086        final int N = baseState.length;
17087        int i = N - 1;
17088        while (i >= 0 && baseState[i] == 0) {
17089            i--;
17090        }
17091        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
17092        return baseState;
17093    }
17094
17095    /**
17096     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
17097     * on all Drawable objects associated with this view.
17098     * <p>
17099     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
17100     * attached to this view.
17101     */
17102    public void jumpDrawablesToCurrentState() {
17103        if (mBackground != null) {
17104            mBackground.jumpToCurrentState();
17105        }
17106        if (mStateListAnimator != null) {
17107            mStateListAnimator.jumpToCurrentState();
17108        }
17109        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17110            mForegroundInfo.mDrawable.jumpToCurrentState();
17111        }
17112    }
17113
17114    /**
17115     * Sets the background color for this view.
17116     * @param color the color of the background
17117     */
17118    @RemotableViewMethod
17119    public void setBackgroundColor(@ColorInt int color) {
17120        if (mBackground instanceof ColorDrawable) {
17121            ((ColorDrawable) mBackground.mutate()).setColor(color);
17122            computeOpaqueFlags();
17123            mBackgroundResource = 0;
17124        } else {
17125            setBackground(new ColorDrawable(color));
17126        }
17127    }
17128
17129    /**
17130     * If the view has a ColorDrawable background, returns the color of that
17131     * drawable.
17132     *
17133     * @return The color of the ColorDrawable background, if set, otherwise 0.
17134     */
17135    @ColorInt
17136    public int getBackgroundColor() {
17137        if (mBackground instanceof ColorDrawable) {
17138            return ((ColorDrawable) mBackground).getColor();
17139        }
17140        return 0;
17141    }
17142
17143    /**
17144     * Set the background to a given resource. The resource should refer to
17145     * a Drawable object or 0 to remove the background.
17146     * @param resid The identifier of the resource.
17147     *
17148     * @attr ref android.R.styleable#View_background
17149     */
17150    @RemotableViewMethod
17151    public void setBackgroundResource(@DrawableRes int resid) {
17152        if (resid != 0 && resid == mBackgroundResource) {
17153            return;
17154        }
17155
17156        Drawable d = null;
17157        if (resid != 0) {
17158            d = mContext.getDrawable(resid);
17159        }
17160        setBackground(d);
17161
17162        mBackgroundResource = resid;
17163    }
17164
17165    /**
17166     * Set the background to a given Drawable, or remove the background. If the
17167     * background has padding, this View's padding is set to the background's
17168     * padding. However, when a background is removed, this View's padding isn't
17169     * touched. If setting the padding is desired, please use
17170     * {@link #setPadding(int, int, int, int)}.
17171     *
17172     * @param background The Drawable to use as the background, or null to remove the
17173     *        background
17174     */
17175    public void setBackground(Drawable background) {
17176        //noinspection deprecation
17177        setBackgroundDrawable(background);
17178    }
17179
17180    /**
17181     * @deprecated use {@link #setBackground(Drawable)} instead
17182     */
17183    @Deprecated
17184    public void setBackgroundDrawable(Drawable background) {
17185        computeOpaqueFlags();
17186
17187        if (background == mBackground) {
17188            return;
17189        }
17190
17191        boolean requestLayout = false;
17192
17193        mBackgroundResource = 0;
17194
17195        /*
17196         * Regardless of whether we're setting a new background or not, we want
17197         * to clear the previous drawable.
17198         */
17199        if (mBackground != null) {
17200            mBackground.setCallback(null);
17201            unscheduleDrawable(mBackground);
17202        }
17203
17204        if (background != null) {
17205            Rect padding = sThreadLocal.get();
17206            if (padding == null) {
17207                padding = new Rect();
17208                sThreadLocal.set(padding);
17209            }
17210            resetResolvedDrawablesInternal();
17211            background.setLayoutDirection(getLayoutDirection());
17212            if (background.getPadding(padding)) {
17213                resetResolvedPaddingInternal();
17214                switch (background.getLayoutDirection()) {
17215                    case LAYOUT_DIRECTION_RTL:
17216                        mUserPaddingLeftInitial = padding.right;
17217                        mUserPaddingRightInitial = padding.left;
17218                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
17219                        break;
17220                    case LAYOUT_DIRECTION_LTR:
17221                    default:
17222                        mUserPaddingLeftInitial = padding.left;
17223                        mUserPaddingRightInitial = padding.right;
17224                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
17225                }
17226                mLeftPaddingDefined = false;
17227                mRightPaddingDefined = false;
17228            }
17229
17230            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
17231            // if it has a different minimum size, we should layout again
17232            if (mBackground == null
17233                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
17234                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
17235                requestLayout = true;
17236            }
17237
17238            background.setCallback(this);
17239            if (background.isStateful()) {
17240                background.setState(getDrawableState());
17241            }
17242            background.setVisible(getVisibility() == VISIBLE, false);
17243            mBackground = background;
17244
17245            applyBackgroundTint();
17246
17247            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17248                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17249                requestLayout = true;
17250            }
17251        } else {
17252            /* Remove the background */
17253            mBackground = null;
17254            if ((mViewFlags & WILL_NOT_DRAW) != 0
17255                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
17256                mPrivateFlags |= PFLAG_SKIP_DRAW;
17257            }
17258
17259            /*
17260             * When the background is set, we try to apply its padding to this
17261             * View. When the background is removed, we don't touch this View's
17262             * padding. This is noted in the Javadocs. Hence, we don't need to
17263             * requestLayout(), the invalidate() below is sufficient.
17264             */
17265
17266            // The old background's minimum size could have affected this
17267            // View's layout, so let's requestLayout
17268            requestLayout = true;
17269        }
17270
17271        computeOpaqueFlags();
17272
17273        if (requestLayout) {
17274            requestLayout();
17275        }
17276
17277        mBackgroundSizeChanged = true;
17278        invalidate(true);
17279    }
17280
17281    /**
17282     * Gets the background drawable
17283     *
17284     * @return The drawable used as the background for this view, if any.
17285     *
17286     * @see #setBackground(Drawable)
17287     *
17288     * @attr ref android.R.styleable#View_background
17289     */
17290    public Drawable getBackground() {
17291        return mBackground;
17292    }
17293
17294    /**
17295     * Applies a tint to the background drawable. Does not modify the current tint
17296     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17297     * <p>
17298     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
17299     * mutate the drawable and apply the specified tint and tint mode using
17300     * {@link Drawable#setTintList(ColorStateList)}.
17301     *
17302     * @param tint the tint to apply, may be {@code null} to clear tint
17303     *
17304     * @attr ref android.R.styleable#View_backgroundTint
17305     * @see #getBackgroundTintList()
17306     * @see Drawable#setTintList(ColorStateList)
17307     */
17308    public void setBackgroundTintList(@Nullable ColorStateList tint) {
17309        if (mBackgroundTint == null) {
17310            mBackgroundTint = new TintInfo();
17311        }
17312        mBackgroundTint.mTintList = tint;
17313        mBackgroundTint.mHasTintList = true;
17314
17315        applyBackgroundTint();
17316    }
17317
17318    /**
17319     * Return the tint applied to the background drawable, if specified.
17320     *
17321     * @return the tint applied to the background drawable
17322     * @attr ref android.R.styleable#View_backgroundTint
17323     * @see #setBackgroundTintList(ColorStateList)
17324     */
17325    @Nullable
17326    public ColorStateList getBackgroundTintList() {
17327        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
17328    }
17329
17330    /**
17331     * Specifies the blending mode used to apply the tint specified by
17332     * {@link #setBackgroundTintList(ColorStateList)}} to the background
17333     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17334     *
17335     * @param tintMode the blending mode used to apply the tint, may be
17336     *                 {@code null} to clear tint
17337     * @attr ref android.R.styleable#View_backgroundTintMode
17338     * @see #getBackgroundTintMode()
17339     * @see Drawable#setTintMode(PorterDuff.Mode)
17340     */
17341    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17342        if (mBackgroundTint == null) {
17343            mBackgroundTint = new TintInfo();
17344        }
17345        mBackgroundTint.mTintMode = tintMode;
17346        mBackgroundTint.mHasTintMode = true;
17347
17348        applyBackgroundTint();
17349    }
17350
17351    /**
17352     * Return the blending mode used to apply the tint to the background
17353     * drawable, if specified.
17354     *
17355     * @return the blending mode used to apply the tint to the background
17356     *         drawable
17357     * @attr ref android.R.styleable#View_backgroundTintMode
17358     * @see #setBackgroundTintMode(PorterDuff.Mode)
17359     */
17360    @Nullable
17361    public PorterDuff.Mode getBackgroundTintMode() {
17362        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
17363    }
17364
17365    private void applyBackgroundTint() {
17366        if (mBackground != null && mBackgroundTint != null) {
17367            final TintInfo tintInfo = mBackgroundTint;
17368            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17369                mBackground = mBackground.mutate();
17370
17371                if (tintInfo.mHasTintList) {
17372                    mBackground.setTintList(tintInfo.mTintList);
17373                }
17374
17375                if (tintInfo.mHasTintMode) {
17376                    mBackground.setTintMode(tintInfo.mTintMode);
17377                }
17378
17379                // The drawable (or one of its children) may not have been
17380                // stateful before applying the tint, so let's try again.
17381                if (mBackground.isStateful()) {
17382                    mBackground.setState(getDrawableState());
17383                }
17384            }
17385        }
17386    }
17387
17388    /**
17389     * Returns the drawable used as the foreground of this View. The
17390     * foreground drawable, if non-null, is always drawn on top of the view's content.
17391     *
17392     * @return a Drawable or null if no foreground was set
17393     *
17394     * @see #onDrawForeground(Canvas)
17395     */
17396    public Drawable getForeground() {
17397        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17398    }
17399
17400    /**
17401     * Supply a Drawable that is to be rendered on top of all of the content in the view.
17402     *
17403     * @param foreground the Drawable to be drawn on top of the children
17404     *
17405     * @attr ref android.R.styleable#View_foreground
17406     */
17407    public void setForeground(Drawable foreground) {
17408        if (mForegroundInfo == null) {
17409            if (foreground == null) {
17410                // Nothing to do.
17411                return;
17412            }
17413            mForegroundInfo = new ForegroundInfo();
17414        }
17415
17416        if (foreground == mForegroundInfo.mDrawable) {
17417            // Nothing to do
17418            return;
17419        }
17420
17421        if (mForegroundInfo.mDrawable != null) {
17422            mForegroundInfo.mDrawable.setCallback(null);
17423            unscheduleDrawable(mForegroundInfo.mDrawable);
17424        }
17425
17426        mForegroundInfo.mDrawable = foreground;
17427        mForegroundInfo.mBoundsChanged = true;
17428        if (foreground != null) {
17429            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17430                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17431            }
17432            foreground.setCallback(this);
17433            foreground.setLayoutDirection(getLayoutDirection());
17434            if (foreground.isStateful()) {
17435                foreground.setState(getDrawableState());
17436            }
17437            applyForegroundTint();
17438        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
17439            mPrivateFlags |= PFLAG_SKIP_DRAW;
17440        }
17441        requestLayout();
17442        invalidate();
17443    }
17444
17445    /**
17446     * Magic bit used to support features of framework-internal window decor implementation details.
17447     * This used to live exclusively in FrameLayout.
17448     *
17449     * @return true if the foreground should draw inside the padding region or false
17450     *         if it should draw inset by the view's padding
17451     * @hide internal use only; only used by FrameLayout and internal screen layouts.
17452     */
17453    public boolean isForegroundInsidePadding() {
17454        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
17455    }
17456
17457    /**
17458     * Describes how the foreground is positioned.
17459     *
17460     * @return foreground gravity.
17461     *
17462     * @see #setForegroundGravity(int)
17463     *
17464     * @attr ref android.R.styleable#View_foregroundGravity
17465     */
17466    public int getForegroundGravity() {
17467        return mForegroundInfo != null ? mForegroundInfo.mGravity
17468                : Gravity.START | Gravity.TOP;
17469    }
17470
17471    /**
17472     * Describes how the foreground is positioned. Defaults to START and TOP.
17473     *
17474     * @param gravity see {@link android.view.Gravity}
17475     *
17476     * @see #getForegroundGravity()
17477     *
17478     * @attr ref android.R.styleable#View_foregroundGravity
17479     */
17480    public void setForegroundGravity(int gravity) {
17481        if (mForegroundInfo == null) {
17482            mForegroundInfo = new ForegroundInfo();
17483        }
17484
17485        if (mForegroundInfo.mGravity != gravity) {
17486            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
17487                gravity |= Gravity.START;
17488            }
17489
17490            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
17491                gravity |= Gravity.TOP;
17492            }
17493
17494            mForegroundInfo.mGravity = gravity;
17495            requestLayout();
17496        }
17497    }
17498
17499    /**
17500     * Applies a tint to the foreground drawable. Does not modify the current tint
17501     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17502     * <p>
17503     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
17504     * mutate the drawable and apply the specified tint and tint mode using
17505     * {@link Drawable#setTintList(ColorStateList)}.
17506     *
17507     * @param tint the tint to apply, may be {@code null} to clear tint
17508     *
17509     * @attr ref android.R.styleable#View_foregroundTint
17510     * @see #getForegroundTintList()
17511     * @see Drawable#setTintList(ColorStateList)
17512     */
17513    public void setForegroundTintList(@Nullable ColorStateList tint) {
17514        if (mForegroundInfo == null) {
17515            mForegroundInfo = new ForegroundInfo();
17516        }
17517        if (mForegroundInfo.mTintInfo == null) {
17518            mForegroundInfo.mTintInfo = new TintInfo();
17519        }
17520        mForegroundInfo.mTintInfo.mTintList = tint;
17521        mForegroundInfo.mTintInfo.mHasTintList = true;
17522
17523        applyForegroundTint();
17524    }
17525
17526    /**
17527     * Return the tint applied to the foreground drawable, if specified.
17528     *
17529     * @return the tint applied to the foreground drawable
17530     * @attr ref android.R.styleable#View_foregroundTint
17531     * @see #setForegroundTintList(ColorStateList)
17532     */
17533    @Nullable
17534    public ColorStateList getForegroundTintList() {
17535        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17536                ? mForegroundInfo.mTintInfo.mTintList : null;
17537    }
17538
17539    /**
17540     * Specifies the blending mode used to apply the tint specified by
17541     * {@link #setForegroundTintList(ColorStateList)}} to the background
17542     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17543     *
17544     * @param tintMode the blending mode used to apply the tint, may be
17545     *                 {@code null} to clear tint
17546     * @attr ref android.R.styleable#View_foregroundTintMode
17547     * @see #getForegroundTintMode()
17548     * @see Drawable#setTintMode(PorterDuff.Mode)
17549     */
17550    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17551        if (mBackgroundTint == null) {
17552            mBackgroundTint = new TintInfo();
17553        }
17554        mBackgroundTint.mTintMode = tintMode;
17555        mBackgroundTint.mHasTintMode = true;
17556
17557        applyBackgroundTint();
17558    }
17559
17560    /**
17561     * Return the blending mode used to apply the tint to the foreground
17562     * drawable, if specified.
17563     *
17564     * @return the blending mode used to apply the tint to the foreground
17565     *         drawable
17566     * @attr ref android.R.styleable#View_foregroundTintMode
17567     * @see #setBackgroundTintMode(PorterDuff.Mode)
17568     */
17569    @Nullable
17570    public PorterDuff.Mode getForegroundTintMode() {
17571        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17572                ? mForegroundInfo.mTintInfo.mTintMode : null;
17573    }
17574
17575    private void applyForegroundTint() {
17576        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
17577                && mForegroundInfo.mTintInfo != null) {
17578            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
17579            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17580                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
17581
17582                if (tintInfo.mHasTintList) {
17583                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
17584                }
17585
17586                if (tintInfo.mHasTintMode) {
17587                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
17588                }
17589
17590                // The drawable (or one of its children) may not have been
17591                // stateful before applying the tint, so let's try again.
17592                if (mForegroundInfo.mDrawable.isStateful()) {
17593                    mForegroundInfo.mDrawable.setState(getDrawableState());
17594                }
17595            }
17596        }
17597    }
17598
17599    /**
17600     * Draw any foreground content for this view.
17601     *
17602     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
17603     * drawable or other view-specific decorations. The foreground is drawn on top of the
17604     * primary view content.</p>
17605     *
17606     * @param canvas canvas to draw into
17607     */
17608    public void onDrawForeground(Canvas canvas) {
17609        onDrawScrollIndicators(canvas);
17610        onDrawScrollBars(canvas);
17611
17612        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17613        if (foreground != null) {
17614            if (mForegroundInfo.mBoundsChanged) {
17615                mForegroundInfo.mBoundsChanged = false;
17616                final Rect selfBounds = mForegroundInfo.mSelfBounds;
17617                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17618
17619                if (mForegroundInfo.mInsidePadding) {
17620                    selfBounds.set(0, 0, getWidth(), getHeight());
17621                } else {
17622                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
17623                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17624                }
17625
17626                final int ld = getLayoutDirection();
17627                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17628                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17629                foreground.setBounds(overlayBounds);
17630            }
17631
17632            foreground.draw(canvas);
17633        }
17634    }
17635
17636    /**
17637     * Sets the padding. The view may add on the space required to display
17638     * the scrollbars, depending on the style and visibility of the scrollbars.
17639     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17640     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17641     * from the values set in this call.
17642     *
17643     * @attr ref android.R.styleable#View_padding
17644     * @attr ref android.R.styleable#View_paddingBottom
17645     * @attr ref android.R.styleable#View_paddingLeft
17646     * @attr ref android.R.styleable#View_paddingRight
17647     * @attr ref android.R.styleable#View_paddingTop
17648     * @param left the left padding in pixels
17649     * @param top the top padding in pixels
17650     * @param right the right padding in pixels
17651     * @param bottom the bottom padding in pixels
17652     */
17653    public void setPadding(int left, int top, int right, int bottom) {
17654        resetResolvedPaddingInternal();
17655
17656        mUserPaddingStart = UNDEFINED_PADDING;
17657        mUserPaddingEnd = UNDEFINED_PADDING;
17658
17659        mUserPaddingLeftInitial = left;
17660        mUserPaddingRightInitial = right;
17661
17662        mLeftPaddingDefined = true;
17663        mRightPaddingDefined = true;
17664
17665        internalSetPadding(left, top, right, bottom);
17666    }
17667
17668    /**
17669     * @hide
17670     */
17671    protected void internalSetPadding(int left, int top, int right, int bottom) {
17672        mUserPaddingLeft = left;
17673        mUserPaddingRight = right;
17674        mUserPaddingBottom = bottom;
17675
17676        final int viewFlags = mViewFlags;
17677        boolean changed = false;
17678
17679        // Common case is there are no scroll bars.
17680        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
17681            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
17682                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
17683                        ? 0 : getVerticalScrollbarWidth();
17684                switch (mVerticalScrollbarPosition) {
17685                    case SCROLLBAR_POSITION_DEFAULT:
17686                        if (isLayoutRtl()) {
17687                            left += offset;
17688                        } else {
17689                            right += offset;
17690                        }
17691                        break;
17692                    case SCROLLBAR_POSITION_RIGHT:
17693                        right += offset;
17694                        break;
17695                    case SCROLLBAR_POSITION_LEFT:
17696                        left += offset;
17697                        break;
17698                }
17699            }
17700            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
17701                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
17702                        ? 0 : getHorizontalScrollbarHeight();
17703            }
17704        }
17705
17706        if (mPaddingLeft != left) {
17707            changed = true;
17708            mPaddingLeft = left;
17709        }
17710        if (mPaddingTop != top) {
17711            changed = true;
17712            mPaddingTop = top;
17713        }
17714        if (mPaddingRight != right) {
17715            changed = true;
17716            mPaddingRight = right;
17717        }
17718        if (mPaddingBottom != bottom) {
17719            changed = true;
17720            mPaddingBottom = bottom;
17721        }
17722
17723        if (changed) {
17724            requestLayout();
17725            invalidateOutline();
17726        }
17727    }
17728
17729    /**
17730     * Sets the relative padding. The view may add on the space required to display
17731     * the scrollbars, depending on the style and visibility of the scrollbars.
17732     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
17733     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
17734     * from the values set in this call.
17735     *
17736     * @attr ref android.R.styleable#View_padding
17737     * @attr ref android.R.styleable#View_paddingBottom
17738     * @attr ref android.R.styleable#View_paddingStart
17739     * @attr ref android.R.styleable#View_paddingEnd
17740     * @attr ref android.R.styleable#View_paddingTop
17741     * @param start the start padding in pixels
17742     * @param top the top padding in pixels
17743     * @param end the end padding in pixels
17744     * @param bottom the bottom padding in pixels
17745     */
17746    public void setPaddingRelative(int start, int top, int end, int bottom) {
17747        resetResolvedPaddingInternal();
17748
17749        mUserPaddingStart = start;
17750        mUserPaddingEnd = end;
17751        mLeftPaddingDefined = true;
17752        mRightPaddingDefined = true;
17753
17754        switch(getLayoutDirection()) {
17755            case LAYOUT_DIRECTION_RTL:
17756                mUserPaddingLeftInitial = end;
17757                mUserPaddingRightInitial = start;
17758                internalSetPadding(end, top, start, bottom);
17759                break;
17760            case LAYOUT_DIRECTION_LTR:
17761            default:
17762                mUserPaddingLeftInitial = start;
17763                mUserPaddingRightInitial = end;
17764                internalSetPadding(start, top, end, bottom);
17765        }
17766    }
17767
17768    /**
17769     * Returns the top padding of this view.
17770     *
17771     * @return the top padding in pixels
17772     */
17773    public int getPaddingTop() {
17774        return mPaddingTop;
17775    }
17776
17777    /**
17778     * Returns the bottom padding of this view. If there are inset and enabled
17779     * scrollbars, this value may include the space required to display the
17780     * scrollbars as well.
17781     *
17782     * @return the bottom padding in pixels
17783     */
17784    public int getPaddingBottom() {
17785        return mPaddingBottom;
17786    }
17787
17788    /**
17789     * Returns the left padding of this view. If there are inset and enabled
17790     * scrollbars, this value may include the space required to display the
17791     * scrollbars as well.
17792     *
17793     * @return the left padding in pixels
17794     */
17795    public int getPaddingLeft() {
17796        if (!isPaddingResolved()) {
17797            resolvePadding();
17798        }
17799        return mPaddingLeft;
17800    }
17801
17802    /**
17803     * Returns the start padding of this view depending on its resolved layout direction.
17804     * If there are inset and enabled scrollbars, this value may include the space
17805     * required to display the scrollbars as well.
17806     *
17807     * @return the start padding in pixels
17808     */
17809    public int getPaddingStart() {
17810        if (!isPaddingResolved()) {
17811            resolvePadding();
17812        }
17813        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17814                mPaddingRight : mPaddingLeft;
17815    }
17816
17817    /**
17818     * Returns the right padding of this view. If there are inset and enabled
17819     * scrollbars, this value may include the space required to display the
17820     * scrollbars as well.
17821     *
17822     * @return the right padding in pixels
17823     */
17824    public int getPaddingRight() {
17825        if (!isPaddingResolved()) {
17826            resolvePadding();
17827        }
17828        return mPaddingRight;
17829    }
17830
17831    /**
17832     * Returns the end padding of this view depending on its resolved layout direction.
17833     * If there are inset and enabled scrollbars, this value may include the space
17834     * required to display the scrollbars as well.
17835     *
17836     * @return the end padding in pixels
17837     */
17838    public int getPaddingEnd() {
17839        if (!isPaddingResolved()) {
17840            resolvePadding();
17841        }
17842        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17843                mPaddingLeft : mPaddingRight;
17844    }
17845
17846    /**
17847     * Return if the padding has been set through relative values
17848     * {@link #setPaddingRelative(int, int, int, int)} or through
17849     * @attr ref android.R.styleable#View_paddingStart or
17850     * @attr ref android.R.styleable#View_paddingEnd
17851     *
17852     * @return true if the padding is relative or false if it is not.
17853     */
17854    public boolean isPaddingRelative() {
17855        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
17856    }
17857
17858    Insets computeOpticalInsets() {
17859        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
17860    }
17861
17862    /**
17863     * @hide
17864     */
17865    public void resetPaddingToInitialValues() {
17866        if (isRtlCompatibilityMode()) {
17867            mPaddingLeft = mUserPaddingLeftInitial;
17868            mPaddingRight = mUserPaddingRightInitial;
17869            return;
17870        }
17871        if (isLayoutRtl()) {
17872            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
17873            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
17874        } else {
17875            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
17876            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
17877        }
17878    }
17879
17880    /**
17881     * @hide
17882     */
17883    public Insets getOpticalInsets() {
17884        if (mLayoutInsets == null) {
17885            mLayoutInsets = computeOpticalInsets();
17886        }
17887        return mLayoutInsets;
17888    }
17889
17890    /**
17891     * Set this view's optical insets.
17892     *
17893     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
17894     * property. Views that compute their own optical insets should call it as part of measurement.
17895     * This method does not request layout. If you are setting optical insets outside of
17896     * measure/layout itself you will want to call requestLayout() yourself.
17897     * </p>
17898     * @hide
17899     */
17900    public void setOpticalInsets(Insets insets) {
17901        mLayoutInsets = insets;
17902    }
17903
17904    /**
17905     * Changes the selection state of this view. A view can be selected or not.
17906     * Note that selection is not the same as focus. Views are typically
17907     * selected in the context of an AdapterView like ListView or GridView;
17908     * the selected view is the view that is highlighted.
17909     *
17910     * @param selected true if the view must be selected, false otherwise
17911     */
17912    public void setSelected(boolean selected) {
17913        //noinspection DoubleNegation
17914        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
17915            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
17916            if (!selected) resetPressedState();
17917            invalidate(true);
17918            refreshDrawableState();
17919            dispatchSetSelected(selected);
17920            if (selected) {
17921                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
17922            } else {
17923                notifyViewAccessibilityStateChangedIfNeeded(
17924                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17925            }
17926        }
17927    }
17928
17929    /**
17930     * Dispatch setSelected to all of this View's children.
17931     *
17932     * @see #setSelected(boolean)
17933     *
17934     * @param selected The new selected state
17935     */
17936    protected void dispatchSetSelected(boolean selected) {
17937    }
17938
17939    /**
17940     * Indicates the selection state of this view.
17941     *
17942     * @return true if the view is selected, false otherwise
17943     */
17944    @ViewDebug.ExportedProperty
17945    public boolean isSelected() {
17946        return (mPrivateFlags & PFLAG_SELECTED) != 0;
17947    }
17948
17949    /**
17950     * Changes the activated state of this view. A view can be activated or not.
17951     * Note that activation is not the same as selection.  Selection is
17952     * a transient property, representing the view (hierarchy) the user is
17953     * currently interacting with.  Activation is a longer-term state that the
17954     * user can move views in and out of.  For example, in a list view with
17955     * single or multiple selection enabled, the views in the current selection
17956     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
17957     * here.)  The activated state is propagated down to children of the view it
17958     * is set on.
17959     *
17960     * @param activated true if the view must be activated, false otherwise
17961     */
17962    public void setActivated(boolean activated) {
17963        //noinspection DoubleNegation
17964        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
17965            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
17966            invalidate(true);
17967            refreshDrawableState();
17968            dispatchSetActivated(activated);
17969        }
17970    }
17971
17972    /**
17973     * Dispatch setActivated to all of this View's children.
17974     *
17975     * @see #setActivated(boolean)
17976     *
17977     * @param activated The new activated state
17978     */
17979    protected void dispatchSetActivated(boolean activated) {
17980    }
17981
17982    /**
17983     * Indicates the activation state of this view.
17984     *
17985     * @return true if the view is activated, false otherwise
17986     */
17987    @ViewDebug.ExportedProperty
17988    public boolean isActivated() {
17989        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
17990    }
17991
17992    /**
17993     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
17994     * observer can be used to get notifications when global events, like
17995     * layout, happen.
17996     *
17997     * The returned ViewTreeObserver observer is not guaranteed to remain
17998     * valid for the lifetime of this View. If the caller of this method keeps
17999     * a long-lived reference to ViewTreeObserver, it should always check for
18000     * the return value of {@link ViewTreeObserver#isAlive()}.
18001     *
18002     * @return The ViewTreeObserver for this view's hierarchy.
18003     */
18004    public ViewTreeObserver getViewTreeObserver() {
18005        if (mAttachInfo != null) {
18006            return mAttachInfo.mTreeObserver;
18007        }
18008        if (mFloatingTreeObserver == null) {
18009            mFloatingTreeObserver = new ViewTreeObserver();
18010        }
18011        return mFloatingTreeObserver;
18012    }
18013
18014    /**
18015     * <p>Finds the topmost view in the current view hierarchy.</p>
18016     *
18017     * @return the topmost view containing this view
18018     */
18019    public View getRootView() {
18020        if (mAttachInfo != null) {
18021            final View v = mAttachInfo.mRootView;
18022            if (v != null) {
18023                return v;
18024            }
18025        }
18026
18027        View parent = this;
18028
18029        while (parent.mParent != null && parent.mParent instanceof View) {
18030            parent = (View) parent.mParent;
18031        }
18032
18033        return parent;
18034    }
18035
18036    /**
18037     * Transforms a motion event from view-local coordinates to on-screen
18038     * coordinates.
18039     *
18040     * @param ev the view-local motion event
18041     * @return false if the transformation could not be applied
18042     * @hide
18043     */
18044    public boolean toGlobalMotionEvent(MotionEvent ev) {
18045        final AttachInfo info = mAttachInfo;
18046        if (info == null) {
18047            return false;
18048        }
18049
18050        final Matrix m = info.mTmpMatrix;
18051        m.set(Matrix.IDENTITY_MATRIX);
18052        transformMatrixToGlobal(m);
18053        ev.transform(m);
18054        return true;
18055    }
18056
18057    /**
18058     * Transforms a motion event from on-screen coordinates to view-local
18059     * coordinates.
18060     *
18061     * @param ev the on-screen motion event
18062     * @return false if the transformation could not be applied
18063     * @hide
18064     */
18065    public boolean toLocalMotionEvent(MotionEvent ev) {
18066        final AttachInfo info = mAttachInfo;
18067        if (info == null) {
18068            return false;
18069        }
18070
18071        final Matrix m = info.mTmpMatrix;
18072        m.set(Matrix.IDENTITY_MATRIX);
18073        transformMatrixToLocal(m);
18074        ev.transform(m);
18075        return true;
18076    }
18077
18078    /**
18079     * Modifies the input matrix such that it maps view-local coordinates to
18080     * on-screen coordinates.
18081     *
18082     * @param m input matrix to modify
18083     * @hide
18084     */
18085    public void transformMatrixToGlobal(Matrix m) {
18086        final ViewParent parent = mParent;
18087        if (parent instanceof View) {
18088            final View vp = (View) parent;
18089            vp.transformMatrixToGlobal(m);
18090            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
18091        } else if (parent instanceof ViewRootImpl) {
18092            final ViewRootImpl vr = (ViewRootImpl) parent;
18093            vr.transformMatrixToGlobal(m);
18094            m.preTranslate(0, -vr.mCurScrollY);
18095        }
18096
18097        m.preTranslate(mLeft, mTop);
18098
18099        if (!hasIdentityMatrix()) {
18100            m.preConcat(getMatrix());
18101        }
18102    }
18103
18104    /**
18105     * Modifies the input matrix such that it maps on-screen coordinates to
18106     * view-local coordinates.
18107     *
18108     * @param m input matrix to modify
18109     * @hide
18110     */
18111    public void transformMatrixToLocal(Matrix m) {
18112        final ViewParent parent = mParent;
18113        if (parent instanceof View) {
18114            final View vp = (View) parent;
18115            vp.transformMatrixToLocal(m);
18116            m.postTranslate(vp.mScrollX, vp.mScrollY);
18117        } else if (parent instanceof ViewRootImpl) {
18118            final ViewRootImpl vr = (ViewRootImpl) parent;
18119            vr.transformMatrixToLocal(m);
18120            m.postTranslate(0, vr.mCurScrollY);
18121        }
18122
18123        m.postTranslate(-mLeft, -mTop);
18124
18125        if (!hasIdentityMatrix()) {
18126            m.postConcat(getInverseMatrix());
18127        }
18128    }
18129
18130    /**
18131     * @hide
18132     */
18133    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
18134            @ViewDebug.IntToString(from = 0, to = "x"),
18135            @ViewDebug.IntToString(from = 1, to = "y")
18136    })
18137    public int[] getLocationOnScreen() {
18138        int[] location = new int[2];
18139        getLocationOnScreen(location);
18140        return location;
18141    }
18142
18143    /**
18144     * <p>Computes the coordinates of this view on the screen. The argument
18145     * must be an array of two integers. After the method returns, the array
18146     * contains the x and y location in that order.</p>
18147     *
18148     * @param location an array of two integers in which to hold the coordinates
18149     */
18150    public void getLocationOnScreen(@Size(2) int[] location) {
18151        getLocationInWindow(location);
18152
18153        final AttachInfo info = mAttachInfo;
18154        if (info != null) {
18155            location[0] += info.mWindowLeft;
18156            location[1] += info.mWindowTop;
18157        }
18158    }
18159
18160    /**
18161     * <p>Computes the coordinates of this view in its window. The argument
18162     * must be an array of two integers. After the method returns, the array
18163     * contains the x and y location in that order.</p>
18164     *
18165     * @param location an array of two integers in which to hold the coordinates
18166     */
18167    public void getLocationInWindow(@Size(2) int[] location) {
18168        if (location == null || location.length < 2) {
18169            throw new IllegalArgumentException("location must be an array of two integers");
18170        }
18171
18172        if (mAttachInfo == null) {
18173            // When the view is not attached to a window, this method does not make sense
18174            location[0] = location[1] = 0;
18175            return;
18176        }
18177
18178        float[] position = mAttachInfo.mTmpTransformLocation;
18179        position[0] = position[1] = 0.0f;
18180
18181        if (!hasIdentityMatrix()) {
18182            getMatrix().mapPoints(position);
18183        }
18184
18185        position[0] += mLeft;
18186        position[1] += mTop;
18187
18188        ViewParent viewParent = mParent;
18189        while (viewParent instanceof View) {
18190            final View view = (View) viewParent;
18191
18192            position[0] -= view.mScrollX;
18193            position[1] -= view.mScrollY;
18194
18195            if (!view.hasIdentityMatrix()) {
18196                view.getMatrix().mapPoints(position);
18197            }
18198
18199            position[0] += view.mLeft;
18200            position[1] += view.mTop;
18201
18202            viewParent = view.mParent;
18203         }
18204
18205        if (viewParent instanceof ViewRootImpl) {
18206            // *cough*
18207            final ViewRootImpl vr = (ViewRootImpl) viewParent;
18208            position[1] -= vr.mCurScrollY;
18209        }
18210
18211        location[0] = (int) (position[0] + 0.5f);
18212        location[1] = (int) (position[1] + 0.5f);
18213    }
18214
18215    /**
18216     * {@hide}
18217     * @param id the id of the view to be found
18218     * @return the view of the specified id, null if cannot be found
18219     */
18220    protected View findViewTraversal(@IdRes int id) {
18221        if (id == mID) {
18222            return this;
18223        }
18224        return null;
18225    }
18226
18227    /**
18228     * {@hide}
18229     * @param tag the tag of the view to be found
18230     * @return the view of specified tag, null if cannot be found
18231     */
18232    protected View findViewWithTagTraversal(Object tag) {
18233        if (tag != null && tag.equals(mTag)) {
18234            return this;
18235        }
18236        return null;
18237    }
18238
18239    /**
18240     * {@hide}
18241     * @param predicate The predicate to evaluate.
18242     * @param childToSkip If not null, ignores this child during the recursive traversal.
18243     * @return The first view that matches the predicate or null.
18244     */
18245    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
18246        if (predicate.apply(this)) {
18247            return this;
18248        }
18249        return null;
18250    }
18251
18252    /**
18253     * Look for a child view with the given id.  If this view has the given
18254     * id, return this view.
18255     *
18256     * @param id The id to search for.
18257     * @return The view that has the given id in the hierarchy or null
18258     */
18259    @Nullable
18260    public final View findViewById(@IdRes int id) {
18261        if (id < 0) {
18262            return null;
18263        }
18264        return findViewTraversal(id);
18265    }
18266
18267    /**
18268     * Finds a view by its unuque and stable accessibility id.
18269     *
18270     * @param accessibilityId The searched accessibility id.
18271     * @return The found view.
18272     */
18273    final View findViewByAccessibilityId(int accessibilityId) {
18274        if (accessibilityId < 0) {
18275            return null;
18276        }
18277        return findViewByAccessibilityIdTraversal(accessibilityId);
18278    }
18279
18280    /**
18281     * Performs the traversal to find a view by its unuque and stable accessibility id.
18282     *
18283     * <strong>Note:</strong>This method does not stop at the root namespace
18284     * boundary since the user can touch the screen at an arbitrary location
18285     * potentially crossing the root namespace bounday which will send an
18286     * accessibility event to accessibility services and they should be able
18287     * to obtain the event source. Also accessibility ids are guaranteed to be
18288     * unique in the window.
18289     *
18290     * @param accessibilityId The accessibility id.
18291     * @return The found view.
18292     *
18293     * @hide
18294     */
18295    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
18296        if (getAccessibilityViewId() == accessibilityId) {
18297            return this;
18298        }
18299        return null;
18300    }
18301
18302    /**
18303     * Look for a child view with the given tag.  If this view has the given
18304     * tag, return this view.
18305     *
18306     * @param tag The tag to search for, using "tag.equals(getTag())".
18307     * @return The View that has the given tag in the hierarchy or null
18308     */
18309    public final View findViewWithTag(Object tag) {
18310        if (tag == null) {
18311            return null;
18312        }
18313        return findViewWithTagTraversal(tag);
18314    }
18315
18316    /**
18317     * {@hide}
18318     * Look for a child view that matches the specified predicate.
18319     * If this view matches the predicate, return this view.
18320     *
18321     * @param predicate The predicate to evaluate.
18322     * @return The first view that matches the predicate or null.
18323     */
18324    public final View findViewByPredicate(Predicate<View> predicate) {
18325        return findViewByPredicateTraversal(predicate, null);
18326    }
18327
18328    /**
18329     * {@hide}
18330     * Look for a child view that matches the specified predicate,
18331     * starting with the specified view and its descendents and then
18332     * recusively searching the ancestors and siblings of that view
18333     * until this view is reached.
18334     *
18335     * This method is useful in cases where the predicate does not match
18336     * a single unique view (perhaps multiple views use the same id)
18337     * and we are trying to find the view that is "closest" in scope to the
18338     * starting view.
18339     *
18340     * @param start The view to start from.
18341     * @param predicate The predicate to evaluate.
18342     * @return The first view that matches the predicate or null.
18343     */
18344    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
18345        View childToSkip = null;
18346        for (;;) {
18347            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
18348            if (view != null || start == this) {
18349                return view;
18350            }
18351
18352            ViewParent parent = start.getParent();
18353            if (parent == null || !(parent instanceof View)) {
18354                return null;
18355            }
18356
18357            childToSkip = start;
18358            start = (View) parent;
18359        }
18360    }
18361
18362    /**
18363     * Sets the identifier for this view. The identifier does not have to be
18364     * unique in this view's hierarchy. The identifier should be a positive
18365     * number.
18366     *
18367     * @see #NO_ID
18368     * @see #getId()
18369     * @see #findViewById(int)
18370     *
18371     * @param id a number used to identify the view
18372     *
18373     * @attr ref android.R.styleable#View_id
18374     */
18375    public void setId(@IdRes int id) {
18376        mID = id;
18377        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
18378            mID = generateViewId();
18379        }
18380    }
18381
18382    /**
18383     * {@hide}
18384     *
18385     * @param isRoot true if the view belongs to the root namespace, false
18386     *        otherwise
18387     */
18388    public void setIsRootNamespace(boolean isRoot) {
18389        if (isRoot) {
18390            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
18391        } else {
18392            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
18393        }
18394    }
18395
18396    /**
18397     * {@hide}
18398     *
18399     * @return true if the view belongs to the root namespace, false otherwise
18400     */
18401    public boolean isRootNamespace() {
18402        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
18403    }
18404
18405    /**
18406     * Returns this view's identifier.
18407     *
18408     * @return a positive integer used to identify the view or {@link #NO_ID}
18409     *         if the view has no ID
18410     *
18411     * @see #setId(int)
18412     * @see #findViewById(int)
18413     * @attr ref android.R.styleable#View_id
18414     */
18415    @IdRes
18416    @ViewDebug.CapturedViewProperty
18417    public int getId() {
18418        return mID;
18419    }
18420
18421    /**
18422     * Returns this view's tag.
18423     *
18424     * @return the Object stored in this view as a tag, or {@code null} if not
18425     *         set
18426     *
18427     * @see #setTag(Object)
18428     * @see #getTag(int)
18429     */
18430    @ViewDebug.ExportedProperty
18431    public Object getTag() {
18432        return mTag;
18433    }
18434
18435    /**
18436     * Sets the tag associated with this view. A tag can be used to mark
18437     * a view in its hierarchy and does not have to be unique within the
18438     * hierarchy. Tags can also be used to store data within a view without
18439     * resorting to another data structure.
18440     *
18441     * @param tag an Object to tag the view with
18442     *
18443     * @see #getTag()
18444     * @see #setTag(int, Object)
18445     */
18446    public void setTag(final Object tag) {
18447        mTag = tag;
18448    }
18449
18450    /**
18451     * Returns the tag associated with this view and the specified key.
18452     *
18453     * @param key The key identifying the tag
18454     *
18455     * @return the Object stored in this view as a tag, or {@code null} if not
18456     *         set
18457     *
18458     * @see #setTag(int, Object)
18459     * @see #getTag()
18460     */
18461    public Object getTag(int key) {
18462        if (mKeyedTags != null) return mKeyedTags.get(key);
18463        return null;
18464    }
18465
18466    /**
18467     * Sets a tag associated with this view and a key. A tag can be used
18468     * to mark a view in its hierarchy and does not have to be unique within
18469     * the hierarchy. Tags can also be used to store data within a view
18470     * without resorting to another data structure.
18471     *
18472     * The specified key should be an id declared in the resources of the
18473     * application to ensure it is unique (see the <a
18474     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
18475     * Keys identified as belonging to
18476     * the Android framework or not associated with any package will cause
18477     * an {@link IllegalArgumentException} to be thrown.
18478     *
18479     * @param key The key identifying the tag
18480     * @param tag An Object to tag the view with
18481     *
18482     * @throws IllegalArgumentException If they specified key is not valid
18483     *
18484     * @see #setTag(Object)
18485     * @see #getTag(int)
18486     */
18487    public void setTag(int key, final Object tag) {
18488        // If the package id is 0x00 or 0x01, it's either an undefined package
18489        // or a framework id
18490        if ((key >>> 24) < 2) {
18491            throw new IllegalArgumentException("The key must be an application-specific "
18492                    + "resource id.");
18493        }
18494
18495        setKeyedTag(key, tag);
18496    }
18497
18498    /**
18499     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
18500     * framework id.
18501     *
18502     * @hide
18503     */
18504    public void setTagInternal(int key, Object tag) {
18505        if ((key >>> 24) != 0x1) {
18506            throw new IllegalArgumentException("The key must be a framework-specific "
18507                    + "resource id.");
18508        }
18509
18510        setKeyedTag(key, tag);
18511    }
18512
18513    private void setKeyedTag(int key, Object tag) {
18514        if (mKeyedTags == null) {
18515            mKeyedTags = new SparseArray<Object>(2);
18516        }
18517
18518        mKeyedTags.put(key, tag);
18519    }
18520
18521    /**
18522     * Prints information about this view in the log output, with the tag
18523     * {@link #VIEW_LOG_TAG}.
18524     *
18525     * @hide
18526     */
18527    public void debug() {
18528        debug(0);
18529    }
18530
18531    /**
18532     * Prints information about this view in the log output, with the tag
18533     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18534     * indentation defined by the <code>depth</code>.
18535     *
18536     * @param depth the indentation level
18537     *
18538     * @hide
18539     */
18540    protected void debug(int depth) {
18541        String output = debugIndent(depth - 1);
18542
18543        output += "+ " + this;
18544        int id = getId();
18545        if (id != -1) {
18546            output += " (id=" + id + ")";
18547        }
18548        Object tag = getTag();
18549        if (tag != null) {
18550            output += " (tag=" + tag + ")";
18551        }
18552        Log.d(VIEW_LOG_TAG, output);
18553
18554        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18555            output = debugIndent(depth) + " FOCUSED";
18556            Log.d(VIEW_LOG_TAG, output);
18557        }
18558
18559        output = debugIndent(depth);
18560        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
18561                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
18562                + "} ";
18563        Log.d(VIEW_LOG_TAG, output);
18564
18565        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
18566                || mPaddingBottom != 0) {
18567            output = debugIndent(depth);
18568            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
18569                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
18570            Log.d(VIEW_LOG_TAG, output);
18571        }
18572
18573        output = debugIndent(depth);
18574        output += "mMeasureWidth=" + mMeasuredWidth +
18575                " mMeasureHeight=" + mMeasuredHeight;
18576        Log.d(VIEW_LOG_TAG, output);
18577
18578        output = debugIndent(depth);
18579        if (mLayoutParams == null) {
18580            output += "BAD! no layout params";
18581        } else {
18582            output = mLayoutParams.debug(output);
18583        }
18584        Log.d(VIEW_LOG_TAG, output);
18585
18586        output = debugIndent(depth);
18587        output += "flags={";
18588        output += View.printFlags(mViewFlags);
18589        output += "}";
18590        Log.d(VIEW_LOG_TAG, output);
18591
18592        output = debugIndent(depth);
18593        output += "privateFlags={";
18594        output += View.printPrivateFlags(mPrivateFlags);
18595        output += "}";
18596        Log.d(VIEW_LOG_TAG, output);
18597    }
18598
18599    /**
18600     * Creates a string of whitespaces used for indentation.
18601     *
18602     * @param depth the indentation level
18603     * @return a String containing (depth * 2 + 3) * 2 white spaces
18604     *
18605     * @hide
18606     */
18607    protected static String debugIndent(int depth) {
18608        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
18609        for (int i = 0; i < (depth * 2) + 3; i++) {
18610            spaces.append(' ').append(' ');
18611        }
18612        return spaces.toString();
18613    }
18614
18615    /**
18616     * <p>Return the offset of the widget's text baseline from the widget's top
18617     * boundary. If this widget does not support baseline alignment, this
18618     * method returns -1. </p>
18619     *
18620     * @return the offset of the baseline within the widget's bounds or -1
18621     *         if baseline alignment is not supported
18622     */
18623    @ViewDebug.ExportedProperty(category = "layout")
18624    public int getBaseline() {
18625        return -1;
18626    }
18627
18628    /**
18629     * Returns whether the view hierarchy is currently undergoing a layout pass. This
18630     * information is useful to avoid situations such as calling {@link #requestLayout()} during
18631     * a layout pass.
18632     *
18633     * @return whether the view hierarchy is currently undergoing a layout pass
18634     */
18635    public boolean isInLayout() {
18636        ViewRootImpl viewRoot = getViewRootImpl();
18637        return (viewRoot != null && viewRoot.isInLayout());
18638    }
18639
18640    /**
18641     * Call this when something has changed which has invalidated the
18642     * layout of this view. This will schedule a layout pass of the view
18643     * tree. This should not be called while the view hierarchy is currently in a layout
18644     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18645     * end of the current layout pass (and then layout will run again) or after the current
18646     * frame is drawn and the next layout occurs.
18647     *
18648     * <p>Subclasses which override this method should call the superclass method to
18649     * handle possible request-during-layout errors correctly.</p>
18650     */
18651    @CallSuper
18652    public void requestLayout() {
18653        if (mMeasureCache != null) mMeasureCache.clear();
18654
18655        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
18656            // Only trigger request-during-layout logic if this is the view requesting it,
18657            // not the views in its parent hierarchy
18658            ViewRootImpl viewRoot = getViewRootImpl();
18659            if (viewRoot != null && viewRoot.isInLayout()) {
18660                if (!viewRoot.requestLayoutDuringLayout(this)) {
18661                    return;
18662                }
18663            }
18664            mAttachInfo.mViewRequestingLayout = this;
18665        }
18666
18667        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18668        mPrivateFlags |= PFLAG_INVALIDATED;
18669
18670        if (mParent != null && !mParent.isLayoutRequested()) {
18671            mParent.requestLayout();
18672        }
18673        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
18674            mAttachInfo.mViewRequestingLayout = null;
18675        }
18676    }
18677
18678    /**
18679     * Forces this view to be laid out during the next layout pass.
18680     * This method does not call requestLayout() or forceLayout()
18681     * on the parent.
18682     */
18683    public void forceLayout() {
18684        if (mMeasureCache != null) mMeasureCache.clear();
18685
18686        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18687        mPrivateFlags |= PFLAG_INVALIDATED;
18688    }
18689
18690    /**
18691     * <p>
18692     * This is called to find out how big a view should be. The parent
18693     * supplies constraint information in the width and height parameters.
18694     * </p>
18695     *
18696     * <p>
18697     * The actual measurement work of a view is performed in
18698     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
18699     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
18700     * </p>
18701     *
18702     *
18703     * @param widthMeasureSpec Horizontal space requirements as imposed by the
18704     *        parent
18705     * @param heightMeasureSpec Vertical space requirements as imposed by the
18706     *        parent
18707     *
18708     * @see #onMeasure(int, int)
18709     */
18710    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
18711        boolean optical = isLayoutModeOptical(this);
18712        if (optical != isLayoutModeOptical(mParent)) {
18713            Insets insets = getOpticalInsets();
18714            int oWidth  = insets.left + insets.right;
18715            int oHeight = insets.top  + insets.bottom;
18716            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
18717            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
18718        }
18719
18720        // Suppress sign extension for the low bytes
18721        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
18722        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
18723
18724        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
18725        final boolean isExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY &&
18726                MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
18727        final boolean matchingSize = isExactly &&
18728                getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) &&
18729                getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
18730        if (forceLayout || !matchingSize &&
18731                (widthMeasureSpec != mOldWidthMeasureSpec ||
18732                        heightMeasureSpec != mOldHeightMeasureSpec)) {
18733
18734            // first clears the measured dimension flag
18735            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
18736
18737            resolveRtlPropertiesIfNeeded();
18738
18739            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
18740            if (cacheIndex < 0 || sIgnoreMeasureCache) {
18741                // measure ourselves, this should set the measured dimension flag back
18742                onMeasure(widthMeasureSpec, heightMeasureSpec);
18743                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18744            } else {
18745                long value = mMeasureCache.valueAt(cacheIndex);
18746                // Casting a long to int drops the high 32 bits, no mask needed
18747                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
18748                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18749            }
18750
18751            // flag not set, setMeasuredDimension() was not invoked, we raise
18752            // an exception to warn the developer
18753            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
18754                throw new IllegalStateException("View with id " + getId() + ": "
18755                        + getClass().getName() + "#onMeasure() did not set the"
18756                        + " measured dimension by calling"
18757                        + " setMeasuredDimension()");
18758            }
18759
18760            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
18761        }
18762
18763        mOldWidthMeasureSpec = widthMeasureSpec;
18764        mOldHeightMeasureSpec = heightMeasureSpec;
18765
18766        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
18767                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
18768    }
18769
18770    /**
18771     * <p>
18772     * Measure the view and its content to determine the measured width and the
18773     * measured height. This method is invoked by {@link #measure(int, int)} and
18774     * should be overridden by subclasses to provide accurate and efficient
18775     * measurement of their contents.
18776     * </p>
18777     *
18778     * <p>
18779     * <strong>CONTRACT:</strong> When overriding this method, you
18780     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
18781     * measured width and height of this view. Failure to do so will trigger an
18782     * <code>IllegalStateException</code>, thrown by
18783     * {@link #measure(int, int)}. Calling the superclass'
18784     * {@link #onMeasure(int, int)} is a valid use.
18785     * </p>
18786     *
18787     * <p>
18788     * The base class implementation of measure defaults to the background size,
18789     * unless a larger size is allowed by the MeasureSpec. Subclasses should
18790     * override {@link #onMeasure(int, int)} to provide better measurements of
18791     * their content.
18792     * </p>
18793     *
18794     * <p>
18795     * If this method is overridden, it is the subclass's responsibility to make
18796     * sure the measured height and width are at least the view's minimum height
18797     * and width ({@link #getSuggestedMinimumHeight()} and
18798     * {@link #getSuggestedMinimumWidth()}).
18799     * </p>
18800     *
18801     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
18802     *                         The requirements are encoded with
18803     *                         {@link android.view.View.MeasureSpec}.
18804     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
18805     *                         The requirements are encoded with
18806     *                         {@link android.view.View.MeasureSpec}.
18807     *
18808     * @see #getMeasuredWidth()
18809     * @see #getMeasuredHeight()
18810     * @see #setMeasuredDimension(int, int)
18811     * @see #getSuggestedMinimumHeight()
18812     * @see #getSuggestedMinimumWidth()
18813     * @see android.view.View.MeasureSpec#getMode(int)
18814     * @see android.view.View.MeasureSpec#getSize(int)
18815     */
18816    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
18817        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
18818                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
18819    }
18820
18821    /**
18822     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
18823     * measured width and measured height. Failing to do so will trigger an
18824     * exception at measurement time.</p>
18825     *
18826     * @param measuredWidth The measured width of this view.  May be a complex
18827     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18828     * {@link #MEASURED_STATE_TOO_SMALL}.
18829     * @param measuredHeight The measured height of this view.  May be a complex
18830     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18831     * {@link #MEASURED_STATE_TOO_SMALL}.
18832     */
18833    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
18834        boolean optical = isLayoutModeOptical(this);
18835        if (optical != isLayoutModeOptical(mParent)) {
18836            Insets insets = getOpticalInsets();
18837            int opticalWidth  = insets.left + insets.right;
18838            int opticalHeight = insets.top  + insets.bottom;
18839
18840            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
18841            measuredHeight += optical ? opticalHeight : -opticalHeight;
18842        }
18843        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
18844    }
18845
18846    /**
18847     * Sets the measured dimension without extra processing for things like optical bounds.
18848     * Useful for reapplying consistent values that have already been cooked with adjustments
18849     * for optical bounds, etc. such as those from the measurement cache.
18850     *
18851     * @param measuredWidth The measured width of this view.  May be a complex
18852     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18853     * {@link #MEASURED_STATE_TOO_SMALL}.
18854     * @param measuredHeight The measured height of this view.  May be a complex
18855     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18856     * {@link #MEASURED_STATE_TOO_SMALL}.
18857     */
18858    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
18859        mMeasuredWidth = measuredWidth;
18860        mMeasuredHeight = measuredHeight;
18861
18862        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
18863    }
18864
18865    /**
18866     * Merge two states as returned by {@link #getMeasuredState()}.
18867     * @param curState The current state as returned from a view or the result
18868     * of combining multiple views.
18869     * @param newState The new view state to combine.
18870     * @return Returns a new integer reflecting the combination of the two
18871     * states.
18872     */
18873    public static int combineMeasuredStates(int curState, int newState) {
18874        return curState | newState;
18875    }
18876
18877    /**
18878     * Version of {@link #resolveSizeAndState(int, int, int)}
18879     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
18880     */
18881    public static int resolveSize(int size, int measureSpec) {
18882        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
18883    }
18884
18885    /**
18886     * Utility to reconcile a desired size and state, with constraints imposed
18887     * by a MeasureSpec. Will take the desired size, unless a different size
18888     * is imposed by the constraints. The returned value is a compound integer,
18889     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
18890     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
18891     * resulting size is smaller than the size the view wants to be.
18892     *
18893     * @param size How big the view wants to be.
18894     * @param measureSpec Constraints imposed by the parent.
18895     * @param childMeasuredState Size information bit mask for the view's
18896     *                           children.
18897     * @return Size information bit mask as defined by
18898     *         {@link #MEASURED_SIZE_MASK} and
18899     *         {@link #MEASURED_STATE_TOO_SMALL}.
18900     */
18901    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
18902        final int specMode = MeasureSpec.getMode(measureSpec);
18903        final int specSize = MeasureSpec.getSize(measureSpec);
18904        final int result;
18905        switch (specMode) {
18906            case MeasureSpec.AT_MOST:
18907                if (specSize < size) {
18908                    result = specSize | MEASURED_STATE_TOO_SMALL;
18909                } else {
18910                    result = size;
18911                }
18912                break;
18913            case MeasureSpec.EXACTLY:
18914                result = specSize;
18915                break;
18916            case MeasureSpec.UNSPECIFIED:
18917            default:
18918                result = size;
18919        }
18920        return result | (childMeasuredState & MEASURED_STATE_MASK);
18921    }
18922
18923    /**
18924     * Utility to return a default size. Uses the supplied size if the
18925     * MeasureSpec imposed no constraints. Will get larger if allowed
18926     * by the MeasureSpec.
18927     *
18928     * @param size Default size for this view
18929     * @param measureSpec Constraints imposed by the parent
18930     * @return The size this view should be.
18931     */
18932    public static int getDefaultSize(int size, int measureSpec) {
18933        int result = size;
18934        int specMode = MeasureSpec.getMode(measureSpec);
18935        int specSize = MeasureSpec.getSize(measureSpec);
18936
18937        switch (specMode) {
18938        case MeasureSpec.UNSPECIFIED:
18939            result = size;
18940            break;
18941        case MeasureSpec.AT_MOST:
18942        case MeasureSpec.EXACTLY:
18943            result = specSize;
18944            break;
18945        }
18946        return result;
18947    }
18948
18949    /**
18950     * Returns the suggested minimum height that the view should use. This
18951     * returns the maximum of the view's minimum height
18952     * and the background's minimum height
18953     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
18954     * <p>
18955     * When being used in {@link #onMeasure(int, int)}, the caller should still
18956     * ensure the returned height is within the requirements of the parent.
18957     *
18958     * @return The suggested minimum height of the view.
18959     */
18960    protected int getSuggestedMinimumHeight() {
18961        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
18962
18963    }
18964
18965    /**
18966     * Returns the suggested minimum width that the view should use. This
18967     * returns the maximum of the view's minimum width)
18968     * and the background's minimum width
18969     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
18970     * <p>
18971     * When being used in {@link #onMeasure(int, int)}, the caller should still
18972     * ensure the returned width is within the requirements of the parent.
18973     *
18974     * @return The suggested minimum width of the view.
18975     */
18976    protected int getSuggestedMinimumWidth() {
18977        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
18978    }
18979
18980    /**
18981     * Returns the minimum height of the view.
18982     *
18983     * @return the minimum height the view will try to be.
18984     *
18985     * @see #setMinimumHeight(int)
18986     *
18987     * @attr ref android.R.styleable#View_minHeight
18988     */
18989    public int getMinimumHeight() {
18990        return mMinHeight;
18991    }
18992
18993    /**
18994     * Sets the minimum height of the view. It is not guaranteed the view will
18995     * be able to achieve this minimum height (for example, if its parent layout
18996     * constrains it with less available height).
18997     *
18998     * @param minHeight The minimum height the view will try to be.
18999     *
19000     * @see #getMinimumHeight()
19001     *
19002     * @attr ref android.R.styleable#View_minHeight
19003     */
19004    public void setMinimumHeight(int minHeight) {
19005        mMinHeight = minHeight;
19006        requestLayout();
19007    }
19008
19009    /**
19010     * Returns the minimum width of the view.
19011     *
19012     * @return the minimum width the view will try to be.
19013     *
19014     * @see #setMinimumWidth(int)
19015     *
19016     * @attr ref android.R.styleable#View_minWidth
19017     */
19018    public int getMinimumWidth() {
19019        return mMinWidth;
19020    }
19021
19022    /**
19023     * Sets the minimum width of the view. It is not guaranteed the view will
19024     * be able to achieve this minimum width (for example, if its parent layout
19025     * constrains it with less available width).
19026     *
19027     * @param minWidth The minimum width the view will try to be.
19028     *
19029     * @see #getMinimumWidth()
19030     *
19031     * @attr ref android.R.styleable#View_minWidth
19032     */
19033    public void setMinimumWidth(int minWidth) {
19034        mMinWidth = minWidth;
19035        requestLayout();
19036
19037    }
19038
19039    /**
19040     * Get the animation currently associated with this view.
19041     *
19042     * @return The animation that is currently playing or
19043     *         scheduled to play for this view.
19044     */
19045    public Animation getAnimation() {
19046        return mCurrentAnimation;
19047    }
19048
19049    /**
19050     * Start the specified animation now.
19051     *
19052     * @param animation the animation to start now
19053     */
19054    public void startAnimation(Animation animation) {
19055        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
19056        setAnimation(animation);
19057        invalidateParentCaches();
19058        invalidate(true);
19059    }
19060
19061    /**
19062     * Cancels any animations for this view.
19063     */
19064    public void clearAnimation() {
19065        if (mCurrentAnimation != null) {
19066            mCurrentAnimation.detach();
19067        }
19068        mCurrentAnimation = null;
19069        invalidateParentIfNeeded();
19070    }
19071
19072    /**
19073     * Sets the next animation to play for this view.
19074     * If you want the animation to play immediately, use
19075     * {@link #startAnimation(android.view.animation.Animation)} instead.
19076     * This method provides allows fine-grained
19077     * control over the start time and invalidation, but you
19078     * must make sure that 1) the animation has a start time set, and
19079     * 2) the view's parent (which controls animations on its children)
19080     * will be invalidated when the animation is supposed to
19081     * start.
19082     *
19083     * @param animation The next animation, or null.
19084     */
19085    public void setAnimation(Animation animation) {
19086        mCurrentAnimation = animation;
19087
19088        if (animation != null) {
19089            // If the screen is off assume the animation start time is now instead of
19090            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
19091            // would cause the animation to start when the screen turns back on
19092            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
19093                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
19094                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
19095            }
19096            animation.reset();
19097        }
19098    }
19099
19100    /**
19101     * Invoked by a parent ViewGroup to notify the start of the animation
19102     * currently associated with this view. If you override this method,
19103     * always call super.onAnimationStart();
19104     *
19105     * @see #setAnimation(android.view.animation.Animation)
19106     * @see #getAnimation()
19107     */
19108    @CallSuper
19109    protected void onAnimationStart() {
19110        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
19111    }
19112
19113    /**
19114     * Invoked by a parent ViewGroup to notify the end of the animation
19115     * currently associated with this view. If you override this method,
19116     * always call super.onAnimationEnd();
19117     *
19118     * @see #setAnimation(android.view.animation.Animation)
19119     * @see #getAnimation()
19120     */
19121    @CallSuper
19122    protected void onAnimationEnd() {
19123        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
19124    }
19125
19126    /**
19127     * Invoked if there is a Transform that involves alpha. Subclass that can
19128     * draw themselves with the specified alpha should return true, and then
19129     * respect that alpha when their onDraw() is called. If this returns false
19130     * then the view may be redirected to draw into an offscreen buffer to
19131     * fulfill the request, which will look fine, but may be slower than if the
19132     * subclass handles it internally. The default implementation returns false.
19133     *
19134     * @param alpha The alpha (0..255) to apply to the view's drawing
19135     * @return true if the view can draw with the specified alpha.
19136     */
19137    protected boolean onSetAlpha(int alpha) {
19138        return false;
19139    }
19140
19141    /**
19142     * This is used by the RootView to perform an optimization when
19143     * the view hierarchy contains one or several SurfaceView.
19144     * SurfaceView is always considered transparent, but its children are not,
19145     * therefore all View objects remove themselves from the global transparent
19146     * region (passed as a parameter to this function).
19147     *
19148     * @param region The transparent region for this ViewAncestor (window).
19149     *
19150     * @return Returns true if the effective visibility of the view at this
19151     * point is opaque, regardless of the transparent region; returns false
19152     * if it is possible for underlying windows to be seen behind the view.
19153     *
19154     * {@hide}
19155     */
19156    public boolean gatherTransparentRegion(Region region) {
19157        final AttachInfo attachInfo = mAttachInfo;
19158        if (region != null && attachInfo != null) {
19159            final int pflags = mPrivateFlags;
19160            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
19161                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
19162                // remove it from the transparent region.
19163                final int[] location = attachInfo.mTransparentLocation;
19164                getLocationInWindow(location);
19165                region.op(location[0], location[1], location[0] + mRight - mLeft,
19166                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
19167            } else {
19168                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
19169                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
19170                    // the background drawable's non-transparent parts from this transparent region.
19171                    applyDrawableToTransparentRegion(mBackground, region);
19172                }
19173                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19174                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
19175                    // Similarly, we remove the foreground drawable's non-transparent parts.
19176                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
19177                }
19178            }
19179        }
19180        return true;
19181    }
19182
19183    /**
19184     * Play a sound effect for this view.
19185     *
19186     * <p>The framework will play sound effects for some built in actions, such as
19187     * clicking, but you may wish to play these effects in your widget,
19188     * for instance, for internal navigation.
19189     *
19190     * <p>The sound effect will only be played if sound effects are enabled by the user, and
19191     * {@link #isSoundEffectsEnabled()} is true.
19192     *
19193     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
19194     */
19195    public void playSoundEffect(int soundConstant) {
19196        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
19197            return;
19198        }
19199        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
19200    }
19201
19202    /**
19203     * BZZZTT!!1!
19204     *
19205     * <p>Provide haptic feedback to the user for this view.
19206     *
19207     * <p>The framework will provide haptic feedback for some built in actions,
19208     * such as long presses, but you may wish to provide feedback for your
19209     * own widget.
19210     *
19211     * <p>The feedback will only be performed if
19212     * {@link #isHapticFeedbackEnabled()} is true.
19213     *
19214     * @param feedbackConstant One of the constants defined in
19215     * {@link HapticFeedbackConstants}
19216     */
19217    public boolean performHapticFeedback(int feedbackConstant) {
19218        return performHapticFeedback(feedbackConstant, 0);
19219    }
19220
19221    /**
19222     * BZZZTT!!1!
19223     *
19224     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
19225     *
19226     * @param feedbackConstant One of the constants defined in
19227     * {@link HapticFeedbackConstants}
19228     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
19229     */
19230    public boolean performHapticFeedback(int feedbackConstant, int flags) {
19231        if (mAttachInfo == null) {
19232            return false;
19233        }
19234        //noinspection SimplifiableIfStatement
19235        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
19236                && !isHapticFeedbackEnabled()) {
19237            return false;
19238        }
19239        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
19240                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
19241    }
19242
19243    /**
19244     * Request that the visibility of the status bar or other screen/window
19245     * decorations be changed.
19246     *
19247     * <p>This method is used to put the over device UI into temporary modes
19248     * where the user's attention is focused more on the application content,
19249     * by dimming or hiding surrounding system affordances.  This is typically
19250     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
19251     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
19252     * to be placed behind the action bar (and with these flags other system
19253     * affordances) so that smooth transitions between hiding and showing them
19254     * can be done.
19255     *
19256     * <p>Two representative examples of the use of system UI visibility is
19257     * implementing a content browsing application (like a magazine reader)
19258     * and a video playing application.
19259     *
19260     * <p>The first code shows a typical implementation of a View in a content
19261     * browsing application.  In this implementation, the application goes
19262     * into a content-oriented mode by hiding the status bar and action bar,
19263     * and putting the navigation elements into lights out mode.  The user can
19264     * then interact with content while in this mode.  Such an application should
19265     * provide an easy way for the user to toggle out of the mode (such as to
19266     * check information in the status bar or access notifications).  In the
19267     * implementation here, this is done simply by tapping on the content.
19268     *
19269     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
19270     *      content}
19271     *
19272     * <p>This second code sample shows a typical implementation of a View
19273     * in a video playing application.  In this situation, while the video is
19274     * playing the application would like to go into a complete full-screen mode,
19275     * to use as much of the display as possible for the video.  When in this state
19276     * the user can not interact with the application; the system intercepts
19277     * touching on the screen to pop the UI out of full screen mode.  See
19278     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
19279     *
19280     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
19281     *      content}
19282     *
19283     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19284     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19285     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19286     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19287     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19288     */
19289    public void setSystemUiVisibility(int visibility) {
19290        if (visibility != mSystemUiVisibility) {
19291            mSystemUiVisibility = visibility;
19292            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19293                mParent.recomputeViewAttributes(this);
19294            }
19295        }
19296    }
19297
19298    /**
19299     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
19300     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19301     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19302     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19303     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19304     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19305     */
19306    public int getSystemUiVisibility() {
19307        return mSystemUiVisibility;
19308    }
19309
19310    /**
19311     * Returns the current system UI visibility that is currently set for
19312     * the entire window.  This is the combination of the
19313     * {@link #setSystemUiVisibility(int)} values supplied by all of the
19314     * views in the window.
19315     */
19316    public int getWindowSystemUiVisibility() {
19317        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
19318    }
19319
19320    /**
19321     * Override to find out when the window's requested system UI visibility
19322     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
19323     * This is different from the callbacks received through
19324     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
19325     * in that this is only telling you about the local request of the window,
19326     * not the actual values applied by the system.
19327     */
19328    public void onWindowSystemUiVisibilityChanged(int visible) {
19329    }
19330
19331    /**
19332     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
19333     * the view hierarchy.
19334     */
19335    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
19336        onWindowSystemUiVisibilityChanged(visible);
19337    }
19338
19339    /**
19340     * Set a listener to receive callbacks when the visibility of the system bar changes.
19341     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
19342     */
19343    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
19344        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
19345        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19346            mParent.recomputeViewAttributes(this);
19347        }
19348    }
19349
19350    /**
19351     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
19352     * the view hierarchy.
19353     */
19354    public void dispatchSystemUiVisibilityChanged(int visibility) {
19355        ListenerInfo li = mListenerInfo;
19356        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
19357            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
19358                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
19359        }
19360    }
19361
19362    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
19363        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
19364        if (val != mSystemUiVisibility) {
19365            setSystemUiVisibility(val);
19366            return true;
19367        }
19368        return false;
19369    }
19370
19371    /** @hide */
19372    public void setDisabledSystemUiVisibility(int flags) {
19373        if (mAttachInfo != null) {
19374            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
19375                mAttachInfo.mDisabledSystemUiVisibility = flags;
19376                if (mParent != null) {
19377                    mParent.recomputeViewAttributes(this);
19378                }
19379            }
19380        }
19381    }
19382
19383    /**
19384     * Creates an image that the system displays during the drag and drop
19385     * operation. This is called a &quot;drag shadow&quot;. The default implementation
19386     * for a DragShadowBuilder based on a View returns an image that has exactly the same
19387     * appearance as the given View. The default also positions the center of the drag shadow
19388     * directly under the touch point. If no View is provided (the constructor with no parameters
19389     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
19390     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
19391     * default is an invisible drag shadow.
19392     * <p>
19393     * You are not required to use the View you provide to the constructor as the basis of the
19394     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
19395     * anything you want as the drag shadow.
19396     * </p>
19397     * <p>
19398     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
19399     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
19400     *  size and position of the drag shadow. It uses this data to construct a
19401     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
19402     *  so that your application can draw the shadow image in the Canvas.
19403     * </p>
19404     *
19405     * <div class="special reference">
19406     * <h3>Developer Guides</h3>
19407     * <p>For a guide to implementing drag and drop features, read the
19408     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19409     * </div>
19410     */
19411    public static class DragShadowBuilder {
19412        private final WeakReference<View> mView;
19413
19414        /**
19415         * Constructs a shadow image builder based on a View. By default, the resulting drag
19416         * shadow will have the same appearance and dimensions as the View, with the touch point
19417         * over the center of the View.
19418         * @param view A View. Any View in scope can be used.
19419         */
19420        public DragShadowBuilder(View view) {
19421            mView = new WeakReference<View>(view);
19422        }
19423
19424        /**
19425         * Construct a shadow builder object with no associated View.  This
19426         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
19427         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
19428         * to supply the drag shadow's dimensions and appearance without
19429         * reference to any View object. If they are not overridden, then the result is an
19430         * invisible drag shadow.
19431         */
19432        public DragShadowBuilder() {
19433            mView = new WeakReference<View>(null);
19434        }
19435
19436        /**
19437         * Returns the View object that had been passed to the
19438         * {@link #View.DragShadowBuilder(View)}
19439         * constructor.  If that View parameter was {@code null} or if the
19440         * {@link #View.DragShadowBuilder()}
19441         * constructor was used to instantiate the builder object, this method will return
19442         * null.
19443         *
19444         * @return The View object associate with this builder object.
19445         */
19446        @SuppressWarnings({"JavadocReference"})
19447        final public View getView() {
19448            return mView.get();
19449        }
19450
19451        /**
19452         * Provides the metrics for the shadow image. These include the dimensions of
19453         * the shadow image, and the point within that shadow that should
19454         * be centered under the touch location while dragging.
19455         * <p>
19456         * The default implementation sets the dimensions of the shadow to be the
19457         * same as the dimensions of the View itself and centers the shadow under
19458         * the touch point.
19459         * </p>
19460         *
19461         * @param shadowSize A {@link android.graphics.Point} containing the width and height
19462         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
19463         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
19464         * image.
19465         *
19466         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
19467         * shadow image that should be underneath the touch point during the drag and drop
19468         * operation. Your application must set {@link android.graphics.Point#x} to the
19469         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
19470         */
19471        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
19472            final View view = mView.get();
19473            if (view != null) {
19474                shadowSize.set(view.getWidth(), view.getHeight());
19475                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
19476            } else {
19477                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
19478            }
19479        }
19480
19481        /**
19482         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
19483         * based on the dimensions it received from the
19484         * {@link #onProvideShadowMetrics(Point, Point)} callback.
19485         *
19486         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
19487         */
19488        public void onDrawShadow(Canvas canvas) {
19489            final View view = mView.get();
19490            if (view != null) {
19491                view.draw(canvas);
19492            } else {
19493                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
19494            }
19495        }
19496    }
19497
19498    /**
19499     * Starts a drag and drop operation. When your application calls this method, it passes a
19500     * {@link android.view.View.DragShadowBuilder} object to the system. The
19501     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
19502     * to get metrics for the drag shadow, and then calls the object's
19503     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
19504     * <p>
19505     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
19506     *  drag events to all the View objects in your application that are currently visible. It does
19507     *  this either by calling the View object's drag listener (an implementation of
19508     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
19509     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
19510     *  Both are passed a {@link android.view.DragEvent} object that has a
19511     *  {@link android.view.DragEvent#getAction()} value of
19512     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19513     * </p>
19514     * <p>
19515     * Your application can invoke startDrag() on any attached View object. The View object does not
19516     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
19517     * be related to the View the user selected for dragging.
19518     * </p>
19519     * @param data A {@link android.content.ClipData} object pointing to the data to be
19520     * transferred by the drag and drop operation.
19521     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19522     * drag shadow.
19523     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19524     * drop operation. This Object is put into every DragEvent object sent by the system during the
19525     * current drag.
19526     * <p>
19527     * myLocalState is a lightweight mechanism for the sending information from the dragged View
19528     * to the target Views. For example, it can contain flags that differentiate between a
19529     * a copy operation and a move operation.
19530     * </p>
19531     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19532     * so the parameter should be set to 0.
19533     * @return {@code true} if the method completes successfully, or
19534     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19535     * do a drag, and so no drag operation is in progress.
19536     */
19537    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19538            Object myLocalState, int flags) {
19539        if (ViewDebug.DEBUG_DRAG) {
19540            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
19541        }
19542        boolean okay = false;
19543
19544        Point shadowSize = new Point();
19545        Point shadowTouchPoint = new Point();
19546        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
19547
19548        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
19549                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
19550            throw new IllegalStateException("Drag shadow dimensions must not be negative");
19551        }
19552
19553        if (ViewDebug.DEBUG_DRAG) {
19554            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
19555                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
19556        }
19557        Surface surface = new Surface();
19558        try {
19559            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
19560                    flags, shadowSize.x, shadowSize.y, surface);
19561            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
19562                    + " surface=" + surface);
19563            if (token != null) {
19564                Canvas canvas = surface.lockCanvas(null);
19565                try {
19566                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
19567                    shadowBuilder.onDrawShadow(canvas);
19568                } finally {
19569                    surface.unlockCanvasAndPost(canvas);
19570                }
19571
19572                final ViewRootImpl root = getViewRootImpl();
19573
19574                // Cache the local state object for delivery with DragEvents
19575                root.setLocalDragState(myLocalState);
19576
19577                // repurpose 'shadowSize' for the last touch point
19578                root.getLastTouchPoint(shadowSize);
19579
19580                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
19581                        shadowSize.x, shadowSize.y,
19582                        shadowTouchPoint.x, shadowTouchPoint.y, data);
19583                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
19584
19585                // Off and running!  Release our local surface instance; the drag
19586                // shadow surface is now managed by the system process.
19587                surface.release();
19588            }
19589        } catch (Exception e) {
19590            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
19591            surface.destroy();
19592        }
19593
19594        return okay;
19595    }
19596
19597    /**
19598     * Handles drag events sent by the system following a call to
19599     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
19600     *<p>
19601     * When the system calls this method, it passes a
19602     * {@link android.view.DragEvent} object. A call to
19603     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
19604     * in DragEvent. The method uses these to determine what is happening in the drag and drop
19605     * operation.
19606     * @param event The {@link android.view.DragEvent} sent by the system.
19607     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
19608     * in DragEvent, indicating the type of drag event represented by this object.
19609     * @return {@code true} if the method was successful, otherwise {@code false}.
19610     * <p>
19611     *  The method should return {@code true} in response to an action type of
19612     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
19613     *  operation.
19614     * </p>
19615     * <p>
19616     *  The method should also return {@code true} in response to an action type of
19617     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19618     *  {@code false} if it didn't.
19619     * </p>
19620     */
19621    public boolean onDragEvent(DragEvent event) {
19622        return false;
19623    }
19624
19625    /**
19626     * Detects if this View is enabled and has a drag event listener.
19627     * If both are true, then it calls the drag event listener with the
19628     * {@link android.view.DragEvent} it received. If the drag event listener returns
19629     * {@code true}, then dispatchDragEvent() returns {@code true}.
19630     * <p>
19631     * For all other cases, the method calls the
19632     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
19633     * method and returns its result.
19634     * </p>
19635     * <p>
19636     * This ensures that a drag event is always consumed, even if the View does not have a drag
19637     * event listener. However, if the View has a listener and the listener returns true, then
19638     * onDragEvent() is not called.
19639     * </p>
19640     */
19641    public boolean dispatchDragEvent(DragEvent event) {
19642        ListenerInfo li = mListenerInfo;
19643        //noinspection SimplifiableIfStatement
19644        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
19645                && li.mOnDragListener.onDrag(this, event)) {
19646            return true;
19647        }
19648        return onDragEvent(event);
19649    }
19650
19651    boolean canAcceptDrag() {
19652        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
19653    }
19654
19655    /**
19656     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
19657     * it is ever exposed at all.
19658     * @hide
19659     */
19660    public void onCloseSystemDialogs(String reason) {
19661    }
19662
19663    /**
19664     * Given a Drawable whose bounds have been set to draw into this view,
19665     * update a Region being computed for
19666     * {@link #gatherTransparentRegion(android.graphics.Region)} so
19667     * that any non-transparent parts of the Drawable are removed from the
19668     * given transparent region.
19669     *
19670     * @param dr The Drawable whose transparency is to be applied to the region.
19671     * @param region A Region holding the current transparency information,
19672     * where any parts of the region that are set are considered to be
19673     * transparent.  On return, this region will be modified to have the
19674     * transparency information reduced by the corresponding parts of the
19675     * Drawable that are not transparent.
19676     * {@hide}
19677     */
19678    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
19679        if (DBG) {
19680            Log.i("View", "Getting transparent region for: " + this);
19681        }
19682        final Region r = dr.getTransparentRegion();
19683        final Rect db = dr.getBounds();
19684        final AttachInfo attachInfo = mAttachInfo;
19685        if (r != null && attachInfo != null) {
19686            final int w = getRight()-getLeft();
19687            final int h = getBottom()-getTop();
19688            if (db.left > 0) {
19689                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
19690                r.op(0, 0, db.left, h, Region.Op.UNION);
19691            }
19692            if (db.right < w) {
19693                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
19694                r.op(db.right, 0, w, h, Region.Op.UNION);
19695            }
19696            if (db.top > 0) {
19697                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
19698                r.op(0, 0, w, db.top, Region.Op.UNION);
19699            }
19700            if (db.bottom < h) {
19701                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
19702                r.op(0, db.bottom, w, h, Region.Op.UNION);
19703            }
19704            final int[] location = attachInfo.mTransparentLocation;
19705            getLocationInWindow(location);
19706            r.translate(location[0], location[1]);
19707            region.op(r, Region.Op.INTERSECT);
19708        } else {
19709            region.op(db, Region.Op.DIFFERENCE);
19710        }
19711    }
19712
19713    private void checkForLongClick(int delayOffset) {
19714        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
19715            mHasPerformedLongPress = false;
19716
19717            if (mPendingCheckForLongPress == null) {
19718                mPendingCheckForLongPress = new CheckForLongPress();
19719            }
19720            mPendingCheckForLongPress.rememberWindowAttachCount();
19721            postDelayed(mPendingCheckForLongPress,
19722                    ViewConfiguration.getLongPressTimeout() - delayOffset);
19723        }
19724    }
19725
19726    /**
19727     * Inflate a view from an XML resource.  This convenience method wraps the {@link
19728     * LayoutInflater} class, which provides a full range of options for view inflation.
19729     *
19730     * @param context The Context object for your activity or application.
19731     * @param resource The resource ID to inflate
19732     * @param root A view group that will be the parent.  Used to properly inflate the
19733     * layout_* parameters.
19734     * @see LayoutInflater
19735     */
19736    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
19737        LayoutInflater factory = LayoutInflater.from(context);
19738        return factory.inflate(resource, root);
19739    }
19740
19741    /**
19742     * Scroll the view with standard behavior for scrolling beyond the normal
19743     * content boundaries. Views that call this method should override
19744     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
19745     * results of an over-scroll operation.
19746     *
19747     * Views can use this method to handle any touch or fling-based scrolling.
19748     *
19749     * @param deltaX Change in X in pixels
19750     * @param deltaY Change in Y in pixels
19751     * @param scrollX Current X scroll value in pixels before applying deltaX
19752     * @param scrollY Current Y scroll value in pixels before applying deltaY
19753     * @param scrollRangeX Maximum content scroll range along the X axis
19754     * @param scrollRangeY Maximum content scroll range along the Y axis
19755     * @param maxOverScrollX Number of pixels to overscroll by in either direction
19756     *          along the X axis.
19757     * @param maxOverScrollY Number of pixels to overscroll by in either direction
19758     *          along the Y axis.
19759     * @param isTouchEvent true if this scroll operation is the result of a touch event.
19760     * @return true if scrolling was clamped to an over-scroll boundary along either
19761     *          axis, false otherwise.
19762     */
19763    @SuppressWarnings({"UnusedParameters"})
19764    protected boolean overScrollBy(int deltaX, int deltaY,
19765            int scrollX, int scrollY,
19766            int scrollRangeX, int scrollRangeY,
19767            int maxOverScrollX, int maxOverScrollY,
19768            boolean isTouchEvent) {
19769        final int overScrollMode = mOverScrollMode;
19770        final boolean canScrollHorizontal =
19771                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
19772        final boolean canScrollVertical =
19773                computeVerticalScrollRange() > computeVerticalScrollExtent();
19774        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
19775                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
19776        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
19777                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
19778
19779        int newScrollX = scrollX + deltaX;
19780        if (!overScrollHorizontal) {
19781            maxOverScrollX = 0;
19782        }
19783
19784        int newScrollY = scrollY + deltaY;
19785        if (!overScrollVertical) {
19786            maxOverScrollY = 0;
19787        }
19788
19789        // Clamp values if at the limits and record
19790        final int left = -maxOverScrollX;
19791        final int right = maxOverScrollX + scrollRangeX;
19792        final int top = -maxOverScrollY;
19793        final int bottom = maxOverScrollY + scrollRangeY;
19794
19795        boolean clampedX = false;
19796        if (newScrollX > right) {
19797            newScrollX = right;
19798            clampedX = true;
19799        } else if (newScrollX < left) {
19800            newScrollX = left;
19801            clampedX = true;
19802        }
19803
19804        boolean clampedY = false;
19805        if (newScrollY > bottom) {
19806            newScrollY = bottom;
19807            clampedY = true;
19808        } else if (newScrollY < top) {
19809            newScrollY = top;
19810            clampedY = true;
19811        }
19812
19813        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
19814
19815        return clampedX || clampedY;
19816    }
19817
19818    /**
19819     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
19820     * respond to the results of an over-scroll operation.
19821     *
19822     * @param scrollX New X scroll value in pixels
19823     * @param scrollY New Y scroll value in pixels
19824     * @param clampedX True if scrollX was clamped to an over-scroll boundary
19825     * @param clampedY True if scrollY was clamped to an over-scroll boundary
19826     */
19827    protected void onOverScrolled(int scrollX, int scrollY,
19828            boolean clampedX, boolean clampedY) {
19829        // Intentionally empty.
19830    }
19831
19832    /**
19833     * Returns the over-scroll mode for this view. The result will be
19834     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19835     * (allow over-scrolling only if the view content is larger than the container),
19836     * or {@link #OVER_SCROLL_NEVER}.
19837     *
19838     * @return This view's over-scroll mode.
19839     */
19840    public int getOverScrollMode() {
19841        return mOverScrollMode;
19842    }
19843
19844    /**
19845     * Set the over-scroll mode for this view. Valid over-scroll modes are
19846     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19847     * (allow over-scrolling only if the view content is larger than the container),
19848     * or {@link #OVER_SCROLL_NEVER}.
19849     *
19850     * Setting the over-scroll mode of a view will have an effect only if the
19851     * view is capable of scrolling.
19852     *
19853     * @param overScrollMode The new over-scroll mode for this view.
19854     */
19855    public void setOverScrollMode(int overScrollMode) {
19856        if (overScrollMode != OVER_SCROLL_ALWAYS &&
19857                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
19858                overScrollMode != OVER_SCROLL_NEVER) {
19859            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
19860        }
19861        mOverScrollMode = overScrollMode;
19862    }
19863
19864    /**
19865     * Enable or disable nested scrolling for this view.
19866     *
19867     * <p>If this property is set to true the view will be permitted to initiate nested
19868     * scrolling operations with a compatible parent view in the current hierarchy. If this
19869     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
19870     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
19871     * the nested scroll.</p>
19872     *
19873     * @param enabled true to enable nested scrolling, false to disable
19874     *
19875     * @see #isNestedScrollingEnabled()
19876     */
19877    public void setNestedScrollingEnabled(boolean enabled) {
19878        if (enabled) {
19879            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
19880        } else {
19881            stopNestedScroll();
19882            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
19883        }
19884    }
19885
19886    /**
19887     * Returns true if nested scrolling is enabled for this view.
19888     *
19889     * <p>If nested scrolling is enabled and this View class implementation supports it,
19890     * this view will act as a nested scrolling child view when applicable, forwarding data
19891     * about the scroll operation in progress to a compatible and cooperating nested scrolling
19892     * parent.</p>
19893     *
19894     * @return true if nested scrolling is enabled
19895     *
19896     * @see #setNestedScrollingEnabled(boolean)
19897     */
19898    public boolean isNestedScrollingEnabled() {
19899        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
19900                PFLAG3_NESTED_SCROLLING_ENABLED;
19901    }
19902
19903    /**
19904     * Begin a nestable scroll operation along the given axes.
19905     *
19906     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
19907     *
19908     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
19909     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
19910     * In the case of touch scrolling the nested scroll will be terminated automatically in
19911     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
19912     * In the event of programmatic scrolling the caller must explicitly call
19913     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
19914     *
19915     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
19916     * If it returns false the caller may ignore the rest of this contract until the next scroll.
19917     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
19918     *
19919     * <p>At each incremental step of the scroll the caller should invoke
19920     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
19921     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
19922     * parent at least partially consumed the scroll and the caller should adjust the amount it
19923     * scrolls by.</p>
19924     *
19925     * <p>After applying the remainder of the scroll delta the caller should invoke
19926     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
19927     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
19928     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
19929     * </p>
19930     *
19931     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
19932     *             {@link #SCROLL_AXIS_VERTICAL}.
19933     * @return true if a cooperative parent was found and nested scrolling has been enabled for
19934     *         the current gesture.
19935     *
19936     * @see #stopNestedScroll()
19937     * @see #dispatchNestedPreScroll(int, int, int[], int[])
19938     * @see #dispatchNestedScroll(int, int, int, int, int[])
19939     */
19940    public boolean startNestedScroll(int axes) {
19941        if (hasNestedScrollingParent()) {
19942            // Already in progress
19943            return true;
19944        }
19945        if (isNestedScrollingEnabled()) {
19946            ViewParent p = getParent();
19947            View child = this;
19948            while (p != null) {
19949                try {
19950                    if (p.onStartNestedScroll(child, this, axes)) {
19951                        mNestedScrollingParent = p;
19952                        p.onNestedScrollAccepted(child, this, axes);
19953                        return true;
19954                    }
19955                } catch (AbstractMethodError e) {
19956                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
19957                            "method onStartNestedScroll", e);
19958                    // Allow the search upward to continue
19959                }
19960                if (p instanceof View) {
19961                    child = (View) p;
19962                }
19963                p = p.getParent();
19964            }
19965        }
19966        return false;
19967    }
19968
19969    /**
19970     * Stop a nested scroll in progress.
19971     *
19972     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
19973     *
19974     * @see #startNestedScroll(int)
19975     */
19976    public void stopNestedScroll() {
19977        if (mNestedScrollingParent != null) {
19978            mNestedScrollingParent.onStopNestedScroll(this);
19979            mNestedScrollingParent = null;
19980        }
19981    }
19982
19983    /**
19984     * Returns true if this view has a nested scrolling parent.
19985     *
19986     * <p>The presence of a nested scrolling parent indicates that this view has initiated
19987     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
19988     *
19989     * @return whether this view has a nested scrolling parent
19990     */
19991    public boolean hasNestedScrollingParent() {
19992        return mNestedScrollingParent != null;
19993    }
19994
19995    /**
19996     * Dispatch one step of a nested scroll in progress.
19997     *
19998     * <p>Implementations of views that support nested scrolling should call this to report
19999     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
20000     * is not currently in progress or nested scrolling is not
20001     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
20002     *
20003     * <p>Compatible View implementations should also call
20004     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
20005     * consuming a component of the scroll event themselves.</p>
20006     *
20007     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
20008     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
20009     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
20010     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
20011     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20012     *                       in local view coordinates of this view from before this operation
20013     *                       to after it completes. View implementations may use this to adjust
20014     *                       expected input coordinate tracking.
20015     * @return true if the event was dispatched, false if it could not be dispatched.
20016     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20017     */
20018    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
20019            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
20020        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20021            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
20022                int startX = 0;
20023                int startY = 0;
20024                if (offsetInWindow != null) {
20025                    getLocationInWindow(offsetInWindow);
20026                    startX = offsetInWindow[0];
20027                    startY = offsetInWindow[1];
20028                }
20029
20030                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
20031                        dxUnconsumed, dyUnconsumed);
20032
20033                if (offsetInWindow != null) {
20034                    getLocationInWindow(offsetInWindow);
20035                    offsetInWindow[0] -= startX;
20036                    offsetInWindow[1] -= startY;
20037                }
20038                return true;
20039            } else if (offsetInWindow != null) {
20040                // No motion, no dispatch. Keep offsetInWindow up to date.
20041                offsetInWindow[0] = 0;
20042                offsetInWindow[1] = 0;
20043            }
20044        }
20045        return false;
20046    }
20047
20048    /**
20049     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
20050     *
20051     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
20052     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
20053     * scrolling operation to consume some or all of the scroll operation before the child view
20054     * consumes it.</p>
20055     *
20056     * @param dx Horizontal scroll distance in pixels
20057     * @param dy Vertical scroll distance in pixels
20058     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
20059     *                 and consumed[1] the consumed dy.
20060     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20061     *                       in local view coordinates of this view from before this operation
20062     *                       to after it completes. View implementations may use this to adjust
20063     *                       expected input coordinate tracking.
20064     * @return true if the parent consumed some or all of the scroll delta
20065     * @see #dispatchNestedScroll(int, int, int, int, int[])
20066     */
20067    public boolean dispatchNestedPreScroll(int dx, int dy,
20068            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
20069        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20070            if (dx != 0 || dy != 0) {
20071                int startX = 0;
20072                int startY = 0;
20073                if (offsetInWindow != null) {
20074                    getLocationInWindow(offsetInWindow);
20075                    startX = offsetInWindow[0];
20076                    startY = offsetInWindow[1];
20077                }
20078
20079                if (consumed == null) {
20080                    if (mTempNestedScrollConsumed == null) {
20081                        mTempNestedScrollConsumed = new int[2];
20082                    }
20083                    consumed = mTempNestedScrollConsumed;
20084                }
20085                consumed[0] = 0;
20086                consumed[1] = 0;
20087                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
20088
20089                if (offsetInWindow != null) {
20090                    getLocationInWindow(offsetInWindow);
20091                    offsetInWindow[0] -= startX;
20092                    offsetInWindow[1] -= startY;
20093                }
20094                return consumed[0] != 0 || consumed[1] != 0;
20095            } else if (offsetInWindow != null) {
20096                offsetInWindow[0] = 0;
20097                offsetInWindow[1] = 0;
20098            }
20099        }
20100        return false;
20101    }
20102
20103    /**
20104     * Dispatch a fling to a nested scrolling parent.
20105     *
20106     * <p>This method should be used to indicate that a nested scrolling child has detected
20107     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
20108     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
20109     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
20110     * along a scrollable axis.</p>
20111     *
20112     * <p>If a nested scrolling child view would normally fling but it is at the edge of
20113     * its own content, it can use this method to delegate the fling to its nested scrolling
20114     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
20115     *
20116     * @param velocityX Horizontal fling velocity in pixels per second
20117     * @param velocityY Vertical fling velocity in pixels per second
20118     * @param consumed true if the child consumed the fling, false otherwise
20119     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
20120     */
20121    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
20122        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20123            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
20124        }
20125        return false;
20126    }
20127
20128    /**
20129     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
20130     *
20131     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
20132     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
20133     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
20134     * before the child view consumes it. If this method returns <code>true</code>, a nested
20135     * parent view consumed the fling and this view should not scroll as a result.</p>
20136     *
20137     * <p>For a better user experience, only one view in a nested scrolling chain should consume
20138     * the fling at a time. If a parent view consumed the fling this method will return false.
20139     * Custom view implementations should account for this in two ways:</p>
20140     *
20141     * <ul>
20142     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
20143     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
20144     *     position regardless.</li>
20145     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
20146     *     even to settle back to a valid idle position.</li>
20147     * </ul>
20148     *
20149     * <p>Views should also not offer fling velocities to nested parent views along an axis
20150     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
20151     * should not offer a horizontal fling velocity to its parents since scrolling along that
20152     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
20153     *
20154     * @param velocityX Horizontal fling velocity in pixels per second
20155     * @param velocityY Vertical fling velocity in pixels per second
20156     * @return true if a nested scrolling parent consumed the fling
20157     */
20158    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
20159        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20160            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
20161        }
20162        return false;
20163    }
20164
20165    /**
20166     * Gets a scale factor that determines the distance the view should scroll
20167     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
20168     * @return The vertical scroll scale factor.
20169     * @hide
20170     */
20171    protected float getVerticalScrollFactor() {
20172        if (mVerticalScrollFactor == 0) {
20173            TypedValue outValue = new TypedValue();
20174            if (!mContext.getTheme().resolveAttribute(
20175                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
20176                throw new IllegalStateException(
20177                        "Expected theme to define listPreferredItemHeight.");
20178            }
20179            mVerticalScrollFactor = outValue.getDimension(
20180                    mContext.getResources().getDisplayMetrics());
20181        }
20182        return mVerticalScrollFactor;
20183    }
20184
20185    /**
20186     * Gets a scale factor that determines the distance the view should scroll
20187     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
20188     * @return The horizontal scroll scale factor.
20189     * @hide
20190     */
20191    protected float getHorizontalScrollFactor() {
20192        // TODO: Should use something else.
20193        return getVerticalScrollFactor();
20194    }
20195
20196    /**
20197     * Return the value specifying the text direction or policy that was set with
20198     * {@link #setTextDirection(int)}.
20199     *
20200     * @return the defined text direction. It can be one of:
20201     *
20202     * {@link #TEXT_DIRECTION_INHERIT},
20203     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20204     * {@link #TEXT_DIRECTION_ANY_RTL},
20205     * {@link #TEXT_DIRECTION_LTR},
20206     * {@link #TEXT_DIRECTION_RTL},
20207     * {@link #TEXT_DIRECTION_LOCALE},
20208     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20209     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20210     *
20211     * @attr ref android.R.styleable#View_textDirection
20212     *
20213     * @hide
20214     */
20215    @ViewDebug.ExportedProperty(category = "text", mapping = {
20216            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20217            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20218            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20219            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20220            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20221            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20222            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20223            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20224    })
20225    public int getRawTextDirection() {
20226        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
20227    }
20228
20229    /**
20230     * Set the text direction.
20231     *
20232     * @param textDirection the direction to set. Should be one of:
20233     *
20234     * {@link #TEXT_DIRECTION_INHERIT},
20235     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20236     * {@link #TEXT_DIRECTION_ANY_RTL},
20237     * {@link #TEXT_DIRECTION_LTR},
20238     * {@link #TEXT_DIRECTION_RTL},
20239     * {@link #TEXT_DIRECTION_LOCALE}
20240     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20241     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
20242     *
20243     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
20244     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
20245     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
20246     *
20247     * @attr ref android.R.styleable#View_textDirection
20248     */
20249    public void setTextDirection(int textDirection) {
20250        if (getRawTextDirection() != textDirection) {
20251            // Reset the current text direction and the resolved one
20252            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
20253            resetResolvedTextDirection();
20254            // Set the new text direction
20255            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
20256            // Do resolution
20257            resolveTextDirection();
20258            // Notify change
20259            onRtlPropertiesChanged(getLayoutDirection());
20260            // Refresh
20261            requestLayout();
20262            invalidate(true);
20263        }
20264    }
20265
20266    /**
20267     * Return the resolved text direction.
20268     *
20269     * @return the resolved text direction. Returns one of:
20270     *
20271     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20272     * {@link #TEXT_DIRECTION_ANY_RTL},
20273     * {@link #TEXT_DIRECTION_LTR},
20274     * {@link #TEXT_DIRECTION_RTL},
20275     * {@link #TEXT_DIRECTION_LOCALE},
20276     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20277     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20278     *
20279     * @attr ref android.R.styleable#View_textDirection
20280     */
20281    @ViewDebug.ExportedProperty(category = "text", mapping = {
20282            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20283            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20284            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20285            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20286            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20287            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20288            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20289            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20290    })
20291    public int getTextDirection() {
20292        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
20293    }
20294
20295    /**
20296     * Resolve the text direction.
20297     *
20298     * @return true if resolution has been done, false otherwise.
20299     *
20300     * @hide
20301     */
20302    public boolean resolveTextDirection() {
20303        // Reset any previous text direction resolution
20304        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20305
20306        if (hasRtlSupport()) {
20307            // Set resolved text direction flag depending on text direction flag
20308            final int textDirection = getRawTextDirection();
20309            switch(textDirection) {
20310                case TEXT_DIRECTION_INHERIT:
20311                    if (!canResolveTextDirection()) {
20312                        // We cannot do the resolution if there is no parent, so use the default one
20313                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20314                        // Resolution will need to happen again later
20315                        return false;
20316                    }
20317
20318                    // Parent has not yet resolved, so we still return the default
20319                    try {
20320                        if (!mParent.isTextDirectionResolved()) {
20321                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20322                            // Resolution will need to happen again later
20323                            return false;
20324                        }
20325                    } catch (AbstractMethodError e) {
20326                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20327                                " does not fully implement ViewParent", e);
20328                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
20329                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20330                        return true;
20331                    }
20332
20333                    // Set current resolved direction to the same value as the parent's one
20334                    int parentResolvedDirection;
20335                    try {
20336                        parentResolvedDirection = mParent.getTextDirection();
20337                    } catch (AbstractMethodError e) {
20338                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20339                                " does not fully implement ViewParent", e);
20340                        parentResolvedDirection = TEXT_DIRECTION_LTR;
20341                    }
20342                    switch (parentResolvedDirection) {
20343                        case TEXT_DIRECTION_FIRST_STRONG:
20344                        case TEXT_DIRECTION_ANY_RTL:
20345                        case TEXT_DIRECTION_LTR:
20346                        case TEXT_DIRECTION_RTL:
20347                        case TEXT_DIRECTION_LOCALE:
20348                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
20349                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
20350                            mPrivateFlags2 |=
20351                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20352                            break;
20353                        default:
20354                            // Default resolved direction is "first strong" heuristic
20355                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20356                    }
20357                    break;
20358                case TEXT_DIRECTION_FIRST_STRONG:
20359                case TEXT_DIRECTION_ANY_RTL:
20360                case TEXT_DIRECTION_LTR:
20361                case TEXT_DIRECTION_RTL:
20362                case TEXT_DIRECTION_LOCALE:
20363                case TEXT_DIRECTION_FIRST_STRONG_LTR:
20364                case TEXT_DIRECTION_FIRST_STRONG_RTL:
20365                    // Resolved direction is the same as text direction
20366                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20367                    break;
20368                default:
20369                    // Default resolved direction is "first strong" heuristic
20370                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20371            }
20372        } else {
20373            // Default resolved direction is "first strong" heuristic
20374            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20375        }
20376
20377        // Set to resolved
20378        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
20379        return true;
20380    }
20381
20382    /**
20383     * Check if text direction resolution can be done.
20384     *
20385     * @return true if text direction resolution can be done otherwise return false.
20386     */
20387    public boolean canResolveTextDirection() {
20388        switch (getRawTextDirection()) {
20389            case TEXT_DIRECTION_INHERIT:
20390                if (mParent != null) {
20391                    try {
20392                        return mParent.canResolveTextDirection();
20393                    } catch (AbstractMethodError e) {
20394                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20395                                " does not fully implement ViewParent", e);
20396                    }
20397                }
20398                return false;
20399
20400            default:
20401                return true;
20402        }
20403    }
20404
20405    /**
20406     * Reset resolved text direction. Text direction will be resolved during a call to
20407     * {@link #onMeasure(int, int)}.
20408     *
20409     * @hide
20410     */
20411    public void resetResolvedTextDirection() {
20412        // Reset any previous text direction resolution
20413        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20414        // Set to default value
20415        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20416    }
20417
20418    /**
20419     * @return true if text direction is inherited.
20420     *
20421     * @hide
20422     */
20423    public boolean isTextDirectionInherited() {
20424        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
20425    }
20426
20427    /**
20428     * @return true if text direction is resolved.
20429     */
20430    public boolean isTextDirectionResolved() {
20431        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
20432    }
20433
20434    /**
20435     * Return the value specifying the text alignment or policy that was set with
20436     * {@link #setTextAlignment(int)}.
20437     *
20438     * @return the defined text alignment. It can be one of:
20439     *
20440     * {@link #TEXT_ALIGNMENT_INHERIT},
20441     * {@link #TEXT_ALIGNMENT_GRAVITY},
20442     * {@link #TEXT_ALIGNMENT_CENTER},
20443     * {@link #TEXT_ALIGNMENT_TEXT_START},
20444     * {@link #TEXT_ALIGNMENT_TEXT_END},
20445     * {@link #TEXT_ALIGNMENT_VIEW_START},
20446     * {@link #TEXT_ALIGNMENT_VIEW_END}
20447     *
20448     * @attr ref android.R.styleable#View_textAlignment
20449     *
20450     * @hide
20451     */
20452    @ViewDebug.ExportedProperty(category = "text", mapping = {
20453            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20454            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20455            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20456            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20457            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20458            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20459            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20460    })
20461    @TextAlignment
20462    public int getRawTextAlignment() {
20463        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
20464    }
20465
20466    /**
20467     * Set the text alignment.
20468     *
20469     * @param textAlignment The text alignment to set. Should be one of
20470     *
20471     * {@link #TEXT_ALIGNMENT_INHERIT},
20472     * {@link #TEXT_ALIGNMENT_GRAVITY},
20473     * {@link #TEXT_ALIGNMENT_CENTER},
20474     * {@link #TEXT_ALIGNMENT_TEXT_START},
20475     * {@link #TEXT_ALIGNMENT_TEXT_END},
20476     * {@link #TEXT_ALIGNMENT_VIEW_START},
20477     * {@link #TEXT_ALIGNMENT_VIEW_END}
20478     *
20479     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
20480     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
20481     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
20482     *
20483     * @attr ref android.R.styleable#View_textAlignment
20484     */
20485    public void setTextAlignment(@TextAlignment int textAlignment) {
20486        if (textAlignment != getRawTextAlignment()) {
20487            // Reset the current and resolved text alignment
20488            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
20489            resetResolvedTextAlignment();
20490            // Set the new text alignment
20491            mPrivateFlags2 |=
20492                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
20493            // Do resolution
20494            resolveTextAlignment();
20495            // Notify change
20496            onRtlPropertiesChanged(getLayoutDirection());
20497            // Refresh
20498            requestLayout();
20499            invalidate(true);
20500        }
20501    }
20502
20503    /**
20504     * Return the resolved text alignment.
20505     *
20506     * @return the resolved text alignment. Returns one of:
20507     *
20508     * {@link #TEXT_ALIGNMENT_GRAVITY},
20509     * {@link #TEXT_ALIGNMENT_CENTER},
20510     * {@link #TEXT_ALIGNMENT_TEXT_START},
20511     * {@link #TEXT_ALIGNMENT_TEXT_END},
20512     * {@link #TEXT_ALIGNMENT_VIEW_START},
20513     * {@link #TEXT_ALIGNMENT_VIEW_END}
20514     *
20515     * @attr ref android.R.styleable#View_textAlignment
20516     */
20517    @ViewDebug.ExportedProperty(category = "text", mapping = {
20518            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20519            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20520            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20521            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20522            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20523            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20524            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20525    })
20526    @TextAlignment
20527    public int getTextAlignment() {
20528        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
20529                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
20530    }
20531
20532    /**
20533     * Resolve the text alignment.
20534     *
20535     * @return true if resolution has been done, false otherwise.
20536     *
20537     * @hide
20538     */
20539    public boolean resolveTextAlignment() {
20540        // Reset any previous text alignment resolution
20541        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20542
20543        if (hasRtlSupport()) {
20544            // Set resolved text alignment flag depending on text alignment flag
20545            final int textAlignment = getRawTextAlignment();
20546            switch (textAlignment) {
20547                case TEXT_ALIGNMENT_INHERIT:
20548                    // Check if we can resolve the text alignment
20549                    if (!canResolveTextAlignment()) {
20550                        // We cannot do the resolution if there is no parent so use the default
20551                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20552                        // Resolution will need to happen again later
20553                        return false;
20554                    }
20555
20556                    // Parent has not yet resolved, so we still return the default
20557                    try {
20558                        if (!mParent.isTextAlignmentResolved()) {
20559                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20560                            // Resolution will need to happen again later
20561                            return false;
20562                        }
20563                    } catch (AbstractMethodError e) {
20564                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20565                                " does not fully implement ViewParent", e);
20566                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
20567                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20568                        return true;
20569                    }
20570
20571                    int parentResolvedTextAlignment;
20572                    try {
20573                        parentResolvedTextAlignment = mParent.getTextAlignment();
20574                    } catch (AbstractMethodError e) {
20575                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20576                                " does not fully implement ViewParent", e);
20577                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
20578                    }
20579                    switch (parentResolvedTextAlignment) {
20580                        case TEXT_ALIGNMENT_GRAVITY:
20581                        case TEXT_ALIGNMENT_TEXT_START:
20582                        case TEXT_ALIGNMENT_TEXT_END:
20583                        case TEXT_ALIGNMENT_CENTER:
20584                        case TEXT_ALIGNMENT_VIEW_START:
20585                        case TEXT_ALIGNMENT_VIEW_END:
20586                            // Resolved text alignment is the same as the parent resolved
20587                            // text alignment
20588                            mPrivateFlags2 |=
20589                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20590                            break;
20591                        default:
20592                            // Use default resolved text alignment
20593                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20594                    }
20595                    break;
20596                case TEXT_ALIGNMENT_GRAVITY:
20597                case TEXT_ALIGNMENT_TEXT_START:
20598                case TEXT_ALIGNMENT_TEXT_END:
20599                case TEXT_ALIGNMENT_CENTER:
20600                case TEXT_ALIGNMENT_VIEW_START:
20601                case TEXT_ALIGNMENT_VIEW_END:
20602                    // Resolved text alignment is the same as text alignment
20603                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20604                    break;
20605                default:
20606                    // Use default resolved text alignment
20607                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20608            }
20609        } else {
20610            // Use default resolved text alignment
20611            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20612        }
20613
20614        // Set the resolved
20615        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20616        return true;
20617    }
20618
20619    /**
20620     * Check if text alignment resolution can be done.
20621     *
20622     * @return true if text alignment resolution can be done otherwise return false.
20623     */
20624    public boolean canResolveTextAlignment() {
20625        switch (getRawTextAlignment()) {
20626            case TEXT_DIRECTION_INHERIT:
20627                if (mParent != null) {
20628                    try {
20629                        return mParent.canResolveTextAlignment();
20630                    } catch (AbstractMethodError e) {
20631                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20632                                " does not fully implement ViewParent", e);
20633                    }
20634                }
20635                return false;
20636
20637            default:
20638                return true;
20639        }
20640    }
20641
20642    /**
20643     * Reset resolved text alignment. Text alignment will be resolved during a call to
20644     * {@link #onMeasure(int, int)}.
20645     *
20646     * @hide
20647     */
20648    public void resetResolvedTextAlignment() {
20649        // Reset any previous text alignment resolution
20650        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20651        // Set to default
20652        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20653    }
20654
20655    /**
20656     * @return true if text alignment is inherited.
20657     *
20658     * @hide
20659     */
20660    public boolean isTextAlignmentInherited() {
20661        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
20662    }
20663
20664    /**
20665     * @return true if text alignment is resolved.
20666     */
20667    public boolean isTextAlignmentResolved() {
20668        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20669    }
20670
20671    /**
20672     * Generate a value suitable for use in {@link #setId(int)}.
20673     * This value will not collide with ID values generated at build time by aapt for R.id.
20674     *
20675     * @return a generated ID value
20676     */
20677    public static int generateViewId() {
20678        for (;;) {
20679            final int result = sNextGeneratedId.get();
20680            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
20681            int newValue = result + 1;
20682            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
20683            if (sNextGeneratedId.compareAndSet(result, newValue)) {
20684                return result;
20685            }
20686        }
20687    }
20688
20689    /**
20690     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
20691     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
20692     *                           a normal View or a ViewGroup with
20693     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
20694     * @hide
20695     */
20696    public void captureTransitioningViews(List<View> transitioningViews) {
20697        if (getVisibility() == View.VISIBLE) {
20698            transitioningViews.add(this);
20699        }
20700    }
20701
20702    /**
20703     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
20704     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
20705     * @hide
20706     */
20707    public void findNamedViews(Map<String, View> namedElements) {
20708        if (getVisibility() == VISIBLE || mGhostView != null) {
20709            String transitionName = getTransitionName();
20710            if (transitionName != null) {
20711                namedElements.put(transitionName, this);
20712            }
20713        }
20714    }
20715
20716    //
20717    // Properties
20718    //
20719    /**
20720     * A Property wrapper around the <code>alpha</code> functionality handled by the
20721     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
20722     */
20723    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
20724        @Override
20725        public void setValue(View object, float value) {
20726            object.setAlpha(value);
20727        }
20728
20729        @Override
20730        public Float get(View object) {
20731            return object.getAlpha();
20732        }
20733    };
20734
20735    /**
20736     * A Property wrapper around the <code>translationX</code> functionality handled by the
20737     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
20738     */
20739    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
20740        @Override
20741        public void setValue(View object, float value) {
20742            object.setTranslationX(value);
20743        }
20744
20745                @Override
20746        public Float get(View object) {
20747            return object.getTranslationX();
20748        }
20749    };
20750
20751    /**
20752     * A Property wrapper around the <code>translationY</code> functionality handled by the
20753     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
20754     */
20755    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
20756        @Override
20757        public void setValue(View object, float value) {
20758            object.setTranslationY(value);
20759        }
20760
20761        @Override
20762        public Float get(View object) {
20763            return object.getTranslationY();
20764        }
20765    };
20766
20767    /**
20768     * A Property wrapper around the <code>translationZ</code> functionality handled by the
20769     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
20770     */
20771    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
20772        @Override
20773        public void setValue(View object, float value) {
20774            object.setTranslationZ(value);
20775        }
20776
20777        @Override
20778        public Float get(View object) {
20779            return object.getTranslationZ();
20780        }
20781    };
20782
20783    /**
20784     * A Property wrapper around the <code>x</code> functionality handled by the
20785     * {@link View#setX(float)} and {@link View#getX()} methods.
20786     */
20787    public static final Property<View, Float> X = new FloatProperty<View>("x") {
20788        @Override
20789        public void setValue(View object, float value) {
20790            object.setX(value);
20791        }
20792
20793        @Override
20794        public Float get(View object) {
20795            return object.getX();
20796        }
20797    };
20798
20799    /**
20800     * A Property wrapper around the <code>y</code> functionality handled by the
20801     * {@link View#setY(float)} and {@link View#getY()} methods.
20802     */
20803    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
20804        @Override
20805        public void setValue(View object, float value) {
20806            object.setY(value);
20807        }
20808
20809        @Override
20810        public Float get(View object) {
20811            return object.getY();
20812        }
20813    };
20814
20815    /**
20816     * A Property wrapper around the <code>z</code> functionality handled by the
20817     * {@link View#setZ(float)} and {@link View#getZ()} methods.
20818     */
20819    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
20820        @Override
20821        public void setValue(View object, float value) {
20822            object.setZ(value);
20823        }
20824
20825        @Override
20826        public Float get(View object) {
20827            return object.getZ();
20828        }
20829    };
20830
20831    /**
20832     * A Property wrapper around the <code>rotation</code> functionality handled by the
20833     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
20834     */
20835    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
20836        @Override
20837        public void setValue(View object, float value) {
20838            object.setRotation(value);
20839        }
20840
20841        @Override
20842        public Float get(View object) {
20843            return object.getRotation();
20844        }
20845    };
20846
20847    /**
20848     * A Property wrapper around the <code>rotationX</code> functionality handled by the
20849     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
20850     */
20851    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
20852        @Override
20853        public void setValue(View object, float value) {
20854            object.setRotationX(value);
20855        }
20856
20857        @Override
20858        public Float get(View object) {
20859            return object.getRotationX();
20860        }
20861    };
20862
20863    /**
20864     * A Property wrapper around the <code>rotationY</code> functionality handled by the
20865     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
20866     */
20867    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
20868        @Override
20869        public void setValue(View object, float value) {
20870            object.setRotationY(value);
20871        }
20872
20873        @Override
20874        public Float get(View object) {
20875            return object.getRotationY();
20876        }
20877    };
20878
20879    /**
20880     * A Property wrapper around the <code>scaleX</code> functionality handled by the
20881     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
20882     */
20883    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
20884        @Override
20885        public void setValue(View object, float value) {
20886            object.setScaleX(value);
20887        }
20888
20889        @Override
20890        public Float get(View object) {
20891            return object.getScaleX();
20892        }
20893    };
20894
20895    /**
20896     * A Property wrapper around the <code>scaleY</code> functionality handled by the
20897     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
20898     */
20899    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
20900        @Override
20901        public void setValue(View object, float value) {
20902            object.setScaleY(value);
20903        }
20904
20905        @Override
20906        public Float get(View object) {
20907            return object.getScaleY();
20908        }
20909    };
20910
20911    /**
20912     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
20913     * Each MeasureSpec represents a requirement for either the width or the height.
20914     * A MeasureSpec is comprised of a size and a mode. There are three possible
20915     * modes:
20916     * <dl>
20917     * <dt>UNSPECIFIED</dt>
20918     * <dd>
20919     * The parent has not imposed any constraint on the child. It can be whatever size
20920     * it wants.
20921     * </dd>
20922     *
20923     * <dt>EXACTLY</dt>
20924     * <dd>
20925     * The parent has determined an exact size for the child. The child is going to be
20926     * given those bounds regardless of how big it wants to be.
20927     * </dd>
20928     *
20929     * <dt>AT_MOST</dt>
20930     * <dd>
20931     * The child can be as large as it wants up to the specified size.
20932     * </dd>
20933     * </dl>
20934     *
20935     * MeasureSpecs are implemented as ints to reduce object allocation. This class
20936     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
20937     */
20938    public static class MeasureSpec {
20939        private static final int MODE_SHIFT = 30;
20940        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
20941
20942        /**
20943         * Measure specification mode: The parent has not imposed any constraint
20944         * on the child. It can be whatever size it wants.
20945         */
20946        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
20947
20948        /**
20949         * Measure specification mode: The parent has determined an exact size
20950         * for the child. The child is going to be given those bounds regardless
20951         * of how big it wants to be.
20952         */
20953        public static final int EXACTLY     = 1 << MODE_SHIFT;
20954
20955        /**
20956         * Measure specification mode: The child can be as large as it wants up
20957         * to the specified size.
20958         */
20959        public static final int AT_MOST     = 2 << MODE_SHIFT;
20960
20961        /**
20962         * Creates a measure specification based on the supplied size and mode.
20963         *
20964         * The mode must always be one of the following:
20965         * <ul>
20966         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
20967         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
20968         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
20969         * </ul>
20970         *
20971         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
20972         * implementation was such that the order of arguments did not matter
20973         * and overflow in either value could impact the resulting MeasureSpec.
20974         * {@link android.widget.RelativeLayout} was affected by this bug.
20975         * Apps targeting API levels greater than 17 will get the fixed, more strict
20976         * behavior.</p>
20977         *
20978         * @param size the size of the measure specification
20979         * @param mode the mode of the measure specification
20980         * @return the measure specification based on size and mode
20981         */
20982        public static int makeMeasureSpec(int size, int mode) {
20983            if (sUseBrokenMakeMeasureSpec) {
20984                return size + mode;
20985            } else {
20986                return (size & ~MODE_MASK) | (mode & MODE_MASK);
20987            }
20988        }
20989
20990        /**
20991         * Extracts the mode from the supplied measure specification.
20992         *
20993         * @param measureSpec the measure specification to extract the mode from
20994         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
20995         *         {@link android.view.View.MeasureSpec#AT_MOST} or
20996         *         {@link android.view.View.MeasureSpec#EXACTLY}
20997         */
20998        public static int getMode(int measureSpec) {
20999            return (measureSpec & MODE_MASK);
21000        }
21001
21002        /**
21003         * Extracts the size from the supplied measure specification.
21004         *
21005         * @param measureSpec the measure specification to extract the size from
21006         * @return the size in pixels defined in the supplied measure specification
21007         */
21008        public static int getSize(int measureSpec) {
21009            return (measureSpec & ~MODE_MASK);
21010        }
21011
21012        static int adjust(int measureSpec, int delta) {
21013            final int mode = getMode(measureSpec);
21014            int size = getSize(measureSpec);
21015            if (mode == UNSPECIFIED) {
21016                // No need to adjust size for UNSPECIFIED mode.
21017                return makeMeasureSpec(size, UNSPECIFIED);
21018            }
21019            size += delta;
21020            if (size < 0) {
21021                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
21022                        ") spec: " + toString(measureSpec) + " delta: " + delta);
21023                size = 0;
21024            }
21025            return makeMeasureSpec(size, mode);
21026        }
21027
21028        /**
21029         * Returns a String representation of the specified measure
21030         * specification.
21031         *
21032         * @param measureSpec the measure specification to convert to a String
21033         * @return a String with the following format: "MeasureSpec: MODE SIZE"
21034         */
21035        public static String toString(int measureSpec) {
21036            int mode = getMode(measureSpec);
21037            int size = getSize(measureSpec);
21038
21039            StringBuilder sb = new StringBuilder("MeasureSpec: ");
21040
21041            if (mode == UNSPECIFIED)
21042                sb.append("UNSPECIFIED ");
21043            else if (mode == EXACTLY)
21044                sb.append("EXACTLY ");
21045            else if (mode == AT_MOST)
21046                sb.append("AT_MOST ");
21047            else
21048                sb.append(mode).append(" ");
21049
21050            sb.append(size);
21051            return sb.toString();
21052        }
21053    }
21054
21055    private final class CheckForLongPress implements Runnable {
21056        private int mOriginalWindowAttachCount;
21057
21058        @Override
21059        public void run() {
21060            if (isPressed() && (mParent != null)
21061                    && mOriginalWindowAttachCount == mWindowAttachCount) {
21062                if (performLongClick()) {
21063                    mHasPerformedLongPress = true;
21064                }
21065            }
21066        }
21067
21068        public void rememberWindowAttachCount() {
21069            mOriginalWindowAttachCount = mWindowAttachCount;
21070        }
21071    }
21072
21073    private final class CheckForTap implements Runnable {
21074        public float x;
21075        public float y;
21076
21077        @Override
21078        public void run() {
21079            mPrivateFlags &= ~PFLAG_PREPRESSED;
21080            setPressed(true, x, y);
21081            checkForLongClick(ViewConfiguration.getTapTimeout());
21082        }
21083    }
21084
21085    private final class PerformClick implements Runnable {
21086        @Override
21087        public void run() {
21088            performClick();
21089        }
21090    }
21091
21092    /** @hide */
21093    public void hackTurnOffWindowResizeAnim(boolean off) {
21094        mAttachInfo.mTurnOffWindowResizeAnim = off;
21095    }
21096
21097    /**
21098     * This method returns a ViewPropertyAnimator object, which can be used to animate
21099     * specific properties on this View.
21100     *
21101     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
21102     */
21103    public ViewPropertyAnimator animate() {
21104        if (mAnimator == null) {
21105            mAnimator = new ViewPropertyAnimator(this);
21106        }
21107        return mAnimator;
21108    }
21109
21110    /**
21111     * Sets the name of the View to be used to identify Views in Transitions.
21112     * Names should be unique in the View hierarchy.
21113     *
21114     * @param transitionName The name of the View to uniquely identify it for Transitions.
21115     */
21116    public final void setTransitionName(String transitionName) {
21117        mTransitionName = transitionName;
21118    }
21119
21120    /**
21121     * Returns the name of the View to be used to identify Views in Transitions.
21122     * Names should be unique in the View hierarchy.
21123     *
21124     * <p>This returns null if the View has not been given a name.</p>
21125     *
21126     * @return The name used of the View to be used to identify Views in Transitions or null
21127     * if no name has been given.
21128     */
21129    @ViewDebug.ExportedProperty
21130    public String getTransitionName() {
21131        return mTransitionName;
21132    }
21133
21134    /**
21135     * Interface definition for a callback to be invoked when a hardware key event is
21136     * dispatched to this view. The callback will be invoked before the key event is
21137     * given to the view. This is only useful for hardware keyboards; a software input
21138     * method has no obligation to trigger this listener.
21139     */
21140    public interface OnKeyListener {
21141        /**
21142         * Called when a hardware key is dispatched to a view. This allows listeners to
21143         * get a chance to respond before the target view.
21144         * <p>Key presses in software keyboards will generally NOT trigger this method,
21145         * although some may elect to do so in some situations. Do not assume a
21146         * software input method has to be key-based; even if it is, it may use key presses
21147         * in a different way than you expect, so there is no way to reliably catch soft
21148         * input key presses.
21149         *
21150         * @param v The view the key has been dispatched to.
21151         * @param keyCode The code for the physical key that was pressed
21152         * @param event The KeyEvent object containing full information about
21153         *        the event.
21154         * @return True if the listener has consumed the event, false otherwise.
21155         */
21156        boolean onKey(View v, int keyCode, KeyEvent event);
21157    }
21158
21159    /**
21160     * Interface definition for a callback to be invoked when a touch event is
21161     * dispatched to this view. The callback will be invoked before the touch
21162     * event is given to the view.
21163     */
21164    public interface OnTouchListener {
21165        /**
21166         * Called when a touch event is dispatched to a view. This allows listeners to
21167         * get a chance to respond before the target view.
21168         *
21169         * @param v The view the touch event has been dispatched to.
21170         * @param event The MotionEvent object containing full information about
21171         *        the event.
21172         * @return True if the listener has consumed the event, false otherwise.
21173         */
21174        boolean onTouch(View v, MotionEvent event);
21175    }
21176
21177    /**
21178     * Interface definition for a callback to be invoked when a hover event is
21179     * dispatched to this view. The callback will be invoked before the hover
21180     * event is given to the view.
21181     */
21182    public interface OnHoverListener {
21183        /**
21184         * Called when a hover event is dispatched to a view. This allows listeners to
21185         * get a chance to respond before the target view.
21186         *
21187         * @param v The view the hover event has been dispatched to.
21188         * @param event The MotionEvent object containing full information about
21189         *        the event.
21190         * @return True if the listener has consumed the event, false otherwise.
21191         */
21192        boolean onHover(View v, MotionEvent event);
21193    }
21194
21195    /**
21196     * Interface definition for a callback to be invoked when a generic motion event is
21197     * dispatched to this view. The callback will be invoked before the generic motion
21198     * event is given to the view.
21199     */
21200    public interface OnGenericMotionListener {
21201        /**
21202         * Called when a generic motion event is dispatched to a view. This allows listeners to
21203         * get a chance to respond before the target view.
21204         *
21205         * @param v The view the generic motion event has been dispatched to.
21206         * @param event The MotionEvent object containing full information about
21207         *        the event.
21208         * @return True if the listener has consumed the event, false otherwise.
21209         */
21210        boolean onGenericMotion(View v, MotionEvent event);
21211    }
21212
21213    /**
21214     * Interface definition for a callback to be invoked when a view has been clicked and held.
21215     */
21216    public interface OnLongClickListener {
21217        /**
21218         * Called when a view has been clicked and held.
21219         *
21220         * @param v The view that was clicked and held.
21221         *
21222         * @return true if the callback consumed the long click, false otherwise.
21223         */
21224        boolean onLongClick(View v);
21225    }
21226
21227    /**
21228     * Interface definition for a callback to be invoked when a drag is being dispatched
21229     * to this view.  The callback will be invoked before the hosting view's own
21230     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
21231     * onDrag(event) behavior, it should return 'false' from this callback.
21232     *
21233     * <div class="special reference">
21234     * <h3>Developer Guides</h3>
21235     * <p>For a guide to implementing drag and drop features, read the
21236     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21237     * </div>
21238     */
21239    public interface OnDragListener {
21240        /**
21241         * Called when a drag event is dispatched to a view. This allows listeners
21242         * to get a chance to override base View behavior.
21243         *
21244         * @param v The View that received the drag event.
21245         * @param event The {@link android.view.DragEvent} object for the drag event.
21246         * @return {@code true} if the drag event was handled successfully, or {@code false}
21247         * if the drag event was not handled. Note that {@code false} will trigger the View
21248         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
21249         */
21250        boolean onDrag(View v, DragEvent event);
21251    }
21252
21253    /**
21254     * Interface definition for a callback to be invoked when the focus state of
21255     * a view changed.
21256     */
21257    public interface OnFocusChangeListener {
21258        /**
21259         * Called when the focus state of a view has changed.
21260         *
21261         * @param v The view whose state has changed.
21262         * @param hasFocus The new focus state of v.
21263         */
21264        void onFocusChange(View v, boolean hasFocus);
21265    }
21266
21267    /**
21268     * Interface definition for a callback to be invoked when a view is clicked.
21269     */
21270    public interface OnClickListener {
21271        /**
21272         * Called when a view has been clicked.
21273         *
21274         * @param v The view that was clicked.
21275         */
21276        void onClick(View v);
21277    }
21278
21279    /**
21280     * Interface definition for a callback to be invoked when a view is touched with a stylus while
21281     * the stylus button is pressed.
21282     */
21283    public interface OnStylusButtonPressListener {
21284        /**
21285         * Called when a view is touched with a stylus while the stylus button is pressed.
21286         *
21287         * @param v The view that was touched.
21288         * @return true if the callback consumed the stylus button press, false otherwise.
21289         */
21290        boolean onStylusButtonPress(View v);
21291    }
21292
21293    /**
21294     * Interface definition for a callback to be invoked when the context menu
21295     * for this view is being built.
21296     */
21297    public interface OnCreateContextMenuListener {
21298        /**
21299         * Called when the context menu for this view is being built. It is not
21300         * safe to hold onto the menu after this method returns.
21301         *
21302         * @param menu The context menu that is being built
21303         * @param v The view for which the context menu is being built
21304         * @param menuInfo Extra information about the item for which the
21305         *            context menu should be shown. This information will vary
21306         *            depending on the class of v.
21307         */
21308        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
21309    }
21310
21311    /**
21312     * Interface definition for a callback to be invoked when the status bar changes
21313     * visibility.  This reports <strong>global</strong> changes to the system UI
21314     * state, not what the application is requesting.
21315     *
21316     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
21317     */
21318    public interface OnSystemUiVisibilityChangeListener {
21319        /**
21320         * Called when the status bar changes visibility because of a call to
21321         * {@link View#setSystemUiVisibility(int)}.
21322         *
21323         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21324         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
21325         * This tells you the <strong>global</strong> state of these UI visibility
21326         * flags, not what your app is currently applying.
21327         */
21328        public void onSystemUiVisibilityChange(int visibility);
21329    }
21330
21331    /**
21332     * Interface definition for a callback to be invoked when this view is attached
21333     * or detached from its window.
21334     */
21335    public interface OnAttachStateChangeListener {
21336        /**
21337         * Called when the view is attached to a window.
21338         * @param v The view that was attached
21339         */
21340        public void onViewAttachedToWindow(View v);
21341        /**
21342         * Called when the view is detached from a window.
21343         * @param v The view that was detached
21344         */
21345        public void onViewDetachedFromWindow(View v);
21346    }
21347
21348    /**
21349     * Listener for applying window insets on a view in a custom way.
21350     *
21351     * <p>Apps may choose to implement this interface if they want to apply custom policy
21352     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
21353     * is set, its
21354     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
21355     * method will be called instead of the View's own
21356     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
21357     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
21358     * the View's normal behavior as part of its own.</p>
21359     */
21360    public interface OnApplyWindowInsetsListener {
21361        /**
21362         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
21363         * on a View, this listener method will be called instead of the view's own
21364         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
21365         *
21366         * @param v The view applying window insets
21367         * @param insets The insets to apply
21368         * @return The insets supplied, minus any insets that were consumed
21369         */
21370        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
21371    }
21372
21373    private final class UnsetPressedState implements Runnable {
21374        @Override
21375        public void run() {
21376            setPressed(false);
21377        }
21378    }
21379
21380    /**
21381     * Base class for derived classes that want to save and restore their own
21382     * state in {@link android.view.View#onSaveInstanceState()}.
21383     */
21384    public static class BaseSavedState extends AbsSavedState {
21385        String mStartActivityRequestWhoSaved;
21386
21387        /**
21388         * Constructor used when reading from a parcel. Reads the state of the superclass.
21389         *
21390         * @param source
21391         */
21392        public BaseSavedState(Parcel source) {
21393            super(source);
21394            mStartActivityRequestWhoSaved = source.readString();
21395        }
21396
21397        /**
21398         * Constructor called by derived classes when creating their SavedState objects
21399         *
21400         * @param superState The state of the superclass of this view
21401         */
21402        public BaseSavedState(Parcelable superState) {
21403            super(superState);
21404        }
21405
21406        @Override
21407        public void writeToParcel(Parcel out, int flags) {
21408            super.writeToParcel(out, flags);
21409            out.writeString(mStartActivityRequestWhoSaved);
21410        }
21411
21412        public static final Parcelable.Creator<BaseSavedState> CREATOR =
21413                new Parcelable.Creator<BaseSavedState>() {
21414            public BaseSavedState createFromParcel(Parcel in) {
21415                return new BaseSavedState(in);
21416            }
21417
21418            public BaseSavedState[] newArray(int size) {
21419                return new BaseSavedState[size];
21420            }
21421        };
21422    }
21423
21424    /**
21425     * A set of information given to a view when it is attached to its parent
21426     * window.
21427     */
21428    final static class AttachInfo {
21429        interface Callbacks {
21430            void playSoundEffect(int effectId);
21431            boolean performHapticFeedback(int effectId, boolean always);
21432        }
21433
21434        /**
21435         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
21436         * to a Handler. This class contains the target (View) to invalidate and
21437         * the coordinates of the dirty rectangle.
21438         *
21439         * For performance purposes, this class also implements a pool of up to
21440         * POOL_LIMIT objects that get reused. This reduces memory allocations
21441         * whenever possible.
21442         */
21443        static class InvalidateInfo {
21444            private static final int POOL_LIMIT = 10;
21445
21446            private static final SynchronizedPool<InvalidateInfo> sPool =
21447                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
21448
21449            View target;
21450
21451            int left;
21452            int top;
21453            int right;
21454            int bottom;
21455
21456            public static InvalidateInfo obtain() {
21457                InvalidateInfo instance = sPool.acquire();
21458                return (instance != null) ? instance : new InvalidateInfo();
21459            }
21460
21461            public void recycle() {
21462                target = null;
21463                sPool.release(this);
21464            }
21465        }
21466
21467        final IWindowSession mSession;
21468
21469        final IWindow mWindow;
21470
21471        final IBinder mWindowToken;
21472
21473        final Display mDisplay;
21474
21475        final Callbacks mRootCallbacks;
21476
21477        IWindowId mIWindowId;
21478        WindowId mWindowId;
21479
21480        /**
21481         * The top view of the hierarchy.
21482         */
21483        View mRootView;
21484
21485        IBinder mPanelParentWindowToken;
21486
21487        boolean mHardwareAccelerated;
21488        boolean mHardwareAccelerationRequested;
21489        HardwareRenderer mHardwareRenderer;
21490        List<RenderNode> mPendingAnimatingRenderNodes;
21491
21492        /**
21493         * The state of the display to which the window is attached, as reported
21494         * by {@link Display#getState()}.  Note that the display state constants
21495         * declared by {@link Display} do not exactly line up with the screen state
21496         * constants declared by {@link View} (there are more display states than
21497         * screen states).
21498         */
21499        int mDisplayState = Display.STATE_UNKNOWN;
21500
21501        /**
21502         * Scale factor used by the compatibility mode
21503         */
21504        float mApplicationScale;
21505
21506        /**
21507         * Indicates whether the application is in compatibility mode
21508         */
21509        boolean mScalingRequired;
21510
21511        /**
21512         * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
21513         */
21514        boolean mTurnOffWindowResizeAnim;
21515
21516        /**
21517         * Left position of this view's window
21518         */
21519        int mWindowLeft;
21520
21521        /**
21522         * Top position of this view's window
21523         */
21524        int mWindowTop;
21525
21526        /**
21527         * Indicates whether views need to use 32-bit drawing caches
21528         */
21529        boolean mUse32BitDrawingCache;
21530
21531        /**
21532         * For windows that are full-screen but using insets to layout inside
21533         * of the screen areas, these are the current insets to appear inside
21534         * the overscan area of the display.
21535         */
21536        final Rect mOverscanInsets = new Rect();
21537
21538        /**
21539         * For windows that are full-screen but using insets to layout inside
21540         * of the screen decorations, these are the current insets for the
21541         * content of the window.
21542         */
21543        final Rect mContentInsets = new Rect();
21544
21545        /**
21546         * For windows that are full-screen but using insets to layout inside
21547         * of the screen decorations, these are the current insets for the
21548         * actual visible parts of the window.
21549         */
21550        final Rect mVisibleInsets = new Rect();
21551
21552        /**
21553         * For windows that are full-screen but using insets to layout inside
21554         * of the screen decorations, these are the current insets for the
21555         * stable system windows.
21556         */
21557        final Rect mStableInsets = new Rect();
21558
21559        /**
21560         * The internal insets given by this window.  This value is
21561         * supplied by the client (through
21562         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
21563         * be given to the window manager when changed to be used in laying
21564         * out windows behind it.
21565         */
21566        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
21567                = new ViewTreeObserver.InternalInsetsInfo();
21568
21569        /**
21570         * Set to true when mGivenInternalInsets is non-empty.
21571         */
21572        boolean mHasNonEmptyGivenInternalInsets;
21573
21574        /**
21575         * All views in the window's hierarchy that serve as scroll containers,
21576         * used to determine if the window can be resized or must be panned
21577         * to adjust for a soft input area.
21578         */
21579        final ArrayList<View> mScrollContainers = new ArrayList<View>();
21580
21581        final KeyEvent.DispatcherState mKeyDispatchState
21582                = new KeyEvent.DispatcherState();
21583
21584        /**
21585         * Indicates whether the view's window currently has the focus.
21586         */
21587        boolean mHasWindowFocus;
21588
21589        /**
21590         * The current visibility of the window.
21591         */
21592        int mWindowVisibility;
21593
21594        /**
21595         * Indicates the time at which drawing started to occur.
21596         */
21597        long mDrawingTime;
21598
21599        /**
21600         * Indicates whether or not ignoring the DIRTY_MASK flags.
21601         */
21602        boolean mIgnoreDirtyState;
21603
21604        /**
21605         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
21606         * to avoid clearing that flag prematurely.
21607         */
21608        boolean mSetIgnoreDirtyState = false;
21609
21610        /**
21611         * Indicates whether the view's window is currently in touch mode.
21612         */
21613        boolean mInTouchMode;
21614
21615        /**
21616         * Indicates whether the view has requested unbuffered input dispatching for the current
21617         * event stream.
21618         */
21619        boolean mUnbufferedDispatchRequested;
21620
21621        /**
21622         * Indicates that ViewAncestor should trigger a global layout change
21623         * the next time it performs a traversal
21624         */
21625        boolean mRecomputeGlobalAttributes;
21626
21627        /**
21628         * Always report new attributes at next traversal.
21629         */
21630        boolean mForceReportNewAttributes;
21631
21632        /**
21633         * Set during a traveral if any views want to keep the screen on.
21634         */
21635        boolean mKeepScreenOn;
21636
21637        /**
21638         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
21639         */
21640        int mSystemUiVisibility;
21641
21642        /**
21643         * Hack to force certain system UI visibility flags to be cleared.
21644         */
21645        int mDisabledSystemUiVisibility;
21646
21647        /**
21648         * Last global system UI visibility reported by the window manager.
21649         */
21650        int mGlobalSystemUiVisibility;
21651
21652        /**
21653         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
21654         * attached.
21655         */
21656        boolean mHasSystemUiListeners;
21657
21658        /**
21659         * Set if the window has requested to extend into the overscan region
21660         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
21661         */
21662        boolean mOverscanRequested;
21663
21664        /**
21665         * Set if the visibility of any views has changed.
21666         */
21667        boolean mViewVisibilityChanged;
21668
21669        /**
21670         * Set to true if a view has been scrolled.
21671         */
21672        boolean mViewScrollChanged;
21673
21674        /**
21675         * Set to true if high contrast mode enabled
21676         */
21677        boolean mHighContrastText;
21678
21679        /**
21680         * Global to the view hierarchy used as a temporary for dealing with
21681         * x/y points in the transparent region computations.
21682         */
21683        final int[] mTransparentLocation = new int[2];
21684
21685        /**
21686         * Global to the view hierarchy used as a temporary for dealing with
21687         * x/y points in the ViewGroup.invalidateChild implementation.
21688         */
21689        final int[] mInvalidateChildLocation = new int[2];
21690
21691        /**
21692         * Global to the view hierarchy used as a temporary for dealng with
21693         * computing absolute on-screen location.
21694         */
21695        final int[] mTmpLocation = new int[2];
21696
21697        /**
21698         * Global to the view hierarchy used as a temporary for dealing with
21699         * x/y location when view is transformed.
21700         */
21701        final float[] mTmpTransformLocation = new float[2];
21702
21703        /**
21704         * The view tree observer used to dispatch global events like
21705         * layout, pre-draw, touch mode change, etc.
21706         */
21707        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
21708
21709        /**
21710         * A Canvas used by the view hierarchy to perform bitmap caching.
21711         */
21712        Canvas mCanvas;
21713
21714        /**
21715         * The view root impl.
21716         */
21717        final ViewRootImpl mViewRootImpl;
21718
21719        /**
21720         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
21721         * handler can be used to pump events in the UI events queue.
21722         */
21723        final Handler mHandler;
21724
21725        /**
21726         * Temporary for use in computing invalidate rectangles while
21727         * calling up the hierarchy.
21728         */
21729        final Rect mTmpInvalRect = new Rect();
21730
21731        /**
21732         * Temporary for use in computing hit areas with transformed views
21733         */
21734        final RectF mTmpTransformRect = new RectF();
21735
21736        /**
21737         * Temporary for use in computing hit areas with transformed views
21738         */
21739        final RectF mTmpTransformRect1 = new RectF();
21740
21741        /**
21742         * Temporary list of rectanges.
21743         */
21744        final List<RectF> mTmpRectList = new ArrayList<>();
21745
21746        /**
21747         * Temporary for use in transforming invalidation rect
21748         */
21749        final Matrix mTmpMatrix = new Matrix();
21750
21751        /**
21752         * Temporary for use in transforming invalidation rect
21753         */
21754        final Transformation mTmpTransformation = new Transformation();
21755
21756        /**
21757         * Temporary for use in querying outlines from OutlineProviders
21758         */
21759        final Outline mTmpOutline = new Outline();
21760
21761        /**
21762         * Temporary list for use in collecting focusable descendents of a view.
21763         */
21764        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
21765
21766        /**
21767         * The id of the window for accessibility purposes.
21768         */
21769        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
21770
21771        /**
21772         * Flags related to accessibility processing.
21773         *
21774         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
21775         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
21776         */
21777        int mAccessibilityFetchFlags;
21778
21779        /**
21780         * The drawable for highlighting accessibility focus.
21781         */
21782        Drawable mAccessibilityFocusDrawable;
21783
21784        /**
21785         * Show where the margins, bounds and layout bounds are for each view.
21786         */
21787        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
21788
21789        /**
21790         * Point used to compute visible regions.
21791         */
21792        final Point mPoint = new Point();
21793
21794        /**
21795         * Used to track which View originated a requestLayout() call, used when
21796         * requestLayout() is called during layout.
21797         */
21798        View mViewRequestingLayout;
21799
21800        /**
21801         * Creates a new set of attachment information with the specified
21802         * events handler and thread.
21803         *
21804         * @param handler the events handler the view must use
21805         */
21806        AttachInfo(IWindowSession session, IWindow window, Display display,
21807                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
21808            mSession = session;
21809            mWindow = window;
21810            mWindowToken = window.asBinder();
21811            mDisplay = display;
21812            mViewRootImpl = viewRootImpl;
21813            mHandler = handler;
21814            mRootCallbacks = effectPlayer;
21815        }
21816    }
21817
21818    /**
21819     * <p>ScrollabilityCache holds various fields used by a View when scrolling
21820     * is supported. This avoids keeping too many unused fields in most
21821     * instances of View.</p>
21822     */
21823    private static class ScrollabilityCache implements Runnable {
21824
21825        /**
21826         * Scrollbars are not visible
21827         */
21828        public static final int OFF = 0;
21829
21830        /**
21831         * Scrollbars are visible
21832         */
21833        public static final int ON = 1;
21834
21835        /**
21836         * Scrollbars are fading away
21837         */
21838        public static final int FADING = 2;
21839
21840        public boolean fadeScrollBars;
21841
21842        public int fadingEdgeLength;
21843        public int scrollBarDefaultDelayBeforeFade;
21844        public int scrollBarFadeDuration;
21845
21846        public int scrollBarSize;
21847        public ScrollBarDrawable scrollBar;
21848        public float[] interpolatorValues;
21849        public View host;
21850
21851        public final Paint paint;
21852        public final Matrix matrix;
21853        public Shader shader;
21854
21855        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
21856
21857        private static final float[] OPAQUE = { 255 };
21858        private static final float[] TRANSPARENT = { 0.0f };
21859
21860        /**
21861         * When fading should start. This time moves into the future every time
21862         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
21863         */
21864        public long fadeStartTime;
21865
21866
21867        /**
21868         * The current state of the scrollbars: ON, OFF, or FADING
21869         */
21870        public int state = OFF;
21871
21872        private int mLastColor;
21873
21874        public ScrollabilityCache(ViewConfiguration configuration, View host) {
21875            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
21876            scrollBarSize = configuration.getScaledScrollBarSize();
21877            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
21878            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
21879
21880            paint = new Paint();
21881            matrix = new Matrix();
21882            // use use a height of 1, and then wack the matrix each time we
21883            // actually use it.
21884            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21885            paint.setShader(shader);
21886            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21887
21888            this.host = host;
21889        }
21890
21891        public void setFadeColor(int color) {
21892            if (color != mLastColor) {
21893                mLastColor = color;
21894
21895                if (color != 0) {
21896                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
21897                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
21898                    paint.setShader(shader);
21899                    // Restore the default transfer mode (src_over)
21900                    paint.setXfermode(null);
21901                } else {
21902                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21903                    paint.setShader(shader);
21904                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21905                }
21906            }
21907        }
21908
21909        public void run() {
21910            long now = AnimationUtils.currentAnimationTimeMillis();
21911            if (now >= fadeStartTime) {
21912
21913                // the animation fades the scrollbars out by changing
21914                // the opacity (alpha) from fully opaque to fully
21915                // transparent
21916                int nextFrame = (int) now;
21917                int framesCount = 0;
21918
21919                Interpolator interpolator = scrollBarInterpolator;
21920
21921                // Start opaque
21922                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
21923
21924                // End transparent
21925                nextFrame += scrollBarFadeDuration;
21926                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
21927
21928                state = FADING;
21929
21930                // Kick off the fade animation
21931                host.invalidate(true);
21932            }
21933        }
21934    }
21935
21936    /**
21937     * Resuable callback for sending
21938     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
21939     */
21940    private class SendViewScrolledAccessibilityEvent implements Runnable {
21941        public volatile boolean mIsPending;
21942
21943        public void run() {
21944            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
21945            mIsPending = false;
21946        }
21947    }
21948
21949    /**
21950     * <p>
21951     * This class represents a delegate that can be registered in a {@link View}
21952     * to enhance accessibility support via composition rather via inheritance.
21953     * It is specifically targeted to widget developers that extend basic View
21954     * classes i.e. classes in package android.view, that would like their
21955     * applications to be backwards compatible.
21956     * </p>
21957     * <div class="special reference">
21958     * <h3>Developer Guides</h3>
21959     * <p>For more information about making applications accessible, read the
21960     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
21961     * developer guide.</p>
21962     * </div>
21963     * <p>
21964     * A scenario in which a developer would like to use an accessibility delegate
21965     * is overriding a method introduced in a later API version then the minimal API
21966     * version supported by the application. For example, the method
21967     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
21968     * in API version 4 when the accessibility APIs were first introduced. If a
21969     * developer would like his application to run on API version 4 devices (assuming
21970     * all other APIs used by the application are version 4 or lower) and take advantage
21971     * of this method, instead of overriding the method which would break the application's
21972     * backwards compatibility, he can override the corresponding method in this
21973     * delegate and register the delegate in the target View if the API version of
21974     * the system is high enough i.e. the API version is same or higher to the API
21975     * version that introduced
21976     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
21977     * </p>
21978     * <p>
21979     * Here is an example implementation:
21980     * </p>
21981     * <code><pre><p>
21982     * if (Build.VERSION.SDK_INT >= 14) {
21983     *     // If the API version is equal of higher than the version in
21984     *     // which onInitializeAccessibilityNodeInfo was introduced we
21985     *     // register a delegate with a customized implementation.
21986     *     View view = findViewById(R.id.view_id);
21987     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
21988     *         public void onInitializeAccessibilityNodeInfo(View host,
21989     *                 AccessibilityNodeInfo info) {
21990     *             // Let the default implementation populate the info.
21991     *             super.onInitializeAccessibilityNodeInfo(host, info);
21992     *             // Set some other information.
21993     *             info.setEnabled(host.isEnabled());
21994     *         }
21995     *     });
21996     * }
21997     * </code></pre></p>
21998     * <p>
21999     * This delegate contains methods that correspond to the accessibility methods
22000     * in View. If a delegate has been specified the implementation in View hands
22001     * off handling to the corresponding method in this delegate. The default
22002     * implementation the delegate methods behaves exactly as the corresponding
22003     * method in View for the case of no accessibility delegate been set. Hence,
22004     * to customize the behavior of a View method, clients can override only the
22005     * corresponding delegate method without altering the behavior of the rest
22006     * accessibility related methods of the host view.
22007     * </p>
22008     */
22009    public static class AccessibilityDelegate {
22010
22011        /**
22012         * Sends an accessibility event of the given type. If accessibility is not
22013         * enabled this method has no effect.
22014         * <p>
22015         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
22016         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
22017         * been set.
22018         * </p>
22019         *
22020         * @param host The View hosting the delegate.
22021         * @param eventType The type of the event to send.
22022         *
22023         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
22024         */
22025        public void sendAccessibilityEvent(View host, int eventType) {
22026            host.sendAccessibilityEventInternal(eventType);
22027        }
22028
22029        /**
22030         * Performs the specified accessibility action on the view. For
22031         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
22032         * <p>
22033         * The default implementation behaves as
22034         * {@link View#performAccessibilityAction(int, Bundle)
22035         *  View#performAccessibilityAction(int, Bundle)} for the case of
22036         *  no accessibility delegate been set.
22037         * </p>
22038         *
22039         * @param action The action to perform.
22040         * @return Whether the action was performed.
22041         *
22042         * @see View#performAccessibilityAction(int, Bundle)
22043         *      View#performAccessibilityAction(int, Bundle)
22044         */
22045        public boolean performAccessibilityAction(View host, int action, Bundle args) {
22046            return host.performAccessibilityActionInternal(action, args);
22047        }
22048
22049        /**
22050         * Sends an accessibility event. This method behaves exactly as
22051         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
22052         * empty {@link AccessibilityEvent} and does not perform a check whether
22053         * accessibility is enabled.
22054         * <p>
22055         * The default implementation behaves as
22056         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22057         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
22058         * the case of no accessibility delegate been set.
22059         * </p>
22060         *
22061         * @param host The View hosting the delegate.
22062         * @param event The event to send.
22063         *
22064         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22065         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22066         */
22067        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
22068            host.sendAccessibilityEventUncheckedInternal(event);
22069        }
22070
22071        /**
22072         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
22073         * to its children for adding their text content to the event.
22074         * <p>
22075         * The default implementation behaves as
22076         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22077         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
22078         * the case of no accessibility delegate been set.
22079         * </p>
22080         *
22081         * @param host The View hosting the delegate.
22082         * @param event The event.
22083         * @return True if the event population was completed.
22084         *
22085         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22086         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22087         */
22088        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22089            return host.dispatchPopulateAccessibilityEventInternal(event);
22090        }
22091
22092        /**
22093         * Gives a chance to the host View to populate the accessibility event with its
22094         * text content.
22095         * <p>
22096         * The default implementation behaves as
22097         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
22098         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
22099         * the case of no accessibility delegate been set.
22100         * </p>
22101         *
22102         * @param host The View hosting the delegate.
22103         * @param event The accessibility event which to populate.
22104         *
22105         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
22106         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
22107         */
22108        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22109            host.onPopulateAccessibilityEventInternal(event);
22110        }
22111
22112        /**
22113         * Initializes an {@link AccessibilityEvent} with information about the
22114         * the host View which is the event source.
22115         * <p>
22116         * The default implementation behaves as
22117         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
22118         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
22119         * the case of no accessibility delegate been set.
22120         * </p>
22121         *
22122         * @param host The View hosting the delegate.
22123         * @param event The event to initialize.
22124         *
22125         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
22126         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
22127         */
22128        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
22129            host.onInitializeAccessibilityEventInternal(event);
22130        }
22131
22132        /**
22133         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
22134         * <p>
22135         * The default implementation behaves as
22136         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22137         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
22138         * the case of no accessibility delegate been set.
22139         * </p>
22140         *
22141         * @param host The View hosting the delegate.
22142         * @param info The instance to initialize.
22143         *
22144         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22145         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22146         */
22147        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
22148            host.onInitializeAccessibilityNodeInfoInternal(info);
22149        }
22150
22151        /**
22152         * Called when a child of the host View has requested sending an
22153         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
22154         * to augment the event.
22155         * <p>
22156         * The default implementation behaves as
22157         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22158         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
22159         * the case of no accessibility delegate been set.
22160         * </p>
22161         *
22162         * @param host The View hosting the delegate.
22163         * @param child The child which requests sending the event.
22164         * @param event The event to be sent.
22165         * @return True if the event should be sent
22166         *
22167         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22168         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22169         */
22170        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
22171                AccessibilityEvent event) {
22172            return host.onRequestSendAccessibilityEventInternal(child, event);
22173        }
22174
22175        /**
22176         * Gets the provider for managing a virtual view hierarchy rooted at this View
22177         * and reported to {@link android.accessibilityservice.AccessibilityService}s
22178         * that explore the window content.
22179         * <p>
22180         * The default implementation behaves as
22181         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
22182         * the case of no accessibility delegate been set.
22183         * </p>
22184         *
22185         * @return The provider.
22186         *
22187         * @see AccessibilityNodeProvider
22188         */
22189        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
22190            return null;
22191        }
22192
22193        /**
22194         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
22195         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
22196         * This method is responsible for obtaining an accessibility node info from a
22197         * pool of reusable instances and calling
22198         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
22199         * view to initialize the former.
22200         * <p>
22201         * <strong>Note:</strong> The client is responsible for recycling the obtained
22202         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
22203         * creation.
22204         * </p>
22205         * <p>
22206         * The default implementation behaves as
22207         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
22208         * the case of no accessibility delegate been set.
22209         * </p>
22210         * @return A populated {@link AccessibilityNodeInfo}.
22211         *
22212         * @see AccessibilityNodeInfo
22213         *
22214         * @hide
22215         */
22216        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
22217            return host.createAccessibilityNodeInfoInternal();
22218        }
22219    }
22220
22221    private class MatchIdPredicate implements Predicate<View> {
22222        public int mId;
22223
22224        @Override
22225        public boolean apply(View view) {
22226            return (view.mID == mId);
22227        }
22228    }
22229
22230    private class MatchLabelForPredicate implements Predicate<View> {
22231        private int mLabeledId;
22232
22233        @Override
22234        public boolean apply(View view) {
22235            return (view.mLabelForId == mLabeledId);
22236        }
22237    }
22238
22239    private class SendViewStateChangedAccessibilityEvent implements Runnable {
22240        private int mChangeTypes = 0;
22241        private boolean mPosted;
22242        private boolean mPostedWithDelay;
22243        private long mLastEventTimeMillis;
22244
22245        @Override
22246        public void run() {
22247            mPosted = false;
22248            mPostedWithDelay = false;
22249            mLastEventTimeMillis = SystemClock.uptimeMillis();
22250            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
22251                final AccessibilityEvent event = AccessibilityEvent.obtain();
22252                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
22253                event.setContentChangeTypes(mChangeTypes);
22254                sendAccessibilityEventUnchecked(event);
22255            }
22256            mChangeTypes = 0;
22257        }
22258
22259        public void runOrPost(int changeType) {
22260            mChangeTypes |= changeType;
22261
22262            // If this is a live region or the child of a live region, collect
22263            // all events from this frame and send them on the next frame.
22264            if (inLiveRegion()) {
22265                // If we're already posted with a delay, remove that.
22266                if (mPostedWithDelay) {
22267                    removeCallbacks(this);
22268                    mPostedWithDelay = false;
22269                }
22270                // Only post if we're not already posted.
22271                if (!mPosted) {
22272                    post(this);
22273                    mPosted = true;
22274                }
22275                return;
22276            }
22277
22278            if (mPosted) {
22279                return;
22280            }
22281
22282            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
22283            final long minEventIntevalMillis =
22284                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
22285            if (timeSinceLastMillis >= minEventIntevalMillis) {
22286                removeCallbacks(this);
22287                run();
22288            } else {
22289                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
22290                mPostedWithDelay = true;
22291            }
22292        }
22293    }
22294
22295    private boolean inLiveRegion() {
22296        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22297            return true;
22298        }
22299
22300        ViewParent parent = getParent();
22301        while (parent instanceof View) {
22302            if (((View) parent).getAccessibilityLiveRegion()
22303                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22304                return true;
22305            }
22306            parent = parent.getParent();
22307        }
22308
22309        return false;
22310    }
22311
22312    /**
22313     * Dump all private flags in readable format, useful for documentation and
22314     * sanity checking.
22315     */
22316    private static void dumpFlags() {
22317        final HashMap<String, String> found = Maps.newHashMap();
22318        try {
22319            for (Field field : View.class.getDeclaredFields()) {
22320                final int modifiers = field.getModifiers();
22321                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
22322                    if (field.getType().equals(int.class)) {
22323                        final int value = field.getInt(null);
22324                        dumpFlag(found, field.getName(), value);
22325                    } else if (field.getType().equals(int[].class)) {
22326                        final int[] values = (int[]) field.get(null);
22327                        for (int i = 0; i < values.length; i++) {
22328                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
22329                        }
22330                    }
22331                }
22332            }
22333        } catch (IllegalAccessException e) {
22334            throw new RuntimeException(e);
22335        }
22336
22337        final ArrayList<String> keys = Lists.newArrayList();
22338        keys.addAll(found.keySet());
22339        Collections.sort(keys);
22340        for (String key : keys) {
22341            Log.d(VIEW_LOG_TAG, found.get(key));
22342        }
22343    }
22344
22345    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
22346        // Sort flags by prefix, then by bits, always keeping unique keys
22347        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
22348        final int prefix = name.indexOf('_');
22349        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
22350        final String output = bits + " " + name;
22351        found.put(key, output);
22352    }
22353
22354    /** {@hide} */
22355    public void encode(@NonNull ViewHierarchyEncoder stream) {
22356        stream.beginObject(this);
22357        encodeProperties(stream);
22358        stream.endObject();
22359    }
22360
22361    /** {@hide} */
22362    @CallSuper
22363    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
22364        Object resolveId = ViewDebug.resolveId(getContext(), mID);
22365        if (resolveId instanceof String) {
22366            stream.addProperty("id", (String) resolveId);
22367        } else {
22368            stream.addProperty("id", mID);
22369        }
22370
22371        stream.addProperty("misc:transformation.alpha",
22372                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
22373        stream.addProperty("misc:transitionName", getTransitionName());
22374
22375        // layout
22376        stream.addProperty("layout:left", mLeft);
22377        stream.addProperty("layout:right", mRight);
22378        stream.addProperty("layout:top", mTop);
22379        stream.addProperty("layout:bottom", mBottom);
22380        stream.addProperty("layout:width", getWidth());
22381        stream.addProperty("layout:height", getHeight());
22382        stream.addProperty("layout:layoutDirection", getLayoutDirection());
22383        stream.addProperty("layout:layoutRtl", isLayoutRtl());
22384        stream.addProperty("layout:hasTransientState", hasTransientState());
22385        stream.addProperty("layout:baseline", getBaseline());
22386
22387        // layout params
22388        ViewGroup.LayoutParams layoutParams = getLayoutParams();
22389        if (layoutParams != null) {
22390            stream.addPropertyKey("layoutParams");
22391            layoutParams.encode(stream);
22392        }
22393
22394        // scrolling
22395        stream.addProperty("scrolling:scrollX", mScrollX);
22396        stream.addProperty("scrolling:scrollY", mScrollY);
22397
22398        // padding
22399        stream.addProperty("padding:paddingLeft", mPaddingLeft);
22400        stream.addProperty("padding:paddingRight", mPaddingRight);
22401        stream.addProperty("padding:paddingTop", mPaddingTop);
22402        stream.addProperty("padding:paddingBottom", mPaddingBottom);
22403        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
22404        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
22405        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
22406        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
22407        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
22408
22409        // measurement
22410        stream.addProperty("measurement:minHeight", mMinHeight);
22411        stream.addProperty("measurement:minWidth", mMinWidth);
22412        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
22413        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
22414
22415        // drawing
22416        stream.addProperty("drawing:elevation", getElevation());
22417        stream.addProperty("drawing:translationX", getTranslationX());
22418        stream.addProperty("drawing:translationY", getTranslationY());
22419        stream.addProperty("drawing:translationZ", getTranslationZ());
22420        stream.addProperty("drawing:rotation", getRotation());
22421        stream.addProperty("drawing:rotationX", getRotationX());
22422        stream.addProperty("drawing:rotationY", getRotationY());
22423        stream.addProperty("drawing:scaleX", getScaleX());
22424        stream.addProperty("drawing:scaleY", getScaleY());
22425        stream.addProperty("drawing:pivotX", getPivotX());
22426        stream.addProperty("drawing:pivotY", getPivotY());
22427        stream.addProperty("drawing:opaque", isOpaque());
22428        stream.addProperty("drawing:alpha", getAlpha());
22429        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
22430        stream.addProperty("drawing:shadow", hasShadow());
22431        stream.addProperty("drawing:solidColor", getSolidColor());
22432        stream.addProperty("drawing:layerType", mLayerType);
22433        stream.addProperty("drawing:willNotDraw", willNotDraw());
22434        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
22435        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
22436        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
22437        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
22438
22439        // focus
22440        stream.addProperty("focus:hasFocus", hasFocus());
22441        stream.addProperty("focus:isFocused", isFocused());
22442        stream.addProperty("focus:isFocusable", isFocusable());
22443        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
22444
22445        stream.addProperty("misc:clickable", isClickable());
22446        stream.addProperty("misc:pressed", isPressed());
22447        stream.addProperty("misc:selected", isSelected());
22448        stream.addProperty("misc:touchMode", isInTouchMode());
22449        stream.addProperty("misc:hovered", isHovered());
22450        stream.addProperty("misc:activated", isActivated());
22451
22452        stream.addProperty("misc:visibility", getVisibility());
22453        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
22454        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
22455
22456        stream.addProperty("misc:enabled", isEnabled());
22457        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
22458        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
22459
22460        // theme attributes
22461        Resources.Theme theme = getContext().getTheme();
22462        if (theme != null) {
22463            stream.addPropertyKey("theme");
22464            theme.encode(stream);
22465        }
22466
22467        // view attribute information
22468        int n = mAttributes != null ? mAttributes.length : 0;
22469        stream.addProperty("meta:__attrCount__", n/2);
22470        for (int i = 0; i < n; i += 2) {
22471            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
22472        }
22473
22474        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
22475
22476        // text
22477        stream.addProperty("text:textDirection", getTextDirection());
22478        stream.addProperty("text:textAlignment", getTextAlignment());
22479
22480        // accessibility
22481        CharSequence contentDescription = getContentDescription();
22482        stream.addProperty("accessibility:contentDescription",
22483                contentDescription == null ? "" : contentDescription.toString());
22484        stream.addProperty("accessibility:labelFor", getLabelFor());
22485        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
22486    }
22487}
22488